mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 08:46:43 +07:00
Merge branch 'upstream'
This commit is contained in:
commit
b194b4250c
@ -131,3 +131,47 @@ Netlink itself is not reliable protocol, that means that messages can
|
|||||||
be lost due to memory pressure or process' receiving queue overflowed,
|
be lost due to memory pressure or process' receiving queue overflowed,
|
||||||
so caller is warned must be prepared. That is why struct cn_msg [main
|
so caller is warned must be prepared. That is why struct cn_msg [main
|
||||||
connector's message header] contains u32 seq and u32 ack fields.
|
connector's message header] contains u32 seq and u32 ack fields.
|
||||||
|
|
||||||
|
/*****************************************/
|
||||||
|
Userspace usage.
|
||||||
|
/*****************************************/
|
||||||
|
2.6.14 has a new netlink socket implementation, which by default does not
|
||||||
|
allow to send data to netlink groups other than 1.
|
||||||
|
So, if to use netlink socket (for example using connector)
|
||||||
|
with different group number userspace application must subscribe to
|
||||||
|
that group. It can be achieved by following pseudocode:
|
||||||
|
|
||||||
|
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||||
|
|
||||||
|
l_local.nl_family = AF_NETLINK;
|
||||||
|
l_local.nl_groups = 12345;
|
||||||
|
l_local.nl_pid = 0;
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
|
||||||
|
perror("bind");
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int on = l_local.nl_groups;
|
||||||
|
setsockopt(s, 270, 1, &on, sizeof(on));
|
||||||
|
}
|
||||||
|
|
||||||
|
Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
|
||||||
|
option. To drop multicast subscription one should call above socket option
|
||||||
|
with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
|
||||||
|
|
||||||
|
2.6.14 netlink code only allows to select a group which is less or equal to
|
||||||
|
the maximum group number, which is used at netlink_kernel_create() time.
|
||||||
|
In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use
|
||||||
|
group number 12345, you must increment CN_NETLINK_USERS to that number.
|
||||||
|
Additional 0xf numbers are allocated to be used by non-in-kernel users.
|
||||||
|
|
||||||
|
Due to this limitation, group 0xffffffff does not work now, so one can
|
||||||
|
not use add/remove connector's group notifications, but as far as I know,
|
||||||
|
only cn_test.c test module used it.
|
||||||
|
|
||||||
|
Some work in netlink area is still being done, so things can be changed in
|
||||||
|
2.6.15 timeframe, if it will happen, documentation will be updated for that
|
||||||
|
kernel.
|
||||||
|
@ -35,6 +35,7 @@ The driver load creates the following directories under the /sys file system.
|
|||||||
/sys/class/firmware/dell_rbu/data
|
/sys/class/firmware/dell_rbu/data
|
||||||
/sys/devices/platform/dell_rbu/image_type
|
/sys/devices/platform/dell_rbu/image_type
|
||||||
/sys/devices/platform/dell_rbu/data
|
/sys/devices/platform/dell_rbu/data
|
||||||
|
/sys/devices/platform/dell_rbu/packet_size
|
||||||
|
|
||||||
The driver supports two types of update mechanism; monolithic and packetized.
|
The driver supports two types of update mechanism; monolithic and packetized.
|
||||||
These update mechanism depends upon the BIOS currently running on the system.
|
These update mechanism depends upon the BIOS currently running on the system.
|
||||||
@ -47,8 +48,26 @@ By default the driver uses monolithic memory for the update type. This can be
|
|||||||
changed to packets during the driver load time by specifying the load
|
changed to packets during the driver load time by specifying the load
|
||||||
parameter image_type=packet. This can also be changed later as below
|
parameter image_type=packet. This can also be changed later as below
|
||||||
echo packet > /sys/devices/platform/dell_rbu/image_type
|
echo packet > /sys/devices/platform/dell_rbu/image_type
|
||||||
Also echoing either mono ,packet or init in to image_type will free up the
|
|
||||||
memory allocated by the driver.
|
In packet update mode the packet size has to be given before any packets can
|
||||||
|
be downloaded. It is done as below
|
||||||
|
echo XXXX > /sys/devices/platform/dell_rbu/packet_size
|
||||||
|
In the packet update mechanism, the user neesd to create a new file having
|
||||||
|
packets of data arranged back to back. It can be done as follows
|
||||||
|
The user creates packets header, gets the chunk of the BIOS image and
|
||||||
|
placs it next to the packetheader; now, the packetheader + BIOS image chunk
|
||||||
|
added to geather should match the specified packet_size. This makes one
|
||||||
|
packet, the user needs to create more such packets out of the entire BIOS
|
||||||
|
image file and then arrange all these packets back to back in to one single
|
||||||
|
file.
|
||||||
|
This file is then copied to /sys/class/firmware/dell_rbu/data.
|
||||||
|
Once this file gets to the driver, the driver extracts packet_size data from
|
||||||
|
the file and spreads it accross the physical memory in contiguous packet_sized
|
||||||
|
space.
|
||||||
|
This method makes sure that all the packets get to the driver in a single operation.
|
||||||
|
|
||||||
|
In monolithic update the user simply get the BIOS image (.hdr file) and copies
|
||||||
|
to the data file as is without any change to the BIOS image itself.
|
||||||
|
|
||||||
Do the steps below to download the BIOS image.
|
Do the steps below to download the BIOS image.
|
||||||
1) echo 1 > /sys/class/firmware/dell_rbu/loading
|
1) echo 1 > /sys/class/firmware/dell_rbu/loading
|
||||||
@ -58,7 +77,10 @@ Do the steps below to download the BIOS image.
|
|||||||
The /sys/class/firmware/dell_rbu/ entries will remain till the following is
|
The /sys/class/firmware/dell_rbu/ entries will remain till the following is
|
||||||
done.
|
done.
|
||||||
echo -1 > /sys/class/firmware/dell_rbu/loading.
|
echo -1 > /sys/class/firmware/dell_rbu/loading.
|
||||||
Until this step is completed the drivr cannot be unloaded.
|
Until this step is completed the driver cannot be unloaded.
|
||||||
|
Also echoing either mono ,packet or init in to image_type will free up the
|
||||||
|
memory allocated by the driver.
|
||||||
|
|
||||||
If an user by accident executes steps 1 and 3 above without executing step 2;
|
If an user by accident executes steps 1 and 3 above without executing step 2;
|
||||||
it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
|
it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
|
||||||
The entries can be recreated by doing the following
|
The entries can be recreated by doing the following
|
||||||
@ -66,15 +88,11 @@ echo init > /sys/devices/platform/dell_rbu/image_type
|
|||||||
NOTE: echoing init in image_type does not change it original value.
|
NOTE: echoing init in image_type does not change it original value.
|
||||||
|
|
||||||
Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
|
Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
|
||||||
read back the image downloaded. This is useful in case of packet update
|
read back the image downloaded.
|
||||||
mechanism where the above steps 1,2,3 will repeated for every packet.
|
|
||||||
By reading the /sys/devices/platform/dell_rbu/data file all packet data
|
|
||||||
downloaded can be verified in a single file.
|
|
||||||
The packets are arranged in this file one after the other in a FIFO order.
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
This driver requires a patch for firmware_class.c which has the addition
|
This driver requires a patch for firmware_class.c which has the modified
|
||||||
of request_firmware_nowait_nohotplug function to wortk
|
request_firmware_nowait function.
|
||||||
Also after updating the BIOS image an user mdoe application neeeds to execute
|
Also after updating the BIOS image an user mdoe application neeeds to execute
|
||||||
code which message the BIOS update request to the BIOS. So on the next reboot
|
code which message the BIOS update request to the BIOS. So on the next reboot
|
||||||
the BIOS knows about the new image downloaded and it updates it self.
|
the BIOS knows about the new image downloaded and it updates it self.
|
||||||
|
161
Documentation/keys-request-key.txt
Normal file
161
Documentation/keys-request-key.txt
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
===================
|
||||||
|
KEY REQUEST SERVICE
|
||||||
|
===================
|
||||||
|
|
||||||
|
The key request service is part of the key retention service (refer to
|
||||||
|
Documentation/keys.txt). This document explains more fully how that the
|
||||||
|
requesting algorithm works.
|
||||||
|
|
||||||
|
The process starts by either the kernel requesting a service by calling
|
||||||
|
request_key():
|
||||||
|
|
||||||
|
struct key *request_key(const struct key_type *type,
|
||||||
|
const char *description,
|
||||||
|
const char *callout_string);
|
||||||
|
|
||||||
|
Or by userspace invoking the request_key system call:
|
||||||
|
|
||||||
|
key_serial_t request_key(const char *type,
|
||||||
|
const char *description,
|
||||||
|
const char *callout_info,
|
||||||
|
key_serial_t dest_keyring);
|
||||||
|
|
||||||
|
The main difference between the two access points is that the in-kernel
|
||||||
|
interface does not need to link the key to a keyring to prevent it from being
|
||||||
|
immediately destroyed. The kernel interface returns a pointer directly to the
|
||||||
|
key, and it's up to the caller to destroy the key.
|
||||||
|
|
||||||
|
The userspace interface links the key to a keyring associated with the process
|
||||||
|
to prevent the key from going away, and returns the serial number of the key to
|
||||||
|
the caller.
|
||||||
|
|
||||||
|
|
||||||
|
===========
|
||||||
|
THE PROCESS
|
||||||
|
===========
|
||||||
|
|
||||||
|
A request proceeds in the following manner:
|
||||||
|
|
||||||
|
(1) Process A calls request_key() [the userspace syscall calls the kernel
|
||||||
|
interface].
|
||||||
|
|
||||||
|
(2) request_key() searches the process's subscribed keyrings to see if there's
|
||||||
|
a suitable key there. If there is, it returns the key. If there isn't, and
|
||||||
|
callout_info is not set, an error is returned. Otherwise the process
|
||||||
|
proceeds to the next step.
|
||||||
|
|
||||||
|
(3) request_key() sees that A doesn't have the desired key yet, so it creates
|
||||||
|
two things:
|
||||||
|
|
||||||
|
(a) An uninstantiated key U of requested type and description.
|
||||||
|
|
||||||
|
(b) An authorisation key V that refers to key U and notes that process A
|
||||||
|
is the context in which key U should be instantiated and secured, and
|
||||||
|
from which associated key requests may be satisfied.
|
||||||
|
|
||||||
|
(4) request_key() then forks and executes /sbin/request-key with a new session
|
||||||
|
keyring that contains a link to auth key V.
|
||||||
|
|
||||||
|
(5) /sbin/request-key execs an appropriate program to perform the actual
|
||||||
|
instantiation.
|
||||||
|
|
||||||
|
(6) The program may want to access another key from A's context (say a
|
||||||
|
Kerberos TGT key). It just requests the appropriate key, and the keyring
|
||||||
|
search notes that the session keyring has auth key V in its bottom level.
|
||||||
|
|
||||||
|
This will permit it to then search the keyrings of process A with the
|
||||||
|
UID, GID, groups and security info of process A as if it was process A,
|
||||||
|
and come up with key W.
|
||||||
|
|
||||||
|
(7) The program then does what it must to get the data with which to
|
||||||
|
instantiate key U, using key W as a reference (perhaps it contacts a
|
||||||
|
Kerberos server using the TGT) and then instantiates key U.
|
||||||
|
|
||||||
|
(8) Upon instantiating key U, auth key V is automatically revoked so that it
|
||||||
|
may not be used again.
|
||||||
|
|
||||||
|
(9) The program then exits 0 and request_key() deletes key V and returns key
|
||||||
|
U to the caller.
|
||||||
|
|
||||||
|
This also extends further. If key W (step 5 above) didn't exist, key W would be
|
||||||
|
created uninstantiated, another auth key (X) would be created [as per step 3]
|
||||||
|
and another copy of /sbin/request-key spawned [as per step 4]; but the context
|
||||||
|
specified by auth key X will still be process A, as it was in auth key V.
|
||||||
|
|
||||||
|
This is because process A's keyrings can't simply be attached to
|
||||||
|
/sbin/request-key at the appropriate places because (a) execve will discard two
|
||||||
|
of them, and (b) it requires the same UID/GID/Groups all the way through.
|
||||||
|
|
||||||
|
|
||||||
|
======================
|
||||||
|
NEGATIVE INSTANTIATION
|
||||||
|
======================
|
||||||
|
|
||||||
|
Rather than instantiating a key, it is possible for the possessor of an
|
||||||
|
authorisation key to negatively instantiate a key that's under construction.
|
||||||
|
This is a short duration placeholder that causes any attempt at re-requesting
|
||||||
|
the key whilst it exists to fail with error ENOKEY.
|
||||||
|
|
||||||
|
This is provided to prevent excessive repeated spawning of /sbin/request-key
|
||||||
|
processes for a key that will never be obtainable.
|
||||||
|
|
||||||
|
Should the /sbin/request-key process exit anything other than 0 or die on a
|
||||||
|
signal, the key under construction will be automatically negatively
|
||||||
|
instantiated for a short amount of time.
|
||||||
|
|
||||||
|
|
||||||
|
====================
|
||||||
|
THE SEARCH ALGORITHM
|
||||||
|
====================
|
||||||
|
|
||||||
|
A search of any particular keyring proceeds in the following fashion:
|
||||||
|
|
||||||
|
(1) When the key management code searches for a key (keyring_search_aux) it
|
||||||
|
firstly calls key_permission(SEARCH) on the keyring it's starting with,
|
||||||
|
if this denies permission, it doesn't search further.
|
||||||
|
|
||||||
|
(2) It considers all the non-keyring keys within that keyring and, if any key
|
||||||
|
matches the criteria specified, calls key_permission(SEARCH) on it to see
|
||||||
|
if the key is allowed to be found. If it is, that key is returned; if
|
||||||
|
not, the search continues, and the error code is retained if of higher
|
||||||
|
priority than the one currently set.
|
||||||
|
|
||||||
|
(3) It then considers all the keyring-type keys in the keyring it's currently
|
||||||
|
searching. It calls key_permission(SEARCH) on each keyring, and if this
|
||||||
|
grants permission, it recurses, executing steps (2) and (3) on that
|
||||||
|
keyring.
|
||||||
|
|
||||||
|
The process stops immediately a valid key is found with permission granted to
|
||||||
|
use it. Any error from a previous match attempt is discarded and the key is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
When search_process_keyrings() is invoked, it performs the following searches
|
||||||
|
until one succeeds:
|
||||||
|
|
||||||
|
(1) If extant, the process's thread keyring is searched.
|
||||||
|
|
||||||
|
(2) If extant, the process's process keyring is searched.
|
||||||
|
|
||||||
|
(3) The process's session keyring is searched.
|
||||||
|
|
||||||
|
(4) If the process has a request_key() authorisation key in its session
|
||||||
|
keyring then:
|
||||||
|
|
||||||
|
(a) If extant, the calling process's thread keyring is searched.
|
||||||
|
|
||||||
|
(b) If extant, the calling process's process keyring is searched.
|
||||||
|
|
||||||
|
(c) The calling process's session keyring is searched.
|
||||||
|
|
||||||
|
The moment one succeeds, all pending errors are discarded and the found key is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
Only if all these fail does the whole thing fail with the highest priority
|
||||||
|
error. Note that several errors may have come from LSM.
|
||||||
|
|
||||||
|
The error priority is:
|
||||||
|
|
||||||
|
EKEYREVOKED > EKEYEXPIRED > ENOKEY
|
||||||
|
|
||||||
|
EACCES/EPERM are only returned on a direct search of a specific keyring where
|
||||||
|
the basal keyring does not grant Search permission.
|
@ -361,6 +361,8 @@ The main syscalls are:
|
|||||||
/sbin/request-key will be invoked in an attempt to obtain a key. The
|
/sbin/request-key will be invoked in an attempt to obtain a key. The
|
||||||
callout_info string will be passed as an argument to the program.
|
callout_info string will be passed as an argument to the program.
|
||||||
|
|
||||||
|
See also Documentation/keys-request-key.txt.
|
||||||
|
|
||||||
|
|
||||||
The keyctl syscall functions are:
|
The keyctl syscall functions are:
|
||||||
|
|
||||||
@ -533,8 +535,8 @@ The keyctl syscall functions are:
|
|||||||
|
|
||||||
(*) Read the payload data from a key:
|
(*) Read the payload data from a key:
|
||||||
|
|
||||||
key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer,
|
long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
|
|
||||||
This function attempts to read the payload data from the specified key
|
This function attempts to read the payload data from the specified key
|
||||||
into the buffer. The process must have read permission on the key to
|
into the buffer. The process must have read permission on the key to
|
||||||
@ -555,9 +557,9 @@ The keyctl syscall functions are:
|
|||||||
|
|
||||||
(*) Instantiate a partially constructed key.
|
(*) Instantiate a partially constructed key.
|
||||||
|
|
||||||
key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
|
long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
|
||||||
const void *payload, size_t plen,
|
const void *payload, size_t plen,
|
||||||
key_serial_t keyring);
|
key_serial_t keyring);
|
||||||
|
|
||||||
If the kernel calls back to userspace to complete the instantiation of a
|
If the kernel calls back to userspace to complete the instantiation of a
|
||||||
key, userspace should use this call to supply data for the key before the
|
key, userspace should use this call to supply data for the key before the
|
||||||
@ -576,8 +578,8 @@ The keyctl syscall functions are:
|
|||||||
|
|
||||||
(*) Negatively instantiate a partially constructed key.
|
(*) Negatively instantiate a partially constructed key.
|
||||||
|
|
||||||
key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key,
|
long keyctl(KEYCTL_NEGATE, key_serial_t key,
|
||||||
unsigned timeout, key_serial_t keyring);
|
unsigned timeout, key_serial_t keyring);
|
||||||
|
|
||||||
If the kernel calls back to userspace to complete the instantiation of a
|
If the kernel calls back to userspace to complete the instantiation of a
|
||||||
key, userspace should use this call mark the key as negative before the
|
key, userspace should use this call mark the key as negative before the
|
||||||
@ -688,6 +690,8 @@ payload contents" for more information.
|
|||||||
If successful, the key will have been attached to the default keyring for
|
If successful, the key will have been attached to the default keyring for
|
||||||
implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
|
implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
|
||||||
|
|
||||||
|
See also Documentation/keys-request-key.txt.
|
||||||
|
|
||||||
|
|
||||||
(*) When it is no longer required, the key should be released using:
|
(*) When it is no longer required, the key should be released using:
|
||||||
|
|
||||||
|
@ -1618,6 +1618,13 @@ M: vandrove@vc.cvut.cz
|
|||||||
L: linux-fbdev-devel@lists.sourceforge.net
|
L: linux-fbdev-devel@lists.sourceforge.net
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
MEGARAID SCSI DRIVERS
|
||||||
|
P: Neela Syam Kolli
|
||||||
|
M: Neela.Kolli@engenio.com
|
||||||
|
S: linux-scsi@vger.kernel.org
|
||||||
|
W: http://megaraid.lsilogic.com
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
MEMORY TECHNOLOGY DEVICES
|
MEMORY TECHNOLOGY DEVICES
|
||||||
P: David Woodhouse
|
P: David Woodhouse
|
||||||
M: dwmw2@infradead.org
|
M: dwmw2@infradead.org
|
||||||
|
6
Makefile
6
Makefile
@ -1,7 +1,7 @@
|
|||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 14
|
SUBLEVEL = 14
|
||||||
EXTRAVERSION =-rc3
|
EXTRAVERSION =-rc4
|
||||||
NAME=Affluent Albatross
|
NAME=Affluent Albatross
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
@ -660,8 +660,10 @@ quiet_cmd_sysmap = SYSMAP
|
|||||||
# Link of vmlinux
|
# Link of vmlinux
|
||||||
# If CONFIG_KALLSYMS is set .version is already updated
|
# If CONFIG_KALLSYMS is set .version is already updated
|
||||||
# Generate System.map and verify that the content is consistent
|
# Generate System.map and verify that the content is consistent
|
||||||
|
# Use + in front of the vmlinux_version rule to silent warning with make -j2
|
||||||
|
# First command is ':' to allow us to use + in front of the rule
|
||||||
define rule_vmlinux__
|
define rule_vmlinux__
|
||||||
|
:
|
||||||
$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
|
$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
|
||||||
|
|
||||||
$(call cmd,vmlinux__)
|
$(call cmd,vmlinux__)
|
||||||
|
@ -53,7 +53,7 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
|
|||||||
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
|
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
|
||||||
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
|
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
|
||||||
tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
|
tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
|
||||||
tune-$(CONFIG_CPU_V6) :=-mtune=strongarm
|
tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
|
||||||
|
|
||||||
# Need -Uarm for gcc < 3.x
|
# Need -Uarm for gcc < 3.x
|
||||||
CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
|
CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
|
||||||
|
@ -26,6 +26,8 @@ struct scoop_pcmcia_dev *scoop_devs;
|
|||||||
struct scoop_dev {
|
struct scoop_dev {
|
||||||
void *base;
|
void *base;
|
||||||
spinlock_t scoop_lock;
|
spinlock_t scoop_lock;
|
||||||
|
unsigned short suspend_clr;
|
||||||
|
unsigned short suspend_set;
|
||||||
u32 scoop_gpwr;
|
u32 scoop_gpwr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -90,14 +92,24 @@ EXPORT_SYMBOL(reset_scoop);
|
|||||||
EXPORT_SYMBOL(read_scoop_reg);
|
EXPORT_SYMBOL(read_scoop_reg);
|
||||||
EXPORT_SYMBOL(write_scoop_reg);
|
EXPORT_SYMBOL(write_scoop_reg);
|
||||||
|
|
||||||
|
static void check_scoop_reg(struct scoop_dev *sdev)
|
||||||
|
{
|
||||||
|
unsigned short mcr;
|
||||||
|
|
||||||
|
mcr = SCOOP_REG(sdev->base, SCOOP_MCR);
|
||||||
|
if ((mcr & 0x100) == 0)
|
||||||
|
SCOOP_REG(sdev->base, SCOOP_MCR) = 0x0101;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
|
static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
|
||||||
{
|
{
|
||||||
if (level == SUSPEND_POWER_DOWN) {
|
if (level == SUSPEND_POWER_DOWN) {
|
||||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR);
|
check_scoop_reg(sdev);
|
||||||
SCOOP_REG(sdev->base,SCOOP_GPWR) = 0;
|
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
|
||||||
|
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -107,6 +119,7 @@ static int scoop_resume(struct device *dev, uint32_t level)
|
|||||||
if (level == RESUME_POWER_ON) {
|
if (level == RESUME_POWER_ON) {
|
||||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
check_scoop_reg(sdev);
|
||||||
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
|
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -151,6 +164,9 @@ int __init scoop_probe(struct device *dev)
|
|||||||
SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
|
SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
|
||||||
SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
|
SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
|
||||||
|
|
||||||
|
devptr->suspend_clr = inf->suspend_clr;
|
||||||
|
devptr->suspend_set = inf->suspend_set;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
888
arch/arm/configs/collie_defconfig
Normal file
888
arch/arm/configs/collie_defconfig
Normal file
@ -0,0 +1,888 @@
|
|||||||
|
#
|
||||||
|
# Automatically generated make config: don't edit
|
||||||
|
# Linux kernel version: 2.6.14-rc3
|
||||||
|
# Sun Oct 9 16:55:14 2005
|
||||||
|
#
|
||||||
|
CONFIG_ARM=y
|
||||||
|
CONFIG_MMU=y
|
||||||
|
CONFIG_UID16=y
|
||||||
|
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||||
|
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Code maturity level options
|
||||||
|
#
|
||||||
|
CONFIG_EXPERIMENTAL=y
|
||||||
|
# CONFIG_CLEAN_COMPILE is not set
|
||||||
|
CONFIG_BROKEN=y
|
||||||
|
CONFIG_BROKEN_ON_SMP=y
|
||||||
|
CONFIG_LOCK_KERNEL=y
|
||||||
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
|
|
||||||
|
#
|
||||||
|
# General setup
|
||||||
|
#
|
||||||
|
CONFIG_LOCALVERSION=""
|
||||||
|
CONFIG_LOCALVERSION_AUTO=y
|
||||||
|
CONFIG_SWAP=y
|
||||||
|
CONFIG_SYSVIPC=y
|
||||||
|
# CONFIG_POSIX_MQUEUE is not set
|
||||||
|
CONFIG_BSD_PROCESS_ACCT=y
|
||||||
|
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
|
||||||
|
CONFIG_SYSCTL=y
|
||||||
|
# CONFIG_AUDIT is not set
|
||||||
|
CONFIG_HOTPLUG=y
|
||||||
|
CONFIG_KOBJECT_UEVENT=y
|
||||||
|
# CONFIG_IKCONFIG is not set
|
||||||
|
CONFIG_INITRAMFS_SOURCE=""
|
||||||
|
CONFIG_EMBEDDED=y
|
||||||
|
CONFIG_KALLSYMS=y
|
||||||
|
# CONFIG_KALLSYMS_ALL is not set
|
||||||
|
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||||
|
CONFIG_PRINTK=y
|
||||||
|
CONFIG_BUG=y
|
||||||
|
CONFIG_BASE_FULL=y
|
||||||
|
CONFIG_FUTEX=y
|
||||||
|
CONFIG_EPOLL=y
|
||||||
|
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||||
|
CONFIG_SHMEM=y
|
||||||
|
CONFIG_CC_ALIGN_FUNCTIONS=0
|
||||||
|
CONFIG_CC_ALIGN_LABELS=0
|
||||||
|
CONFIG_CC_ALIGN_LOOPS=0
|
||||||
|
CONFIG_CC_ALIGN_JUMPS=0
|
||||||
|
# CONFIG_TINY_SHMEM is not set
|
||||||
|
CONFIG_BASE_SMALL=0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Loadable module support
|
||||||
|
#
|
||||||
|
CONFIG_MODULES=y
|
||||||
|
CONFIG_MODULE_UNLOAD=y
|
||||||
|
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||||
|
CONFIG_OBSOLETE_MODPARM=y
|
||||||
|
CONFIG_MODVERSIONS=y
|
||||||
|
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||||
|
CONFIG_KMOD=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# System Type
|
||||||
|
#
|
||||||
|
# CONFIG_ARCH_CLPS7500 is not set
|
||||||
|
# CONFIG_ARCH_CLPS711X is not set
|
||||||
|
# CONFIG_ARCH_CO285 is not set
|
||||||
|
# CONFIG_ARCH_EBSA110 is not set
|
||||||
|
# CONFIG_ARCH_CAMELOT is not set
|
||||||
|
# CONFIG_ARCH_FOOTBRIDGE is not set
|
||||||
|
# CONFIG_ARCH_INTEGRATOR is not set
|
||||||
|
# CONFIG_ARCH_IOP3XX is not set
|
||||||
|
# CONFIG_ARCH_IXP4XX is not set
|
||||||
|
# CONFIG_ARCH_IXP2000 is not set
|
||||||
|
# CONFIG_ARCH_L7200 is not set
|
||||||
|
# CONFIG_ARCH_PXA is not set
|
||||||
|
# CONFIG_ARCH_RPC is not set
|
||||||
|
CONFIG_ARCH_SA1100=y
|
||||||
|
# CONFIG_ARCH_S3C2410 is not set
|
||||||
|
# CONFIG_ARCH_SHARK is not set
|
||||||
|
# CONFIG_ARCH_LH7A40X is not set
|
||||||
|
# CONFIG_ARCH_OMAP is not set
|
||||||
|
# CONFIG_ARCH_VERSATILE is not set
|
||||||
|
# CONFIG_ARCH_IMX is not set
|
||||||
|
# CONFIG_ARCH_H720X is not set
|
||||||
|
# CONFIG_ARCH_AAEC2000 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# SA11x0 Implementations
|
||||||
|
#
|
||||||
|
# CONFIG_SA1100_ASSABET is not set
|
||||||
|
# CONFIG_SA1100_CERF is not set
|
||||||
|
CONFIG_SA1100_COLLIE=y
|
||||||
|
# CONFIG_SA1100_H3100 is not set
|
||||||
|
# CONFIG_SA1100_H3600 is not set
|
||||||
|
# CONFIG_SA1100_H3800 is not set
|
||||||
|
# CONFIG_SA1100_BADGE4 is not set
|
||||||
|
# CONFIG_SA1100_JORNADA720 is not set
|
||||||
|
# CONFIG_SA1100_HACKKIT is not set
|
||||||
|
# CONFIG_SA1100_LART is not set
|
||||||
|
# CONFIG_SA1100_PLEB is not set
|
||||||
|
# CONFIG_SA1100_SHANNON is not set
|
||||||
|
# CONFIG_SA1100_SIMPAD is not set
|
||||||
|
# CONFIG_SA1100_SSP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Processor Type
|
||||||
|
#
|
||||||
|
CONFIG_CPU_32=y
|
||||||
|
CONFIG_CPU_SA1100=y
|
||||||
|
CONFIG_CPU_32v4=y
|
||||||
|
CONFIG_CPU_ABRT_EV4=y
|
||||||
|
CONFIG_CPU_CACHE_V4WB=y
|
||||||
|
CONFIG_CPU_CACHE_VIVT=y
|
||||||
|
CONFIG_CPU_TLB_V4WB=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Processor Features
|
||||||
|
#
|
||||||
|
CONFIG_SHARP_LOCOMO=y
|
||||||
|
CONFIG_SHARP_PARAM=y
|
||||||
|
CONFIG_SHARP_SCOOP=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bus support
|
||||||
|
#
|
||||||
|
CONFIG_ISA=y
|
||||||
|
CONFIG_ISA_DMA_API=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# PCCARD (PCMCIA/CardBus) support
|
||||||
|
#
|
||||||
|
# CONFIG_PCCARD is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kernel Features
|
||||||
|
#
|
||||||
|
# CONFIG_SMP is not set
|
||||||
|
CONFIG_PREEMPT=y
|
||||||
|
# CONFIG_NO_IDLE_HZ is not set
|
||||||
|
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
|
||||||
|
CONFIG_SELECT_MEMORY_MODEL=y
|
||||||
|
# CONFIG_FLATMEM_MANUAL is not set
|
||||||
|
CONFIG_DISCONTIGMEM_MANUAL=y
|
||||||
|
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||||
|
CONFIG_DISCONTIGMEM=y
|
||||||
|
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||||
|
CONFIG_NEED_MULTIPLE_NODES=y
|
||||||
|
# CONFIG_SPARSEMEM_STATIC is not set
|
||||||
|
# CONFIG_LEDS is not set
|
||||||
|
CONFIG_ALIGNMENT_TRAP=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Boot options
|
||||||
|
#
|
||||||
|
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||||
|
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||||
|
CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug"
|
||||||
|
# CONFIG_XIP_KERNEL is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# CPU Frequency scaling
|
||||||
|
#
|
||||||
|
# CONFIG_CPU_FREQ is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Floating point emulation
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# At least one emulation must be selected
|
||||||
|
#
|
||||||
|
CONFIG_FPE_NWFPE=y
|
||||||
|
# CONFIG_FPE_NWFPE_XP is not set
|
||||||
|
# CONFIG_FPE_FASTFPE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Userspace binary formats
|
||||||
|
#
|
||||||
|
CONFIG_BINFMT_ELF=y
|
||||||
|
CONFIG_BINFMT_AOUT=m
|
||||||
|
CONFIG_BINFMT_MISC=m
|
||||||
|
# CONFIG_ARTHUR is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Power management options
|
||||||
|
#
|
||||||
|
CONFIG_PM=y
|
||||||
|
CONFIG_APM=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Networking
|
||||||
|
#
|
||||||
|
CONFIG_NET=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Networking options
|
||||||
|
#
|
||||||
|
CONFIG_PACKET=y
|
||||||
|
CONFIG_PACKET_MMAP=y
|
||||||
|
CONFIG_UNIX=y
|
||||||
|
# CONFIG_NET_KEY is not set
|
||||||
|
CONFIG_INET=y
|
||||||
|
# CONFIG_IP_MULTICAST is not set
|
||||||
|
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||||
|
CONFIG_IP_FIB_HASH=y
|
||||||
|
# CONFIG_IP_PNP is not set
|
||||||
|
# CONFIG_NET_IPIP is not set
|
||||||
|
# CONFIG_NET_IPGRE is not set
|
||||||
|
# CONFIG_ARPD is not set
|
||||||
|
CONFIG_SYN_COOKIES=y
|
||||||
|
# CONFIG_INET_AH is not set
|
||||||
|
# CONFIG_INET_ESP is not set
|
||||||
|
# CONFIG_INET_IPCOMP is not set
|
||||||
|
# CONFIG_INET_TUNNEL is not set
|
||||||
|
CONFIG_INET_DIAG=y
|
||||||
|
CONFIG_INET_TCP_DIAG=y
|
||||||
|
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||||
|
CONFIG_TCP_CONG_BIC=y
|
||||||
|
# CONFIG_IPV6 is not set
|
||||||
|
# CONFIG_NETFILTER is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# DCCP Configuration (EXPERIMENTAL)
|
||||||
|
#
|
||||||
|
# CONFIG_IP_DCCP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# SCTP Configuration (EXPERIMENTAL)
|
||||||
|
#
|
||||||
|
# CONFIG_IP_SCTP is not set
|
||||||
|
# CONFIG_ATM is not set
|
||||||
|
# CONFIG_BRIDGE is not set
|
||||||
|
# CONFIG_VLAN_8021Q is not set
|
||||||
|
# CONFIG_DECNET is not set
|
||||||
|
# CONFIG_LLC2 is not set
|
||||||
|
# CONFIG_IPX is not set
|
||||||
|
# CONFIG_ATALK is not set
|
||||||
|
# CONFIG_X25 is not set
|
||||||
|
# CONFIG_LAPB is not set
|
||||||
|
# CONFIG_NET_DIVERT is not set
|
||||||
|
# CONFIG_ECONET is not set
|
||||||
|
# CONFIG_WAN_ROUTER is not set
|
||||||
|
# CONFIG_NET_SCHED is not set
|
||||||
|
# CONFIG_NET_CLS_ROUTE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Network testing
|
||||||
|
#
|
||||||
|
# CONFIG_NET_PKTGEN is not set
|
||||||
|
# CONFIG_HAMRADIO is not set
|
||||||
|
# CONFIG_IRDA is not set
|
||||||
|
# CONFIG_BT is not set
|
||||||
|
# CONFIG_IEEE80211 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Device Drivers
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generic Driver Options
|
||||||
|
#
|
||||||
|
CONFIG_STANDALONE=y
|
||||||
|
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||||
|
CONFIG_FW_LOADER=m
|
||||||
|
# CONFIG_DEBUG_DRIVER is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Memory Technology Devices (MTD)
|
||||||
|
#
|
||||||
|
CONFIG_MTD=y
|
||||||
|
# CONFIG_MTD_DEBUG is not set
|
||||||
|
# CONFIG_MTD_CONCAT is not set
|
||||||
|
CONFIG_MTD_PARTITIONS=y
|
||||||
|
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||||
|
# CONFIG_MTD_CMDLINE_PARTS is not set
|
||||||
|
# CONFIG_MTD_AFS_PARTS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# User Modules And Translation Layers
|
||||||
|
#
|
||||||
|
CONFIG_MTD_CHAR=y
|
||||||
|
CONFIG_MTD_BLOCK=y
|
||||||
|
# CONFIG_FTL is not set
|
||||||
|
# CONFIG_NFTL is not set
|
||||||
|
# CONFIG_INFTL is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# RAM/ROM/Flash chip drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_CFI is not set
|
||||||
|
# CONFIG_MTD_JEDECPROBE is not set
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_1=y
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_2=y
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
|
||||||
|
CONFIG_MTD_CFI_I1=y
|
||||||
|
CONFIG_MTD_CFI_I2=y
|
||||||
|
# CONFIG_MTD_CFI_I4 is not set
|
||||||
|
# CONFIG_MTD_CFI_I8 is not set
|
||||||
|
# CONFIG_MTD_RAM is not set
|
||||||
|
# CONFIG_MTD_ROM is not set
|
||||||
|
# CONFIG_MTD_ABSENT is not set
|
||||||
|
CONFIG_MTD_OBSOLETE_CHIPS=y
|
||||||
|
# CONFIG_MTD_AMDSTD is not set
|
||||||
|
CONFIG_MTD_SHARP=y
|
||||||
|
# CONFIG_MTD_JEDEC is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mapping drivers for chip access
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||||
|
# CONFIG_MTD_PLATRAM is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Self-contained MTD device drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_SLRAM is not set
|
||||||
|
# CONFIG_MTD_PHRAM is not set
|
||||||
|
# CONFIG_MTD_MTDRAM is not set
|
||||||
|
# CONFIG_MTD_BLKMTD is not set
|
||||||
|
# CONFIG_MTD_BLOCK2MTD is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Disk-On-Chip Device Drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_DOC2000 is not set
|
||||||
|
# CONFIG_MTD_DOC2001 is not set
|
||||||
|
# CONFIG_MTD_DOC2001PLUS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# NAND Flash Device Drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_NAND is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parallel port support
|
||||||
|
#
|
||||||
|
# CONFIG_PARPORT is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Plug and Play support
|
||||||
|
#
|
||||||
|
# CONFIG_PNP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Block devices
|
||||||
|
#
|
||||||
|
# CONFIG_BLK_DEV_XD is not set
|
||||||
|
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||||
|
CONFIG_BLK_DEV_LOOP=y
|
||||||
|
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||||
|
# CONFIG_BLK_DEV_NBD is not set
|
||||||
|
CONFIG_BLK_DEV_RAM=y
|
||||||
|
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||||
|
CONFIG_BLK_DEV_RAM_SIZE=1024
|
||||||
|
CONFIG_BLK_DEV_INITRD=y
|
||||||
|
# CONFIG_CDROM_PKTCDVD is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# IO Schedulers
|
||||||
|
#
|
||||||
|
CONFIG_IOSCHED_NOOP=y
|
||||||
|
CONFIG_IOSCHED_AS=y
|
||||||
|
CONFIG_IOSCHED_DEADLINE=y
|
||||||
|
CONFIG_IOSCHED_CFQ=y
|
||||||
|
CONFIG_ATA_OVER_ETH=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# ATA/ATAPI/MFM/RLL support
|
||||||
|
#
|
||||||
|
# CONFIG_IDE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# SCSI device support
|
||||||
|
#
|
||||||
|
# CONFIG_RAID_ATTRS is not set
|
||||||
|
# CONFIG_SCSI is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multi-device support (RAID and LVM)
|
||||||
|
#
|
||||||
|
# CONFIG_MD is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fusion MPT device support
|
||||||
|
#
|
||||||
|
# CONFIG_FUSION is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# IEEE 1394 (FireWire) support
|
||||||
|
#
|
||||||
|
# CONFIG_IEEE1394 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# I2O device support
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Network device support
|
||||||
|
#
|
||||||
|
# CONFIG_NETDEVICES is not set
|
||||||
|
# CONFIG_NETPOLL is not set
|
||||||
|
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# ISDN subsystem
|
||||||
|
#
|
||||||
|
# CONFIG_ISDN is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Input device support
|
||||||
|
#
|
||||||
|
CONFIG_INPUT=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Userland interfaces
|
||||||
|
#
|
||||||
|
# CONFIG_INPUT_MOUSEDEV is not set
|
||||||
|
# CONFIG_INPUT_JOYDEV is not set
|
||||||
|
CONFIG_INPUT_TSDEV=y
|
||||||
|
CONFIG_INPUT_TSDEV_SCREEN_X=240
|
||||||
|
CONFIG_INPUT_TSDEV_SCREEN_Y=320
|
||||||
|
CONFIG_INPUT_EVDEV=y
|
||||||
|
CONFIG_INPUT_EVBUG=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Input Device Drivers
|
||||||
|
#
|
||||||
|
CONFIG_INPUT_KEYBOARD=y
|
||||||
|
# CONFIG_KEYBOARD_ATKBD is not set
|
||||||
|
# CONFIG_KEYBOARD_SUNKBD is not set
|
||||||
|
# CONFIG_KEYBOARD_LKKBD is not set
|
||||||
|
CONFIG_KEYBOARD_LOCOMO=y
|
||||||
|
# CONFIG_KEYBOARD_XTKBD is not set
|
||||||
|
# CONFIG_KEYBOARD_NEWTON is not set
|
||||||
|
# CONFIG_INPUT_MOUSE is not set
|
||||||
|
# CONFIG_INPUT_JOYSTICK is not set
|
||||||
|
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||||
|
# CONFIG_INPUT_MISC is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hardware I/O ports
|
||||||
|
#
|
||||||
|
CONFIG_SERIO=y
|
||||||
|
# CONFIG_SERIO_SERPORT is not set
|
||||||
|
# CONFIG_SERIO_LIBPS2 is not set
|
||||||
|
# CONFIG_SERIO_RAW is not set
|
||||||
|
# CONFIG_GAMEPORT is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Character devices
|
||||||
|
#
|
||||||
|
CONFIG_VT=y
|
||||||
|
CONFIG_VT_CONSOLE=y
|
||||||
|
CONFIG_HW_CONSOLE=y
|
||||||
|
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Serial drivers
|
||||||
|
#
|
||||||
|
# CONFIG_SERIAL_8250 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Non-8250 serial port support
|
||||||
|
#
|
||||||
|
CONFIG_SERIAL_SA1100=y
|
||||||
|
CONFIG_SERIAL_SA1100_CONSOLE=y
|
||||||
|
CONFIG_SERIAL_CORE=y
|
||||||
|
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||||
|
CONFIG_UNIX98_PTYS=y
|
||||||
|
# CONFIG_LEGACY_PTYS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# IPMI
|
||||||
|
#
|
||||||
|
# CONFIG_IPMI_HANDLER is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Watchdog Cards
|
||||||
|
#
|
||||||
|
# CONFIG_WATCHDOG is not set
|
||||||
|
# CONFIG_NVRAM is not set
|
||||||
|
# CONFIG_RTC is not set
|
||||||
|
# CONFIG_DTLK is not set
|
||||||
|
# CONFIG_R3964 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Ftape, the floppy tape device driver
|
||||||
|
#
|
||||||
|
# CONFIG_RAW_DRIVER is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# TPM devices
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# I2C support
|
||||||
|
#
|
||||||
|
CONFIG_I2C=m
|
||||||
|
# CONFIG_I2C_CHARDEV is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# I2C Algorithms
|
||||||
|
#
|
||||||
|
CONFIG_I2C_ALGOBIT=m
|
||||||
|
# CONFIG_I2C_ALGOPCF is not set
|
||||||
|
# CONFIG_I2C_ALGOPCA is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# I2C Hardware Bus support
|
||||||
|
#
|
||||||
|
# CONFIG_I2C_ELEKTOR is not set
|
||||||
|
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||||
|
# CONFIG_I2C_STUB is not set
|
||||||
|
# CONFIG_I2C_PCA_ISA is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Miscellaneous I2C Chip support
|
||||||
|
#
|
||||||
|
# CONFIG_SENSORS_DS1337 is not set
|
||||||
|
# CONFIG_SENSORS_DS1374 is not set
|
||||||
|
# CONFIG_SENSORS_EEPROM is not set
|
||||||
|
# CONFIG_SENSORS_PCF8574 is not set
|
||||||
|
# CONFIG_SENSORS_PCA9539 is not set
|
||||||
|
# CONFIG_SENSORS_PCF8591 is not set
|
||||||
|
# CONFIG_SENSORS_RTC8564 is not set
|
||||||
|
# CONFIG_SENSORS_MAX6875 is not set
|
||||||
|
# CONFIG_I2C_DEBUG_CORE is not set
|
||||||
|
# CONFIG_I2C_DEBUG_ALGO is not set
|
||||||
|
# CONFIG_I2C_DEBUG_BUS is not set
|
||||||
|
# CONFIG_I2C_DEBUG_CHIP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hardware Monitoring support
|
||||||
|
#
|
||||||
|
CONFIG_HWMON=y
|
||||||
|
# CONFIG_HWMON_VID is not set
|
||||||
|
# CONFIG_SENSORS_ADM1021 is not set
|
||||||
|
# CONFIG_SENSORS_ADM1025 is not set
|
||||||
|
# CONFIG_SENSORS_ADM1026 is not set
|
||||||
|
# CONFIG_SENSORS_ADM1031 is not set
|
||||||
|
# CONFIG_SENSORS_ADM9240 is not set
|
||||||
|
# CONFIG_SENSORS_ASB100 is not set
|
||||||
|
# CONFIG_SENSORS_ATXP1 is not set
|
||||||
|
# CONFIG_SENSORS_DS1621 is not set
|
||||||
|
# CONFIG_SENSORS_FSCHER is not set
|
||||||
|
# CONFIG_SENSORS_FSCPOS is not set
|
||||||
|
# CONFIG_SENSORS_GL518SM is not set
|
||||||
|
# CONFIG_SENSORS_GL520SM is not set
|
||||||
|
# CONFIG_SENSORS_IT87 is not set
|
||||||
|
# CONFIG_SENSORS_LM63 is not set
|
||||||
|
# CONFIG_SENSORS_LM75 is not set
|
||||||
|
# CONFIG_SENSORS_LM77 is not set
|
||||||
|
# CONFIG_SENSORS_LM78 is not set
|
||||||
|
# CONFIG_SENSORS_LM80 is not set
|
||||||
|
# CONFIG_SENSORS_LM83 is not set
|
||||||
|
# CONFIG_SENSORS_LM85 is not set
|
||||||
|
# CONFIG_SENSORS_LM87 is not set
|
||||||
|
# CONFIG_SENSORS_LM90 is not set
|
||||||
|
# CONFIG_SENSORS_LM92 is not set
|
||||||
|
# CONFIG_SENSORS_MAX1619 is not set
|
||||||
|
# CONFIG_SENSORS_PC87360 is not set
|
||||||
|
# CONFIG_SENSORS_SMSC47M1 is not set
|
||||||
|
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||||
|
# CONFIG_SENSORS_W83781D is not set
|
||||||
|
# CONFIG_SENSORS_W83792D is not set
|
||||||
|
# CONFIG_SENSORS_W83L785TS is not set
|
||||||
|
# CONFIG_SENSORS_W83627HF is not set
|
||||||
|
# CONFIG_SENSORS_W83627EHF is not set
|
||||||
|
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Misc devices
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multimedia Capabilities Port drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MCP_SA11X0 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multimedia devices
|
||||||
|
#
|
||||||
|
CONFIG_VIDEO_DEV=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# Video For Linux
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Video Adapters
|
||||||
|
#
|
||||||
|
# CONFIG_VIDEO_PMS is not set
|
||||||
|
# CONFIG_VIDEO_CPIA is not set
|
||||||
|
# CONFIG_VIDEO_SAA5246A is not set
|
||||||
|
# CONFIG_VIDEO_SAA5249 is not set
|
||||||
|
# CONFIG_TUNER_3036 is not set
|
||||||
|
# CONFIG_VIDEO_OVCAMCHIP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Radio Adapters
|
||||||
|
#
|
||||||
|
# CONFIG_RADIO_CADET is not set
|
||||||
|
# CONFIG_RADIO_RTRACK is not set
|
||||||
|
# CONFIG_RADIO_RTRACK2 is not set
|
||||||
|
# CONFIG_RADIO_AZTECH is not set
|
||||||
|
# CONFIG_RADIO_GEMTEK is not set
|
||||||
|
# CONFIG_RADIO_MAESTRO is not set
|
||||||
|
# CONFIG_RADIO_SF16FMI is not set
|
||||||
|
# CONFIG_RADIO_SF16FMR2 is not set
|
||||||
|
# CONFIG_RADIO_TERRATEC is not set
|
||||||
|
# CONFIG_RADIO_TRUST is not set
|
||||||
|
# CONFIG_RADIO_TYPHOON is not set
|
||||||
|
# CONFIG_RADIO_ZOLTRIX is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Digital Video Broadcasting Devices
|
||||||
|
#
|
||||||
|
# CONFIG_DVB is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Graphics support
|
||||||
|
#
|
||||||
|
CONFIG_FB=y
|
||||||
|
CONFIG_FB_CFB_FILLRECT=y
|
||||||
|
CONFIG_FB_CFB_COPYAREA=y
|
||||||
|
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||||
|
CONFIG_FB_SOFT_CURSOR=y
|
||||||
|
# CONFIG_FB_MACMODES is not set
|
||||||
|
CONFIG_FB_MODE_HELPERS=y
|
||||||
|
# CONFIG_FB_TILEBLITTING is not set
|
||||||
|
CONFIG_FB_SA1100=y
|
||||||
|
# CONFIG_FB_S1D13XXX is not set
|
||||||
|
# CONFIG_FB_VIRTUAL is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Console display driver support
|
||||||
|
#
|
||||||
|
# CONFIG_VGA_CONSOLE is not set
|
||||||
|
# CONFIG_MDA_CONSOLE is not set
|
||||||
|
CONFIG_DUMMY_CONSOLE=y
|
||||||
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
|
CONFIG_FONTS=y
|
||||||
|
CONFIG_FONT_8x8=y
|
||||||
|
# CONFIG_FONT_8x16 is not set
|
||||||
|
# CONFIG_FONT_6x11 is not set
|
||||||
|
# CONFIG_FONT_7x14 is not set
|
||||||
|
# CONFIG_FONT_PEARL_8x8 is not set
|
||||||
|
# CONFIG_FONT_ACORN_8x8 is not set
|
||||||
|
# CONFIG_FONT_MINI_4x6 is not set
|
||||||
|
# CONFIG_FONT_SUN8x16 is not set
|
||||||
|
# CONFIG_FONT_SUN12x22 is not set
|
||||||
|
# CONFIG_FONT_10x18 is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Logo configuration
|
||||||
|
#
|
||||||
|
# CONFIG_LOGO is not set
|
||||||
|
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sound
|
||||||
|
#
|
||||||
|
# CONFIG_SOUND is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB support
|
||||||
|
#
|
||||||
|
CONFIG_USB_ARCH_HAS_HCD=y
|
||||||
|
# CONFIG_USB_ARCH_HAS_OHCI is not set
|
||||||
|
# CONFIG_USB is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB Gadget Support
|
||||||
|
#
|
||||||
|
CONFIG_USB_GADGET=y
|
||||||
|
# CONFIG_USB_GADGET_DEBUG_FILES is not set
|
||||||
|
# CONFIG_USB_GADGET_NET2280 is not set
|
||||||
|
# CONFIG_USB_GADGET_PXA2XX is not set
|
||||||
|
# CONFIG_USB_GADGET_GOKU is not set
|
||||||
|
# CONFIG_USB_GADGET_LH7A40X is not set
|
||||||
|
# CONFIG_USB_GADGET_OMAP is not set
|
||||||
|
# CONFIG_USB_GADGET_DUMMY_HCD is not set
|
||||||
|
# CONFIG_USB_GADGET_DUALSPEED is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# MMC/SD Card support
|
||||||
|
#
|
||||||
|
# CONFIG_MMC is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# File systems
|
||||||
|
#
|
||||||
|
CONFIG_EXT2_FS=y
|
||||||
|
CONFIG_EXT2_FS_XATTR=y
|
||||||
|
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||||
|
CONFIG_EXT2_FS_SECURITY=y
|
||||||
|
# CONFIG_EXT2_FS_XIP is not set
|
||||||
|
# CONFIG_EXT3_FS is not set
|
||||||
|
# CONFIG_JBD is not set
|
||||||
|
CONFIG_FS_MBCACHE=y
|
||||||
|
# CONFIG_REISERFS_FS is not set
|
||||||
|
# CONFIG_JFS_FS is not set
|
||||||
|
CONFIG_FS_POSIX_ACL=y
|
||||||
|
# CONFIG_XFS_FS is not set
|
||||||
|
# CONFIG_MINIX_FS is not set
|
||||||
|
CONFIG_ROMFS_FS=y
|
||||||
|
CONFIG_INOTIFY=y
|
||||||
|
# CONFIG_QUOTA is not set
|
||||||
|
# CONFIG_DNOTIFY is not set
|
||||||
|
# CONFIG_AUTOFS_FS is not set
|
||||||
|
# CONFIG_AUTOFS4_FS is not set
|
||||||
|
# CONFIG_FUSE_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# CD-ROM/DVD Filesystems
|
||||||
|
#
|
||||||
|
# CONFIG_ISO9660_FS is not set
|
||||||
|
# CONFIG_UDF_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# DOS/FAT/NT Filesystems
|
||||||
|
#
|
||||||
|
CONFIG_FAT_FS=y
|
||||||
|
CONFIG_MSDOS_FS=y
|
||||||
|
CONFIG_VFAT_FS=y
|
||||||
|
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||||
|
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||||
|
# CONFIG_NTFS_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Pseudo filesystems
|
||||||
|
#
|
||||||
|
CONFIG_PROC_FS=y
|
||||||
|
CONFIG_SYSFS=y
|
||||||
|
CONFIG_TMPFS=y
|
||||||
|
# CONFIG_HUGETLBFS is not set
|
||||||
|
# CONFIG_HUGETLB_PAGE is not set
|
||||||
|
CONFIG_RAMFS=y
|
||||||
|
# CONFIG_RELAYFS_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Miscellaneous filesystems
|
||||||
|
#
|
||||||
|
# CONFIG_ADFS_FS is not set
|
||||||
|
# CONFIG_AFFS_FS is not set
|
||||||
|
# CONFIG_HFS_FS is not set
|
||||||
|
# CONFIG_HFSPLUS_FS is not set
|
||||||
|
# CONFIG_BEFS_FS is not set
|
||||||
|
# CONFIG_BFS_FS is not set
|
||||||
|
# CONFIG_EFS_FS is not set
|
||||||
|
# CONFIG_JFFS_FS is not set
|
||||||
|
CONFIG_JFFS2_FS=y
|
||||||
|
CONFIG_JFFS2_FS_DEBUG=0
|
||||||
|
CONFIG_JFFS2_FS_WRITEBUFFER=y
|
||||||
|
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
|
||||||
|
CONFIG_JFFS2_ZLIB=y
|
||||||
|
CONFIG_JFFS2_RTIME=y
|
||||||
|
# CONFIG_JFFS2_RUBIN is not set
|
||||||
|
CONFIG_CRAMFS=y
|
||||||
|
# CONFIG_VXFS_FS is not set
|
||||||
|
# CONFIG_HPFS_FS is not set
|
||||||
|
# CONFIG_QNX4FS_FS is not set
|
||||||
|
# CONFIG_SYSV_FS is not set
|
||||||
|
# CONFIG_UFS_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Network File Systems
|
||||||
|
#
|
||||||
|
# CONFIG_NFS_FS is not set
|
||||||
|
# CONFIG_NFSD is not set
|
||||||
|
# CONFIG_SMB_FS is not set
|
||||||
|
# CONFIG_CIFS is not set
|
||||||
|
# CONFIG_NCP_FS is not set
|
||||||
|
# CONFIG_CODA_FS is not set
|
||||||
|
# CONFIG_AFS_FS is not set
|
||||||
|
# CONFIG_9P_FS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Partition Types
|
||||||
|
#
|
||||||
|
# CONFIG_PARTITION_ADVANCED is not set
|
||||||
|
CONFIG_MSDOS_PARTITION=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Native Language Support
|
||||||
|
#
|
||||||
|
CONFIG_NLS=y
|
||||||
|
CONFIG_NLS_DEFAULT="cp437"
|
||||||
|
CONFIG_NLS_CODEPAGE_437=m
|
||||||
|
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_936 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_8 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||||
|
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||||
|
# CONFIG_NLS_ASCII is not set
|
||||||
|
CONFIG_NLS_ISO8859_1=m
|
||||||
|
# CONFIG_NLS_ISO8859_2 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_3 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_4 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_5 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_6 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_7 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_9 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_13 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_14 is not set
|
||||||
|
# CONFIG_NLS_ISO8859_15 is not set
|
||||||
|
# CONFIG_NLS_KOI8_R is not set
|
||||||
|
# CONFIG_NLS_KOI8_U is not set
|
||||||
|
CONFIG_NLS_UTF8=m
|
||||||
|
|
||||||
|
#
|
||||||
|
# Profiling support
|
||||||
|
#
|
||||||
|
# CONFIG_PROFILING is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kernel hacking
|
||||||
|
#
|
||||||
|
# CONFIG_PRINTK_TIME is not set
|
||||||
|
CONFIG_DEBUG_KERNEL=y
|
||||||
|
CONFIG_MAGIC_SYSRQ=y
|
||||||
|
CONFIG_LOG_BUF_SHIFT=14
|
||||||
|
CONFIG_DETECT_SOFTLOCKUP=y
|
||||||
|
# CONFIG_SCHEDSTATS is not set
|
||||||
|
# CONFIG_DEBUG_SLAB is not set
|
||||||
|
CONFIG_DEBUG_PREEMPT=y
|
||||||
|
# CONFIG_DEBUG_SPINLOCK is not set
|
||||||
|
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||||
|
# CONFIG_DEBUG_KOBJECT is not set
|
||||||
|
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||||
|
# CONFIG_DEBUG_INFO is not set
|
||||||
|
# CONFIG_DEBUG_FS is not set
|
||||||
|
CONFIG_FRAME_POINTER=y
|
||||||
|
# CONFIG_DEBUG_USER is not set
|
||||||
|
# CONFIG_DEBUG_WAITQ is not set
|
||||||
|
CONFIG_DEBUG_ERRORS=y
|
||||||
|
# CONFIG_DEBUG_LL is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Security options
|
||||||
|
#
|
||||||
|
# CONFIG_KEYS is not set
|
||||||
|
# CONFIG_SECURITY is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cryptographic options
|
||||||
|
#
|
||||||
|
# CONFIG_CRYPTO is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hardware crypto devices
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Library routines
|
||||||
|
#
|
||||||
|
# CONFIG_CRC_CCITT is not set
|
||||||
|
# CONFIG_CRC16 is not set
|
||||||
|
CONFIG_CRC32=y
|
||||||
|
# CONFIG_LIBCRC32C is not set
|
||||||
|
CONFIG_ZLIB_INFLATE=y
|
||||||
|
CONFIG_ZLIB_DEFLATE=y
|
1523
arch/arm/configs/corgi_defconfig
Normal file
1523
arch/arm/configs/corgi_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1015
arch/arm/configs/poodle_defconfig
Normal file
1015
arch/arm/configs/poodle_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1401
arch/arm/configs/spitz_defconfig
Normal file
1401
arch/arm/configs/spitz_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@ extern void fp_enter(void);
|
|||||||
|
|
||||||
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
|
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
|
||||||
EXPORT_CRC_ALIAS(sym) \
|
EXPORT_CRC_ALIAS(sym) \
|
||||||
const struct kernel_symbol __ksymtab_##sym \
|
static const struct kernel_symbol __ksymtab_##sym \
|
||||||
__attribute__((section("__ksymtab"))) = \
|
__attribute_used__ __attribute__((section("__ksymtab"))) = \
|
||||||
{ (unsigned long)&orig, #sym };
|
{ (unsigned long)&orig, #sym };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,15 +106,10 @@ ENTRY(ret_from_fork)
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
.Larm700bug:
|
.Larm700bug:
|
||||||
ldr r0, [sp, #S_PSR] @ Get calling cpsr
|
|
||||||
sub lr, lr, #4
|
|
||||||
str lr, [r8]
|
|
||||||
msr spsr_cxsf, r0
|
|
||||||
ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
|
ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
|
||||||
mov r0, r0
|
mov r0, r0
|
||||||
ldr lr, [sp, #S_PC] @ Get PC
|
|
||||||
add sp, sp, #S_FRAME_SIZE
|
add sp, sp, #S_FRAME_SIZE
|
||||||
movs pc, lr
|
subs pc, lr, #4
|
||||||
#else
|
#else
|
||||||
.macro arm710_bug_check, instr, temp
|
.macro arm710_bug_check, instr, temp
|
||||||
.endm
|
.endm
|
||||||
|
@ -89,13 +89,6 @@ SECTIONS
|
|||||||
*(.got) /* Global offset table */
|
*(.got) /* Global offset table */
|
||||||
}
|
}
|
||||||
|
|
||||||
. = ALIGN(16);
|
|
||||||
__ex_table : { /* Exception table */
|
|
||||||
__start___ex_table = .;
|
|
||||||
*(__ex_table)
|
|
||||||
__stop___ex_table = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
RODATA
|
RODATA
|
||||||
|
|
||||||
_etext = .; /* End of text and rodata section */
|
_etext = .; /* End of text and rodata section */
|
||||||
@ -137,6 +130,14 @@ SECTIONS
|
|||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
*(.data.cacheline_aligned)
|
*(.data.cacheline_aligned)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The exception fixup table (might need resorting at runtime)
|
||||||
|
*/
|
||||||
|
. = ALIGN(32);
|
||||||
|
__start___ex_table = .;
|
||||||
|
*(__ex_table)
|
||||||
|
__stop___ex_table = .;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* and the usual data section
|
* and the usual data section
|
||||||
*/
|
*/
|
||||||
|
@ -7,11 +7,17 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
|
||||||
|
#include <asm/types.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/map.h>
|
#include <asm/mach/map.h>
|
||||||
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IRQ base register
|
* IRQ base register
|
||||||
@ -47,6 +53,12 @@ static void l7200_unmask_irq(unsigned int irq)
|
|||||||
{
|
{
|
||||||
IRQ_ENABLE = 1 << irq;
|
IRQ_ENABLE = 1 << irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct irqchip l7200_irq_chip = {
|
||||||
|
.ack = l7200_mask_irq,
|
||||||
|
.mask = l7200_mask_irq,
|
||||||
|
.unmask = l7200_unmask_irq
|
||||||
|
};
|
||||||
|
|
||||||
static void __init l7200_init_irq(void)
|
static void __init l7200_init_irq(void)
|
||||||
{
|
{
|
||||||
@ -56,11 +68,9 @@ static void __init l7200_init_irq(void)
|
|||||||
FIQ_ENABLECLEAR = 0xffffffff; /* clear all fast interrupt enables */
|
FIQ_ENABLECLEAR = 0xffffffff; /* clear all fast interrupt enables */
|
||||||
|
|
||||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||||
irq_desc[irq].valid = 1;
|
set_irq_chip(irq, &l7200_irq_chip);
|
||||||
irq_desc[irq].probe_ok = 1;
|
set_irq_flags(irq, IRQF_VALID);
|
||||||
irq_desc[irq].mask_ack = l7200_mask_irq;
|
set_irq_handler(irq, do_level_IRQ);
|
||||||
irq_desc[irq].mask = l7200_mask_irq;
|
|
||||||
irq_desc[irq].unmask = l7200_unmask_irq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_FIQ();
|
init_FIQ();
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <asm/arch/mmc.h>
|
#include <asm/arch/mmc.h>
|
||||||
#include <asm/arch/udc.h>
|
#include <asm/arch/udc.h>
|
||||||
#include <asm/arch/corgi.h>
|
#include <asm/arch/corgi.h>
|
||||||
|
#include <asm/arch/sharpsl.h>
|
||||||
|
|
||||||
#include <asm/mach/sharpsl_param.h>
|
#include <asm/mach/sharpsl_param.h>
|
||||||
#include <asm/hardware/scoop.h>
|
#include <asm/hardware/scoop.h>
|
||||||
|
@ -467,6 +467,7 @@ void corgi_put_hsync(void)
|
|||||||
{
|
{
|
||||||
if (get_hsync_time)
|
if (get_hsync_time)
|
||||||
symbol_put(w100fb_get_hsynclen);
|
symbol_put(w100fb_get_hsynclen);
|
||||||
|
get_hsync_time = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void corgi_wait_hsync(void)
|
void corgi_wait_hsync(void)
|
||||||
@ -476,20 +477,37 @@ void corgi_wait_hsync(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PXA_SHARP_Cxx00
|
#ifdef CONFIG_PXA_SHARP_Cxx00
|
||||||
|
static struct device *spitz_pxafb_dev;
|
||||||
|
|
||||||
|
static int is_pxafb_device(struct device * dev, void * data)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
|
||||||
|
|
||||||
|
return (strncmp(pdev->name, "pxa2xx-fb", 9) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long spitz_get_hsync_len(void)
|
unsigned long spitz_get_hsync_len(void)
|
||||||
{
|
{
|
||||||
|
if (!spitz_pxafb_dev) {
|
||||||
|
spitz_pxafb_dev = bus_find_device(&platform_bus_type, NULL, NULL, is_pxafb_device);
|
||||||
|
if (!spitz_pxafb_dev)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!get_hsync_time)
|
if (!get_hsync_time)
|
||||||
get_hsync_time = symbol_get(pxafb_get_hsync_time);
|
get_hsync_time = symbol_get(pxafb_get_hsync_time);
|
||||||
if (!get_hsync_time)
|
if (!get_hsync_time)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return pxafb_get_hsync_time(&pxafb_device.dev);
|
return pxafb_get_hsync_time(spitz_pxafb_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spitz_put_hsync(void)
|
void spitz_put_hsync(void)
|
||||||
{
|
{
|
||||||
|
put_device(spitz_pxafb_dev);
|
||||||
if (get_hsync_time)
|
if (get_hsync_time)
|
||||||
symbol_put(pxafb_get_hsync_time);
|
symbol_put(pxafb_get_hsync_time);
|
||||||
|
spitz_pxafb_dev = NULL;
|
||||||
|
get_hsync_time = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spitz_wait_hsync(void)
|
void spitz_wait_hsync(void)
|
||||||
|
@ -208,6 +208,11 @@ static struct platform_device pxafb_device = {
|
|||||||
.resource = pxafb_resources,
|
.resource = pxafb_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void __init set_pxa_fb_parent(struct device *parent_dev)
|
||||||
|
{
|
||||||
|
pxafb_device.dev.parent = parent_dev;
|
||||||
|
}
|
||||||
|
|
||||||
static struct platform_device ffuart_device = {
|
static struct platform_device ffuart_device = {
|
||||||
.name = "pxa2xx-uart",
|
.name = "pxa2xx-uart",
|
||||||
.id = 0,
|
.id = 0,
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
#include <asm/arch/irq.h>
|
#include <asm/arch/irq.h>
|
||||||
#include <asm/arch/mmc.h>
|
#include <asm/arch/mmc.h>
|
||||||
#include <asm/arch/udc.h>
|
#include <asm/arch/udc.h>
|
||||||
#include <asm/arch/ohci.h>
|
|
||||||
#include <asm/arch/pxafb.h>
|
#include <asm/arch/pxafb.h>
|
||||||
#include <asm/arch/akita.h>
|
#include <asm/arch/akita.h>
|
||||||
#include <asm/arch/spitz.h>
|
#include <asm/arch/spitz.h>
|
||||||
@ -304,7 +303,6 @@ static struct platform_device *devices[] __initdata = {
|
|||||||
&spitzkbd_device,
|
&spitzkbd_device,
|
||||||
&spitzts_device,
|
&spitzts_device,
|
||||||
&spitzbl_device,
|
&spitzbl_device,
|
||||||
&spitzbattery_device,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init common_init(void)
|
static void __init common_init(void)
|
||||||
@ -328,7 +326,7 @@ static void __init common_init(void)
|
|||||||
|
|
||||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
pxa_set_mci_info(&spitz_mci_platform_data);
|
pxa_set_mci_info(&spitz_mci_platform_data);
|
||||||
pxafb_device.dev.parent = &spitzssp_device.dev;
|
set_pxa_fb_parent(&spitzssp_device.dev);
|
||||||
set_pxa_fb_info(&spitz_pxafb_info);
|
set_pxa_fb_info(&spitz_pxafb_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ config MACH_ANUBIS
|
|||||||
config ARCH_BAST
|
config ARCH_BAST
|
||||||
bool "Simtec Electronics BAST (EB2410ITX)"
|
bool "Simtec Electronics BAST (EB2410ITX)"
|
||||||
select CPU_S3C2410
|
select CPU_S3C2410
|
||||||
|
select ISA
|
||||||
help
|
help
|
||||||
Say Y here if you are using the Simtec Electronics EB2410ITX
|
Say Y here if you are using the Simtec Electronics EB2410ITX
|
||||||
development board (also known as BAST)
|
development board (also known as BAST)
|
||||||
|
@ -125,7 +125,7 @@ static int external_map[] = { 2 };
|
|||||||
static int chip0_map[] = { 0 };
|
static int chip0_map[] = { 0 };
|
||||||
static int chip1_map[] = { 1 };
|
static int chip1_map[] = { 1 };
|
||||||
|
|
||||||
struct mtd_partition anubis_default_nand_part[] = {
|
static struct mtd_partition anubis_default_nand_part[] = {
|
||||||
[0] = {
|
[0] = {
|
||||||
.name = "Boot Agent",
|
.name = "Boot Agent",
|
||||||
.size = SZ_16K,
|
.size = SZ_16K,
|
||||||
|
@ -230,7 +230,7 @@ static int chip0_map[] = { 1 };
|
|||||||
static int chip1_map[] = { 2 };
|
static int chip1_map[] = { 2 };
|
||||||
static int chip2_map[] = { 3 };
|
static int chip2_map[] = { 3 };
|
||||||
|
|
||||||
struct mtd_partition bast_default_nand_part[] = {
|
static struct mtd_partition bast_default_nand_part[] = {
|
||||||
[0] = {
|
[0] = {
|
||||||
.name = "Boot Agent",
|
.name = "Boot Agent",
|
||||||
.size = SZ_16K,
|
.size = SZ_16K,
|
||||||
@ -340,7 +340,7 @@ static struct resource bast_dm9k_resource[] = {
|
|||||||
* better IO routines can be written and tested
|
* better IO routines can be written and tested
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dm9000_plat_data bast_dm9k_platdata = {
|
static struct dm9000_plat_data bast_dm9k_platdata = {
|
||||||
.flags = DM9000_PLATF_16BITONLY
|
.flags = DM9000_PLATF_16BITONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ static struct resource vr1000_dm9k1_resource[] = {
|
|||||||
* better IO routines can be written and tested
|
* better IO routines can be written and tested
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dm9000_plat_data vr1000_dm9k_platdata = {
|
static struct dm9000_plat_data vr1000_dm9k_platdata = {
|
||||||
.flags = DM9000_PLATF_16BITONLY,
|
.flags = DM9000_PLATF_16BITONLY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,9 +125,6 @@ static struct platform_device *uart_devices[] __initdata = {
|
|||||||
&s3c_uart2
|
&s3c_uart2
|
||||||
};
|
};
|
||||||
|
|
||||||
/* store our uart devices for the serial driver console */
|
|
||||||
struct platform_device *s3c2410_uart_devices[3];
|
|
||||||
|
|
||||||
static int s3c2410_uart_count = 0;
|
static int s3c2410_uart_count = 0;
|
||||||
|
|
||||||
/* uart registration process */
|
/* uart registration process */
|
||||||
|
@ -151,7 +151,7 @@ void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
|
|||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
struct sleep_save s3c2440_sleep[] = {
|
static struct sleep_save s3c2440_sleep[] = {
|
||||||
SAVE_ITEM(S3C2440_DSC0),
|
SAVE_ITEM(S3C2440_DSC0),
|
||||||
SAVE_ITEM(S3C2440_DSC1),
|
SAVE_ITEM(S3C2440_DSC1),
|
||||||
SAVE_ITEM(S3C2440_GPJDAT),
|
SAVE_ITEM(S3C2440_GPJDAT),
|
||||||
@ -260,7 +260,7 @@ void __init s3c2440_init_clocks(int xtal)
|
|||||||
* as a driver which may support both 2410 and 2440 may try and use it.
|
* as a driver which may support both 2410 and 2440 may try and use it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int __init s3c2440_core_init(void)
|
static int __init s3c2440_core_init(void)
|
||||||
{
|
{
|
||||||
return sysdev_class_register(&s3c2440_sysclass);
|
return sysdev_class_register(&s3c2440_sysclass);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <asm/hardware/clock.h>
|
#include <asm/hardware/clock.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
static unsigned long timer_startval;
|
static unsigned long timer_startval;
|
||||||
static unsigned long timer_usec_ticks;
|
static unsigned long timer_usec_ticks;
|
||||||
|
@ -111,11 +111,11 @@ static struct mtd_partition collie_partitions[] = {
|
|||||||
|
|
||||||
static void collie_set_vpp(int vpp)
|
static void collie_set_vpp(int vpp)
|
||||||
{
|
{
|
||||||
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN);
|
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR) | COLLIE_SCP_VPEN);
|
||||||
if (vpp)
|
if (vpp)
|
||||||
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN);
|
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) | COLLIE_SCP_VPEN);
|
||||||
else
|
else
|
||||||
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
|
write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct flash_platform_data collie_flash_data = {
|
static struct flash_platform_data collie_flash_data = {
|
||||||
|
@ -111,7 +111,7 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int proc_alignment_write(struct file *file, const char __user *buffer,
|
static int proc_alignment_write(struct file *file, const char __user *buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
char mode;
|
char mode;
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ static int proc_alignment_write(struct file *file, const char __user *buffer,
|
|||||||
if (get_user(mode, buffer))
|
if (get_user(mode, buffer))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (mode >= '0' && mode <= '5')
|
if (mode >= '0' && mode <= '5')
|
||||||
ai_usermode = mode - '0';
|
ai_usermode = mode - '0';
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ union offset_union {
|
|||||||
goto fault; \
|
goto fault; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define put32_unaligned_check(val,addr) \
|
#define put32_unaligned_check(val,addr) \
|
||||||
__put32_unaligned_check("strb", val, addr)
|
__put32_unaligned_check("strb", val, addr)
|
||||||
|
|
||||||
#define put32t_unaligned_check(val,addr) \
|
#define put32t_unaligned_check(val,addr) \
|
||||||
@ -306,19 +306,19 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
|
|||||||
return TYPE_LDST;
|
return TYPE_LDST;
|
||||||
|
|
||||||
user:
|
user:
|
||||||
if (LDST_L_BIT(instr)) {
|
if (LDST_L_BIT(instr)) {
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
get16t_unaligned_check(val, addr);
|
get16t_unaligned_check(val, addr);
|
||||||
|
|
||||||
/* signed half-word? */
|
/* signed half-word? */
|
||||||
if (instr & 0x40)
|
if (instr & 0x40)
|
||||||
val = (signed long)((signed short) val);
|
val = (signed long)((signed short) val);
|
||||||
|
|
||||||
regs->uregs[rd] = val;
|
regs->uregs[rd] = val;
|
||||||
} else
|
} else
|
||||||
put16t_unaligned_check(regs->uregs[rd], addr);
|
put16t_unaligned_check(regs->uregs[rd], addr);
|
||||||
|
|
||||||
return TYPE_LDST;
|
return TYPE_LDST;
|
||||||
|
|
||||||
fault:
|
fault:
|
||||||
return TYPE_FAULT;
|
return TYPE_FAULT;
|
||||||
@ -330,6 +330,9 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
|
|||||||
{
|
{
|
||||||
unsigned int rd = RD_BITS(instr);
|
unsigned int rd = RD_BITS(instr);
|
||||||
|
|
||||||
|
if (((rd & 1) == 1) || (rd == 14))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
ai_dword += 1;
|
ai_dword += 1;
|
||||||
|
|
||||||
if (user_mode(regs))
|
if (user_mode(regs))
|
||||||
@ -339,11 +342,11 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
|
|||||||
unsigned long val;
|
unsigned long val;
|
||||||
get32_unaligned_check(val, addr);
|
get32_unaligned_check(val, addr);
|
||||||
regs->uregs[rd] = val;
|
regs->uregs[rd] = val;
|
||||||
get32_unaligned_check(val, addr+4);
|
get32_unaligned_check(val, addr + 4);
|
||||||
regs->uregs[rd+1] = val;
|
regs->uregs[rd + 1] = val;
|
||||||
} else {
|
} else {
|
||||||
put32_unaligned_check(regs->uregs[rd], addr);
|
put32_unaligned_check(regs->uregs[rd], addr);
|
||||||
put32_unaligned_check(regs->uregs[rd+1], addr+4);
|
put32_unaligned_check(regs->uregs[rd + 1], addr + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TYPE_LDST;
|
return TYPE_LDST;
|
||||||
@ -353,15 +356,16 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
|
|||||||
unsigned long val;
|
unsigned long val;
|
||||||
get32t_unaligned_check(val, addr);
|
get32t_unaligned_check(val, addr);
|
||||||
regs->uregs[rd] = val;
|
regs->uregs[rd] = val;
|
||||||
get32t_unaligned_check(val, addr+4);
|
get32t_unaligned_check(val, addr + 4);
|
||||||
regs->uregs[rd+1] = val;
|
regs->uregs[rd + 1] = val;
|
||||||
} else {
|
} else {
|
||||||
put32t_unaligned_check(regs->uregs[rd], addr);
|
put32t_unaligned_check(regs->uregs[rd], addr);
|
||||||
put32t_unaligned_check(regs->uregs[rd+1], addr+4);
|
put32t_unaligned_check(regs->uregs[rd + 1], addr + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TYPE_LDST;
|
return TYPE_LDST;
|
||||||
|
bad:
|
||||||
|
return TYPE_ERROR;
|
||||||
fault:
|
fault:
|
||||||
return TYPE_FAULT;
|
return TYPE_FAULT;
|
||||||
}
|
}
|
||||||
@ -439,7 +443,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg
|
|||||||
if (LDST_P_EQ_U(instr)) /* U = P */
|
if (LDST_P_EQ_U(instr)) /* U = P */
|
||||||
eaddr += 4;
|
eaddr += 4;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For alignment faults on the ARM922T/ARM920T the MMU makes
|
* For alignment faults on the ARM922T/ARM920T the MMU makes
|
||||||
* the FSR (and hence addr) equal to the updated base address
|
* the FSR (and hence addr) equal to the updated base address
|
||||||
* of the multiple access rather than the restored value.
|
* of the multiple access rather than the restored value.
|
||||||
@ -566,7 +570,7 @@ thumb2arm(u16 tinstr)
|
|||||||
/* 6.5.1 Format 3: */
|
/* 6.5.1 Format 3: */
|
||||||
case 0x4800 >> 11: /* 7.1.28 LDR(3) */
|
case 0x4800 >> 11: /* 7.1.28 LDR(3) */
|
||||||
/* NOTE: This case is not technically possible. We're
|
/* NOTE: This case is not technically possible. We're
|
||||||
* loading 32-bit memory data via PC relative
|
* loading 32-bit memory data via PC relative
|
||||||
* addressing mode. So we can and should eliminate
|
* addressing mode. So we can and should eliminate
|
||||||
* this case. But I'll leave it here for now.
|
* this case. But I'll leave it here for now.
|
||||||
*/
|
*/
|
||||||
@ -638,7 +642,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||||||
|
|
||||||
if (fault) {
|
if (fault) {
|
||||||
type = TYPE_FAULT;
|
type = TYPE_FAULT;
|
||||||
goto bad_or_fault;
|
goto bad_or_fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_mode(regs))
|
if (user_mode(regs))
|
||||||
@ -663,6 +667,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||||||
else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
|
else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
|
||||||
(instr & 0x001000f0) == 0x000000f0) /* STRD */
|
(instr & 0x001000f0) == 0x000000f0) /* STRD */
|
||||||
handler = do_alignment_ldrdstrd;
|
handler = do_alignment_ldrdstrd;
|
||||||
|
else if ((instr & 0x01f00ff0) == 0x01000090) /* SWP */
|
||||||
|
goto swp;
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
break;
|
break;
|
||||||
@ -733,6 +739,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||||||
do_bad_area(current, current->mm, addr, fsr, regs);
|
do_bad_area(current, current->mm, addr, fsr, regs);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
swp:
|
||||||
|
printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
/*
|
/*
|
||||||
* Oops, we didn't handle the instruction.
|
* Oops, we didn't handle the instruction.
|
||||||
|
@ -31,11 +31,6 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
/* forward declarations */
|
|
||||||
unsigned int EmulateCPDO(const unsigned int);
|
|
||||||
unsigned int EmulateCPDT(const unsigned int);
|
|
||||||
unsigned int EmulateCPRT(const unsigned int);
|
|
||||||
|
|
||||||
/* Reset the FPA11 chip. Called to initialize and reset the emulator. */
|
/* Reset the FPA11 chip. Called to initialize and reset the emulator. */
|
||||||
static void resetFPA11(void)
|
static void resetFPA11(void)
|
||||||
{
|
{
|
||||||
|
@ -95,4 +95,24 @@ extern int8 SetRoundingMode(const unsigned int);
|
|||||||
extern int8 SetRoundingPrecision(const unsigned int);
|
extern int8 SetRoundingPrecision(const unsigned int);
|
||||||
extern void nwfpe_init_fpa(union fp_state *fp);
|
extern void nwfpe_init_fpa(union fp_state *fp);
|
||||||
|
|
||||||
|
extern unsigned int EmulateAll(unsigned int opcode);
|
||||||
|
|
||||||
|
extern unsigned int EmulateCPDT(const unsigned int opcode);
|
||||||
|
extern unsigned int EmulateCPDO(const unsigned int opcode);
|
||||||
|
extern unsigned int EmulateCPRT(const unsigned int opcode);
|
||||||
|
|
||||||
|
/* fpa11_cpdt.c */
|
||||||
|
extern unsigned int PerformLDF(const unsigned int opcode);
|
||||||
|
extern unsigned int PerformSTF(const unsigned int opcode);
|
||||||
|
extern unsigned int PerformLFM(const unsigned int opcode);
|
||||||
|
extern unsigned int PerformSFM(const unsigned int opcode);
|
||||||
|
|
||||||
|
/* single_cpdo.c */
|
||||||
|
|
||||||
|
extern unsigned int SingleCPDO(struct roundingData *roundData,
|
||||||
|
const unsigned int opcode, FPREG * rFd);
|
||||||
|
/* double_cpdo.c */
|
||||||
|
extern unsigned int DoubleCPDO(struct roundingData *roundData,
|
||||||
|
const unsigned int opcode, FPREG * rFd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,12 +26,11 @@
|
|||||||
#include "fpa11.inl"
|
#include "fpa11.inl"
|
||||||
#include "fpmodule.h"
|
#include "fpmodule.h"
|
||||||
#include "fpmodule.inl"
|
#include "fpmodule.inl"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
#ifdef CONFIG_FPE_NWFPE_XP
|
#ifdef CONFIG_FPE_NWFPE_XP
|
||||||
extern flag floatx80_is_nan(floatx80);
|
extern flag floatx80_is_nan(floatx80);
|
||||||
#endif
|
#endif
|
||||||
extern flag float64_is_nan(float64);
|
|
||||||
extern flag float32_is_nan(float32);
|
|
||||||
|
|
||||||
unsigned int PerformFLT(const unsigned int opcode);
|
unsigned int PerformFLT(const unsigned int opcode);
|
||||||
unsigned int PerformFIX(const unsigned int opcode);
|
unsigned int PerformFIX(const unsigned int opcode);
|
||||||
|
@ -476,4 +476,10 @@ static inline unsigned int getDestinationSize(const unsigned int opcode)
|
|||||||
return (nRc);
|
return (nRc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned int checkCondition(const unsigned int opcode,
|
||||||
|
const unsigned int ccodes);
|
||||||
|
|
||||||
|
extern const float64 float64Constant[];
|
||||||
|
extern const float32 float32Constant[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -265,4 +265,7 @@ static inline flag float64_lt_nocheck(float64 a, float64 b)
|
|||||||
return (a != b) && (aSign ^ (a < b));
|
return (a != b) && (aSign ^ (a < b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern flag float32_is_nan( float32 a );
|
||||||
|
extern flag float64_is_nan( float64 a );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,11 +2,17 @@
|
|||||||
#
|
#
|
||||||
# This file is linux/arch/arm/tools/mach-types
|
# This file is linux/arch/arm/tools/mach-types
|
||||||
#
|
#
|
||||||
|
# Up to date versions of this file can be obtained from:
|
||||||
|
#
|
||||||
|
# http://www.arm.linux.org.uk/developer/machines/?action=download
|
||||||
|
#
|
||||||
# Please do not send patches to this file; it is automatically generated!
|
# Please do not send patches to this file; it is automatically generated!
|
||||||
# To add an entry into this database, please see Documentation/arm/README,
|
# To add an entry into this database, please see Documentation/arm/README,
|
||||||
# or contact rmk@arm.linux.org.uk
|
# or visit:
|
||||||
#
|
#
|
||||||
# Last update: Thu Jun 23 20:19:33 2005
|
# http://www.arm.linux.org.uk/developer/machines/?action=new
|
||||||
|
#
|
||||||
|
# Last update: Mon Oct 10 09:46:25 2005
|
||||||
#
|
#
|
||||||
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
||||||
#
|
#
|
||||||
@ -421,7 +427,7 @@ mt02 MACH_MT02 MT02 410
|
|||||||
mport3s MACH_MPORT3S MPORT3S 411
|
mport3s MACH_MPORT3S MPORT3S 411
|
||||||
ra_alpha MACH_RA_ALPHA RA_ALPHA 412
|
ra_alpha MACH_RA_ALPHA RA_ALPHA 412
|
||||||
xcep MACH_XCEP XCEP 413
|
xcep MACH_XCEP XCEP 413
|
||||||
arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414
|
arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414
|
||||||
stargate MACH_STARGATE STARGATE 415
|
stargate MACH_STARGATE STARGATE 415
|
||||||
armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
|
armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
|
||||||
elroy_jack MACH_ELROY_JACK ELROY_JACK 417
|
elroy_jack MACH_ELROY_JACK ELROY_JACK 417
|
||||||
@ -454,7 +460,7 @@ esl_sarva MACH_ESL_SARVA ESL_SARVA 443
|
|||||||
xm250 MACH_XM250 XM250 444
|
xm250 MACH_XM250 XM250 444
|
||||||
t6tc1xb MACH_T6TC1XB T6TC1XB 445
|
t6tc1xb MACH_T6TC1XB T6TC1XB 445
|
||||||
ess710 MACH_ESS710 ESS710 446
|
ess710 MACH_ESS710 ESS710 446
|
||||||
mx3ads MACH_MX3ADS MX3ADS 447
|
mx31ads MACH_MX3ADS MX3ADS 447
|
||||||
himalaya MACH_HIMALAYA HIMALAYA 448
|
himalaya MACH_HIMALAYA HIMALAYA 448
|
||||||
bolfenk MACH_BOLFENK BOLFENK 449
|
bolfenk MACH_BOLFENK BOLFENK 449
|
||||||
at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
|
at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
|
||||||
@ -787,3 +793,79 @@ ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778
|
|||||||
tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
|
tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
|
||||||
universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
|
universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
|
||||||
hicoarm9 MACH_HICOARM9 HICOARM9 781
|
hicoarm9 MACH_HICOARM9 HICOARM9 781
|
||||||
|
pnx4008 MACH_PNX4008 PNX4008 782
|
||||||
|
kws6000 MACH_KWS6000 KWS6000 783
|
||||||
|
portux920t MACH_PORTUX920T PORTUX920T 784
|
||||||
|
ez_x5 MACH_EZ_X5 EZ_X5 785
|
||||||
|
omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786
|
||||||
|
cpuat91 MACH_CPUAT91 CPUAT91 787
|
||||||
|
rea9200 MACH_REA9200 REA9200 788
|
||||||
|
acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
|
||||||
|
ixp425 MACH_IXP425 IXP425 790
|
||||||
|
argonplusodyssey MACH_ODYSSEY ODYSSEY 791
|
||||||
|
perch MACH_PERCH PERCH 792
|
||||||
|
eis05r1 MACH_EIS05R1 EIS05R1 793
|
||||||
|
pepperpad MACH_PEPPERPAD PEPPERPAD 794
|
||||||
|
sb3010 MACH_SB3010 SB3010 795
|
||||||
|
rm9200 MACH_RM9200 RM9200 796
|
||||||
|
dma03 MACH_DMA03 DMA03 797
|
||||||
|
road_s101 MACH_ROAD_S101 ROAD_S101 798
|
||||||
|
iq_nextgen_a MACH_IQ_NEXTGEN_A IQ_NEXTGEN_A 799
|
||||||
|
iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800
|
||||||
|
iq_nextgen_c MACH_IQ_NEXTGEN_C IQ_NEXTGEN_C 801
|
||||||
|
iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802
|
||||||
|
iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803
|
||||||
|
mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804
|
||||||
|
cybertracker MACH_CYBERTRACKER CYBERTRACKER 805
|
||||||
|
gesbc931x MACH_GESBC931X GESBC931X 806
|
||||||
|
centipad MACH_CENTIPAD CENTIPAD 807
|
||||||
|
armsoc MACH_ARMSOC ARMSOC 808
|
||||||
|
se4200 MACH_SE4200 SE4200 809
|
||||||
|
ems197a MACH_EMS197A EMS197A 810
|
||||||
|
micro9 MACH_MICRO9 MICRO9 811
|
||||||
|
micro9l MACH_MICRO9L MICRO9L 812
|
||||||
|
uc5471dsp MACH_UC5471DSP UC5471DSP 813
|
||||||
|
sj5471eng MACH_SJ5471ENG SJ5471ENG 814
|
||||||
|
none MACH_CMPXA26X CMPXA26X 815
|
||||||
|
nc MACH_NC NC 816
|
||||||
|
omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817
|
||||||
|
ajax52x MACH_AJAX52X AJAX52X 818
|
||||||
|
siriustar MACH_SIRIUSTAR SIRIUSTAR 819
|
||||||
|
iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820
|
||||||
|
at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821
|
||||||
|
biosafe MACH_BIOSAFE BIOSAFE 822
|
||||||
|
mp1000 MACH_MP1000 MP1000 823
|
||||||
|
parsy MACH_PARSY PARSY 824
|
||||||
|
ccxp270 MACH_CCXP CCXP 825
|
||||||
|
omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826
|
||||||
|
realview_eb MACH_REALVIEW_EB REALVIEW_EB 827
|
||||||
|
samoa MACH_SAMOA SAMOA 828
|
||||||
|
t3xscale MACH_T3XSCALE T3XSCALE 829
|
||||||
|
i878 MACH_I878 I878 830
|
||||||
|
borzoi MACH_BORZOI BORZOI 831
|
||||||
|
gecko MACH_GECKO GECKO 832
|
||||||
|
ds101 MACH_DS101 DS101 833
|
||||||
|
omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834
|
||||||
|
xscale_palmld MACH_XSCALE_PALMLD XSCALE_PALMLD 835
|
||||||
|
cc9c MACH_CC9C CC9C 836
|
||||||
|
sbc1670 MACH_SBC1670 SBC1670 837
|
||||||
|
ixdp28x5 MACH_IXDP28X5 IXDP28X5 838
|
||||||
|
omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839
|
||||||
|
ml696k MACH_ML696K ML696K 840
|
||||||
|
arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841
|
||||||
|
osiris MACH_OSIRIS OSIRIS 842
|
||||||
|
maestro MACH_MAESTRO MAESTRO 843
|
||||||
|
tunge2 MACH_TUNGE2 TUNGE2 844
|
||||||
|
ixbbm MACH_IXBBM IXBBM 845
|
||||||
|
mx27 MACH_MX27 MX27 846
|
||||||
|
ax8004 MACH_AX8004 AX8004 847
|
||||||
|
at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848
|
||||||
|
loft MACH_LOFT LOFT 849
|
||||||
|
magpie MACH_MAGPIE MAGPIE 850
|
||||||
|
mx21 MACH_MX21 MX21 851
|
||||||
|
mb87m3400 MACH_MB87M3400 MB87M3400 852
|
||||||
|
mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853
|
||||||
|
davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854
|
||||||
|
htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855
|
||||||
|
tpad MACH_TPAD TPAD 856
|
||||||
|
roverp3 MACH_ROVERP3 ROVERP3 857
|
||||||
|
@ -24,7 +24,7 @@ struct dma_coherent_mem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast gfp)
|
dma_addr_t *dma_handle, gfp_t gfp)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
#define IPI_SCHEDULE 1
|
#define IPI_SCHEDULE 1
|
||||||
#define IPI_CALL 2
|
#define IPI_CALL 2
|
||||||
@ -28,6 +29,7 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
|
|||||||
/* CPU masks */
|
/* CPU masks */
|
||||||
cpumask_t cpu_online_map = CPU_MASK_NONE;
|
cpumask_t cpu_online_map = CPU_MASK_NONE;
|
||||||
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
|
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
|
||||||
|
EXPORT_SYMBOL(phys_cpu_present_map);
|
||||||
|
|
||||||
/* Variables used during SMP boot */
|
/* Variables used during SMP boot */
|
||||||
volatile int cpu_now_booting = 0;
|
volatile int cpu_now_booting = 0;
|
||||||
|
@ -29,7 +29,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
unsigned long value;
|
unsigned long long value;
|
||||||
|
|
||||||
/* Disable TLB flush filter by setting HWCR.FFDIS on K8
|
/* Disable TLB flush filter by setting HWCR.FFDIS on K8
|
||||||
* bit 6 of msr C001_0015
|
* bit 6 of msr C001_0015
|
||||||
|
@ -23,7 +23,7 @@ struct dma_coherent_mem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast gfp)
|
dma_addr_t *dma_handle, gfp_t gfp)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||||
|
@ -338,7 +338,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
|
|||||||
esp = (unsigned long) ka->sa.sa_restorer;
|
esp = (unsigned long) ka->sa.sa_restorer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void __user *)((esp - frame_size) & -8ul);
|
esp -= frame_size;
|
||||||
|
/* Align the stack pointer according to the i386 ABI,
|
||||||
|
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
|
||||||
|
esp = ((esp + 4) & -16ul) - 4;
|
||||||
|
return (void __user *) esp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These symbols are defined with the addresses in the vsyscall page.
|
/* These symbols are defined with the addresses in the vsyscall page.
|
||||||
|
@ -681,6 +681,15 @@ ENTRY(debug_trap)
|
|||||||
bl do_debug_trap
|
bl do_debug_trap
|
||||||
bra error_code
|
bra error_code
|
||||||
|
|
||||||
|
ENTRY(ill_trap)
|
||||||
|
/* void ill_trap(void) */
|
||||||
|
SWITCH_TO_KERNEL_STACK
|
||||||
|
SAVE_ALL
|
||||||
|
ldi r1, #0 ; error_code ; FIXME
|
||||||
|
mv r0, sp ; pt_regs
|
||||||
|
bl do_ill_trap
|
||||||
|
bra error_code
|
||||||
|
|
||||||
|
|
||||||
/* Cache flushing handler */
|
/* Cache flushing handler */
|
||||||
ENTRY(cache_flushing_handler)
|
ENTRY(cache_flushing_handler)
|
||||||
|
@ -275,12 +275,14 @@ static void flush_tlb_all_ipi(void *info)
|
|||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
void smp_flush_tlb_mm(struct mm_struct *mm)
|
void smp_flush_tlb_mm(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
int cpu_id = smp_processor_id();
|
int cpu_id;
|
||||||
cpumask_t cpu_mask;
|
cpumask_t cpu_mask;
|
||||||
unsigned long *mmc = &mm->context[cpu_id];
|
unsigned long *mmc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
cpu_id = smp_processor_id();
|
||||||
|
mmc = &mm->context[cpu_id];
|
||||||
cpu_mask = mm->cpu_vm_mask;
|
cpu_mask = mm->cpu_vm_mask;
|
||||||
cpu_clear(cpu_id, cpu_mask);
|
cpu_clear(cpu_id, cpu_mask);
|
||||||
|
|
||||||
@ -343,12 +345,14 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
|||||||
void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
|
void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = vma->vm_mm;
|
struct mm_struct *mm = vma->vm_mm;
|
||||||
int cpu_id = smp_processor_id();
|
int cpu_id;
|
||||||
cpumask_t cpu_mask;
|
cpumask_t cpu_mask;
|
||||||
unsigned long *mmc = &mm->context[cpu_id];
|
unsigned long *mmc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
cpu_id = smp_processor_id();
|
||||||
|
mmc = &mm->context[cpu_id];
|
||||||
cpu_mask = mm->cpu_vm_mask;
|
cpu_mask = mm->cpu_vm_mask;
|
||||||
cpu_clear(cpu_id, cpu_mask);
|
cpu_clear(cpu_id, cpu_mask);
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
* Hitoshi Yamamoto
|
* Hitoshi Yamamoto
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id$ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'traps.c' handles hardware traps and faults after we have saved some
|
* 'traps.c' handles hardware traps and faults after we have saved some
|
||||||
* state in 'entry.S'.
|
* state in 'entry.S'.
|
||||||
@ -35,6 +33,7 @@ asmlinkage void ei_handler(void);
|
|||||||
asmlinkage void rie_handler(void);
|
asmlinkage void rie_handler(void);
|
||||||
asmlinkage void debug_trap(void);
|
asmlinkage void debug_trap(void);
|
||||||
asmlinkage void cache_flushing_handler(void);
|
asmlinkage void cache_flushing_handler(void);
|
||||||
|
asmlinkage void ill_trap(void);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
extern void smp_reschedule_interrupt(void);
|
extern void smp_reschedule_interrupt(void);
|
||||||
@ -77,22 +76,22 @@ void set_eit_vector_entries(void)
|
|||||||
eit_vector[5] = BRA_INSN(default_eit_handler, 5);
|
eit_vector[5] = BRA_INSN(default_eit_handler, 5);
|
||||||
eit_vector[8] = BRA_INSN(rie_handler, 8);
|
eit_vector[8] = BRA_INSN(rie_handler, 8);
|
||||||
eit_vector[12] = BRA_INSN(alignment_check, 12);
|
eit_vector[12] = BRA_INSN(alignment_check, 12);
|
||||||
eit_vector[16] = 0xff000000UL;
|
eit_vector[16] = BRA_INSN(ill_trap, 16);
|
||||||
eit_vector[17] = BRA_INSN(debug_trap, 17);
|
eit_vector[17] = BRA_INSN(debug_trap, 17);
|
||||||
eit_vector[18] = BRA_INSN(system_call, 18);
|
eit_vector[18] = BRA_INSN(system_call, 18);
|
||||||
eit_vector[19] = 0xff000000UL;
|
eit_vector[19] = BRA_INSN(ill_trap, 19);
|
||||||
eit_vector[20] = 0xff000000UL;
|
eit_vector[20] = BRA_INSN(ill_trap, 20);
|
||||||
eit_vector[21] = 0xff000000UL;
|
eit_vector[21] = BRA_INSN(ill_trap, 21);
|
||||||
eit_vector[22] = 0xff000000UL;
|
eit_vector[22] = BRA_INSN(ill_trap, 22);
|
||||||
eit_vector[23] = 0xff000000UL;
|
eit_vector[23] = BRA_INSN(ill_trap, 23);
|
||||||
eit_vector[24] = 0xff000000UL;
|
eit_vector[24] = BRA_INSN(ill_trap, 24);
|
||||||
eit_vector[25] = 0xff000000UL;
|
eit_vector[25] = BRA_INSN(ill_trap, 25);
|
||||||
eit_vector[26] = 0xff000000UL;
|
eit_vector[26] = BRA_INSN(ill_trap, 26);
|
||||||
eit_vector[27] = 0xff000000UL;
|
eit_vector[27] = BRA_INSN(ill_trap, 27);
|
||||||
eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
|
eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
|
||||||
eit_vector[29] = 0xff000000UL;
|
eit_vector[29] = BRA_INSN(ill_trap, 29);
|
||||||
eit_vector[30] = 0xff000000UL;
|
eit_vector[30] = BRA_INSN(ill_trap, 30);
|
||||||
eit_vector[31] = 0xff000000UL;
|
eit_vector[31] = BRA_INSN(ill_trap, 31);
|
||||||
eit_vector[32] = BRA_INSN(ei_handler, 32);
|
eit_vector[32] = BRA_INSN(ei_handler, 32);
|
||||||
eit_vector[64] = BRA_INSN(pie_handler, 64);
|
eit_vector[64] = BRA_INSN(pie_handler, 64);
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
@ -286,7 +285,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
|
|||||||
|
|
||||||
DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
|
DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
|
||||||
DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
|
DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
|
||||||
DO_ERROR_INFO(0x100, SIGILL, "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc)
|
DO_ERROR_INFO(0x100, SIGILL, "privileged instruction", pie_handler, ILL_PRVOPC, regs->bpc)
|
||||||
|
DO_ERROR_INFO(-1, SIGILL, "illegal trap", ill_trap, ILL_ILLTRP, regs->bpc)
|
||||||
|
|
||||||
extern int handle_unaligned_access(unsigned long, struct pt_regs *);
|
extern int handle_unaligned_access(unsigned long, struct pt_regs *);
|
||||||
|
|
||||||
@ -329,4 +329,3 @@ asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code)
|
|||||||
set_fs(oldfs);
|
set_fs(oldfs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
|
* fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
|
* Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
|
||||||
|
#include <asm/vr41xx/giu.h>
|
||||||
#include <asm/vr41xx/tb0226.h>
|
#include <asm/vr41xx/tb0226.h>
|
||||||
|
|
||||||
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||||
@ -29,42 +30,42 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
|||||||
switch (slot) {
|
switch (slot) {
|
||||||
case 12:
|
case 12:
|
||||||
vr41xx_set_irq_trigger(GD82559_1_PIN,
|
vr41xx_set_irq_trigger(GD82559_1_PIN,
|
||||||
TRIGGER_LEVEL,
|
IRQ_TRIGGER_LEVEL,
|
||||||
SIGNAL_THROUGH);
|
IRQ_SIGNAL_THROUGH);
|
||||||
vr41xx_set_irq_level(GD82559_1_PIN, LEVEL_LOW);
|
vr41xx_set_irq_level(GD82559_1_PIN, IRQ_LEVEL_LOW);
|
||||||
irq = GD82559_1_IRQ;
|
irq = GD82559_1_IRQ;
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
vr41xx_set_irq_trigger(GD82559_2_PIN,
|
vr41xx_set_irq_trigger(GD82559_2_PIN,
|
||||||
TRIGGER_LEVEL,
|
IRQ_TRIGGER_LEVEL,
|
||||||
SIGNAL_THROUGH);
|
IRQ_SIGNAL_THROUGH);
|
||||||
vr41xx_set_irq_level(GD82559_2_PIN, LEVEL_LOW);
|
vr41xx_set_irq_level(GD82559_2_PIN, IRQ_LEVEL_LOW);
|
||||||
irq = GD82559_2_IRQ;
|
irq = GD82559_2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
switch (pin) {
|
switch (pin) {
|
||||||
case 1:
|
case 1:
|
||||||
vr41xx_set_irq_trigger(UPD720100_INTA_PIN,
|
vr41xx_set_irq_trigger(UPD720100_INTA_PIN,
|
||||||
TRIGGER_LEVEL,
|
IRQ_TRIGGER_LEVEL,
|
||||||
SIGNAL_THROUGH);
|
IRQ_SIGNAL_THROUGH);
|
||||||
vr41xx_set_irq_level(UPD720100_INTA_PIN,
|
vr41xx_set_irq_level(UPD720100_INTA_PIN,
|
||||||
LEVEL_LOW);
|
IRQ_LEVEL_LOW);
|
||||||
irq = UPD720100_INTA_IRQ;
|
irq = UPD720100_INTA_IRQ;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
vr41xx_set_irq_trigger(UPD720100_INTB_PIN,
|
vr41xx_set_irq_trigger(UPD720100_INTB_PIN,
|
||||||
TRIGGER_LEVEL,
|
IRQ_TRIGGER_LEVEL,
|
||||||
SIGNAL_THROUGH);
|
IRQ_SIGNAL_THROUGH);
|
||||||
vr41xx_set_irq_level(UPD720100_INTB_PIN,
|
vr41xx_set_irq_level(UPD720100_INTB_PIN,
|
||||||
LEVEL_LOW);
|
IRQ_LEVEL_LOW);
|
||||||
irq = UPD720100_INTB_IRQ;
|
irq = UPD720100_INTB_IRQ;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
vr41xx_set_irq_trigger(UPD720100_INTC_PIN,
|
vr41xx_set_irq_trigger(UPD720100_INTC_PIN,
|
||||||
TRIGGER_LEVEL,
|
IRQ_TRIGGER_LEVEL,
|
||||||
SIGNAL_THROUGH);
|
IRQ_SIGNAL_THROUGH);
|
||||||
vr41xx_set_irq_level(UPD720100_INTC_PIN,
|
vr41xx_set_irq_level(UPD720100_INTC_PIN,
|
||||||
LEVEL_LOW);
|
IRQ_LEVEL_LOW);
|
||||||
irq = UPD720100_INTC_IRQ;
|
irq = UPD720100_INTC_IRQ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -91,7 +91,7 @@ struct cpu_spec cpu_specs[] = {
|
|||||||
.cpu_features = CPU_FTR_COMMON | CPU_FTR_601 |
|
.cpu_features = CPU_FTR_COMMON | CPU_FTR_601 |
|
||||||
CPU_FTR_HPTE_TABLE,
|
CPU_FTR_HPTE_TABLE,
|
||||||
.cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR |
|
.cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR |
|
||||||
PPC_FEATURE_UNIFIED_CACHE,
|
PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
|
||||||
.icache_bsize = 32,
|
.icache_bsize = 32,
|
||||||
.dcache_bsize = 32,
|
.dcache_bsize = 32,
|
||||||
.cpu_setup = __setup_cpu_601
|
.cpu_setup = __setup_cpu_601
|
||||||
@ -745,7 +745,8 @@ struct cpu_spec cpu_specs[] = {
|
|||||||
.cpu_name = "403GCX",
|
.cpu_name = "403GCX",
|
||||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||||
CPU_FTR_USE_TB,
|
CPU_FTR_USE_TB,
|
||||||
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
|
.cpu_user_features = PPC_FEATURE_32 |
|
||||||
|
PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
|
||||||
.icache_bsize = 16,
|
.icache_bsize = 16,
|
||||||
.dcache_bsize = 16,
|
.dcache_bsize = 16,
|
||||||
},
|
},
|
||||||
|
@ -401,10 +401,10 @@ EXPORT_SYMBOL(__dma_sync);
|
|||||||
static inline void __dma_sync_page_highmem(struct page *page,
|
static inline void __dma_sync_page_highmem(struct page *page,
|
||||||
unsigned long offset, size_t size, int direction)
|
unsigned long offset, size_t size, int direction)
|
||||||
{
|
{
|
||||||
size_t seg_size = min((size_t)PAGE_SIZE, size) - offset;
|
size_t seg_size = min((size_t)(PAGE_SIZE - offset), size);
|
||||||
size_t cur_size = seg_size;
|
size_t cur_size = seg_size;
|
||||||
unsigned long flags, start, seg_offset = offset;
|
unsigned long flags, start, seg_offset = offset;
|
||||||
int nr_segs = PAGE_ALIGN(size + (PAGE_SIZE - offset))/PAGE_SIZE;
|
int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE;
|
||||||
int seg_nr = 0;
|
int seg_nr = 0;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
@ -310,7 +310,7 @@ static void bpa_map_iommu(void)
|
|||||||
|
|
||||||
|
|
||||||
static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
|
static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
|
|||||||
EXPORT_SYMBOL(dma_set_mask);
|
EXPORT_SYMBOL(dma_set_mask);
|
||||||
|
|
||||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||||
|
|
||||||
|
@ -519,7 +519,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
|
|||||||
* to the dma address (mapping) of the first page.
|
* to the dma address (mapping) of the first page.
|
||||||
*/
|
*/
|
||||||
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
|
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
dma_addr_t mapping;
|
dma_addr_t mapping;
|
||||||
|
@ -341,6 +341,19 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
|||||||
*(unsigned long *)location = my_r2(sechdrs, me);
|
*(unsigned long *)location = my_r2(sechdrs, me);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_PPC64_TOC16:
|
||||||
|
/* Subtact TOC pointer */
|
||||||
|
value -= my_r2(sechdrs, me);
|
||||||
|
if (value + 0x8000 > 0xffff) {
|
||||||
|
printk("%s: bad TOC16 relocation (%lu)\n",
|
||||||
|
me->name, value);
|
||||||
|
return -ENOEXEC;
|
||||||
|
}
|
||||||
|
*((uint16_t *) location)
|
||||||
|
= (*((uint16_t *) location) & ~0xffff)
|
||||||
|
| (value & 0xffff);
|
||||||
|
break;
|
||||||
|
|
||||||
case R_PPC64_TOC16_DS:
|
case R_PPC64_TOC16_DS:
|
||||||
/* Subtact TOC pointer */
|
/* Subtact TOC pointer */
|
||||||
value -= my_r2(sechdrs, me);
|
value -= my_r2(sechdrs, me);
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
static int __initdata s7a_workaround = -1;
|
static int __devinitdata s7a_workaround = -1;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void pcibios_name_device(struct pci_dev *dev)
|
void pcibios_name_device(struct pci_dev *dev)
|
||||||
@ -60,7 +60,7 @@ void pcibios_name_device(struct pci_dev *dev)
|
|||||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
|
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void __init check_s7a(void)
|
static void __devinit check_s7a(void)
|
||||||
{
|
{
|
||||||
struct device_node *root;
|
struct device_node *root;
|
||||||
char *model;
|
char *model;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
|
static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ static inline struct iommu_table *devnode_table(struct device *dev)
|
|||||||
* to the dma address (mapping) of the first page.
|
* to the dma address (mapping) of the first page.
|
||||||
*/
|
*/
|
||||||
static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
|
static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
|
return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
|
||||||
flag);
|
flag);
|
||||||
|
@ -115,7 +115,7 @@ static void __pmac pmac_show_cpuinfo(struct seq_file *m)
|
|||||||
|
|
||||||
/* find motherboard type */
|
/* find motherboard type */
|
||||||
seq_printf(m, "machine\t\t: ");
|
seq_printf(m, "machine\t\t: ");
|
||||||
np = find_devices("device-tree");
|
np = of_find_node_by_path("/");
|
||||||
if (np != NULL) {
|
if (np != NULL) {
|
||||||
pp = (char *) get_property(np, "model", NULL);
|
pp = (char *) get_property(np, "model", NULL);
|
||||||
if (pp != NULL)
|
if (pp != NULL)
|
||||||
@ -133,6 +133,7 @@ static void __pmac pmac_show_cpuinfo(struct seq_file *m)
|
|||||||
}
|
}
|
||||||
seq_printf(m, "\n");
|
seq_printf(m, "\n");
|
||||||
}
|
}
|
||||||
|
of_node_put(np);
|
||||||
} else
|
} else
|
||||||
seq_printf(m, "PowerMac\n");
|
seq_printf(m, "PowerMac\n");
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *vio_alloc_coherent(struct device *dev, size_t size,
|
static void *vio_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, unsigned int __nocast flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
{
|
{
|
||||||
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
|
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
|
||||||
dma_handle, flag);
|
dma_handle, flag);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/timex.h>
|
#include <linux/timex.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
@ -39,6 +40,8 @@ struct sh_cpuinfo cpu_data[NR_CPUS];
|
|||||||
extern void per_cpu_trap_init(void);
|
extern void per_cpu_trap_init(void);
|
||||||
|
|
||||||
cpumask_t cpu_possible_map;
|
cpumask_t cpu_possible_map;
|
||||||
|
EXPORT_SYMBOL(cpu_possible_map);
|
||||||
|
|
||||||
cpumask_t cpu_online_map;
|
cpumask_t cpu_online_map;
|
||||||
static atomic_t cpus_booted = ATOMIC_INIT(0);
|
static atomic_t cpus_booted = ATOMIC_INIT(0);
|
||||||
|
|
||||||
|
@ -53,19 +53,18 @@
|
|||||||
* be guaranteed to be 0 ... mmu_context.h does guarantee this
|
* be guaranteed to be 0 ... mmu_context.h does guarantee this
|
||||||
* by only using 10 bits in the hwcontext value.
|
* by only using 10 bits in the hwcontext value.
|
||||||
*/
|
*/
|
||||||
#define CREATE_VPTE_OFFSET1(r1, r2)
|
#define CREATE_VPTE_OFFSET1(r1, r2) nop
|
||||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||||
srax r1, 10, r2
|
srax r1, 10, r2
|
||||||
#define CREATE_VPTE_NOP nop
|
|
||||||
#else
|
#else
|
||||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||||
srax r1, PAGE_SHIFT, r2
|
srax r1, PAGE_SHIFT, r2
|
||||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||||
sllx r2, 3, r2
|
sllx r2, 3, r2
|
||||||
#define CREATE_VPTE_NOP
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DTLB ** ICACHE line 1: Quick user TLB misses */
|
/* DTLB ** ICACHE line 1: Quick user TLB misses */
|
||||||
|
mov TLB_SFSR, %g1
|
||||||
ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
|
ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
|
||||||
andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus?
|
andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus?
|
||||||
from_tl1_trap:
|
from_tl1_trap:
|
||||||
@ -74,18 +73,16 @@ from_tl1_trap:
|
|||||||
be,pn %xcc, kvmap ! Yep, special processing
|
be,pn %xcc, kvmap ! Yep, special processing
|
||||||
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
||||||
cmp %g5, 4 ! Last trap level?
|
cmp %g5, 4 ! Last trap level?
|
||||||
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
|
|
||||||
nop ! delay slot
|
|
||||||
|
|
||||||
/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
|
/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
|
||||||
|
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
|
||||||
|
nop ! delay slot
|
||||||
ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
|
ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
|
||||||
1: brgez,pn %g5, longpath ! Invalid, branch out
|
1: brgez,pn %g5, longpath ! Invalid, branch out
|
||||||
nop ! Delay-slot
|
nop ! Delay-slot
|
||||||
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
||||||
retry ! Trap return
|
retry ! Trap return
|
||||||
nop
|
nop
|
||||||
nop
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* DTLB ** ICACHE line 3: winfixups+real_faults */
|
/* DTLB ** ICACHE line 3: winfixups+real_faults */
|
||||||
longpath:
|
longpath:
|
||||||
@ -106,8 +103,7 @@ longpath:
|
|||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
CREATE_VPTE_NOP
|
nop
|
||||||
|
|
||||||
#undef CREATE_VPTE_OFFSET1
|
#undef CREATE_VPTE_OFFSET1
|
||||||
#undef CREATE_VPTE_OFFSET2
|
#undef CREATE_VPTE_OFFSET2
|
||||||
#undef CREATE_VPTE_NOP
|
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* PROT ** ICACHE line 1: User DTLB protection trap */
|
/* PROT ** ICACHE line 1: User DTLB protection trap */
|
||||||
stxa %g0, [%g1] ASI_DMMU ! Clear SFSR FaultValid bit
|
mov TLB_SFSR, %g1
|
||||||
membar #Sync ! Synchronize ASI stores
|
stxa %g0, [%g1] ASI_DMMU ! Clear FaultValid bit
|
||||||
rdpr %pstate, %g5 ! Move into alternate globals
|
membar #Sync ! Synchronize stores
|
||||||
|
rdpr %pstate, %g5 ! Move into alt-globals
|
||||||
wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate
|
wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate
|
||||||
rdpr %tl, %g1 ! Need to do a winfixup?
|
rdpr %tl, %g1 ! Need a winfixup?
|
||||||
cmp %g1, 1 ! Trap level >1?
|
cmp %g1, 1 ! Trap level >1?
|
||||||
mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr
|
mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr
|
||||||
nop
|
|
||||||
|
|
||||||
/* PROT ** ICACHE line 2: More real fault processing */
|
/* PROT ** ICACHE line 2: More real fault processing */
|
||||||
bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup
|
bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
/* This is trivial with the new code... */
|
/* This is trivial with the new code... */
|
||||||
.globl do_fpdis
|
.globl do_fpdis
|
||||||
do_fpdis:
|
do_fpdis:
|
||||||
sethi %hi(TSTATE_PEF), %g4 ! IEU0
|
sethi %hi(TSTATE_PEF), %g4
|
||||||
rdpr %tstate, %g5
|
rdpr %tstate, %g5
|
||||||
andcc %g5, %g4, %g0
|
andcc %g5, %g4, %g0
|
||||||
be,pt %xcc, 1f
|
be,pt %xcc, 1f
|
||||||
@ -50,18 +50,18 @@ do_fpdis:
|
|||||||
add %g0, %g0, %g0
|
add %g0, %g0, %g0
|
||||||
ba,a,pt %xcc, rtrap_clr_l6
|
ba,a,pt %xcc, rtrap_clr_l6
|
||||||
|
|
||||||
1: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group
|
1: ldub [%g6 + TI_FPSAVED], %g5
|
||||||
wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles
|
wr %g0, FPRS_FEF, %fprs
|
||||||
andcc %g5, FPRS_FEF, %g0 ! IEU1 Group
|
andcc %g5, FPRS_FEF, %g0
|
||||||
be,a,pt %icc, 1f ! CTI
|
be,a,pt %icc, 1f
|
||||||
clr %g7 ! IEU0
|
clr %g7
|
||||||
ldx [%g6 + TI_GSR], %g7 ! Load Group
|
ldx [%g6 + TI_GSR], %g7
|
||||||
1: andcc %g5, FPRS_DL, %g0 ! IEU1
|
1: andcc %g5, FPRS_DL, %g0
|
||||||
bne,pn %icc, 2f ! CTI
|
bne,pn %icc, 2f
|
||||||
fzero %f0 ! FPA
|
fzero %f0
|
||||||
andcc %g5, FPRS_DU, %g0 ! IEU1 Group
|
andcc %g5, FPRS_DU, %g0
|
||||||
bne,pn %icc, 1f ! CTI
|
bne,pn %icc, 1f
|
||||||
fzero %f2 ! FPA
|
fzero %f2
|
||||||
faddd %f0, %f2, %f4
|
faddd %f0, %f2, %f4
|
||||||
fmuld %f0, %f2, %f6
|
fmuld %f0, %f2, %f6
|
||||||
faddd %f0, %f2, %f8
|
faddd %f0, %f2, %f8
|
||||||
@ -104,8 +104,10 @@ do_fpdis:
|
|||||||
add %g6, TI_FPREGS + 0xc0, %g2
|
add %g6, TI_FPREGS + 0xc0, %g2
|
||||||
faddd %f0, %f2, %f8
|
faddd %f0, %f2, %f8
|
||||||
fmuld %f0, %f2, %f10
|
fmuld %f0, %f2, %f10
|
||||||
ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-(
|
membar #Sync
|
||||||
|
ldda [%g1] ASI_BLK_S, %f32
|
||||||
ldda [%g2] ASI_BLK_S, %f48
|
ldda [%g2] ASI_BLK_S, %f48
|
||||||
|
membar #Sync
|
||||||
faddd %f0, %f2, %f12
|
faddd %f0, %f2, %f12
|
||||||
fmuld %f0, %f2, %f14
|
fmuld %f0, %f2, %f14
|
||||||
faddd %f0, %f2, %f16
|
faddd %f0, %f2, %f16
|
||||||
@ -116,7 +118,6 @@ do_fpdis:
|
|||||||
fmuld %f0, %f2, %f26
|
fmuld %f0, %f2, %f26
|
||||||
faddd %f0, %f2, %f28
|
faddd %f0, %f2, %f28
|
||||||
fmuld %f0, %f2, %f30
|
fmuld %f0, %f2, %f30
|
||||||
membar #Sync
|
|
||||||
b,pt %xcc, fpdis_exit
|
b,pt %xcc, fpdis_exit
|
||||||
nop
|
nop
|
||||||
2: andcc %g5, FPRS_DU, %g0
|
2: andcc %g5, FPRS_DU, %g0
|
||||||
@ -133,8 +134,10 @@ do_fpdis:
|
|||||||
add %g6, TI_FPREGS + 0x40, %g2
|
add %g6, TI_FPREGS + 0x40, %g2
|
||||||
faddd %f32, %f34, %f36
|
faddd %f32, %f34, %f36
|
||||||
fmuld %f32, %f34, %f38
|
fmuld %f32, %f34, %f38
|
||||||
ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-(
|
membar #Sync
|
||||||
|
ldda [%g1] ASI_BLK_S, %f0
|
||||||
ldda [%g2] ASI_BLK_S, %f16
|
ldda [%g2] ASI_BLK_S, %f16
|
||||||
|
membar #Sync
|
||||||
faddd %f32, %f34, %f40
|
faddd %f32, %f34, %f40
|
||||||
fmuld %f32, %f34, %f42
|
fmuld %f32, %f34, %f42
|
||||||
faddd %f32, %f34, %f44
|
faddd %f32, %f34, %f44
|
||||||
@ -147,7 +150,6 @@ do_fpdis:
|
|||||||
fmuld %f32, %f34, %f58
|
fmuld %f32, %f34, %f58
|
||||||
faddd %f32, %f34, %f60
|
faddd %f32, %f34, %f60
|
||||||
fmuld %f32, %f34, %f62
|
fmuld %f32, %f34, %f62
|
||||||
membar #Sync
|
|
||||||
ba,pt %xcc, fpdis_exit
|
ba,pt %xcc, fpdis_exit
|
||||||
nop
|
nop
|
||||||
3: mov SECONDARY_CONTEXT, %g3
|
3: mov SECONDARY_CONTEXT, %g3
|
||||||
@ -158,7 +160,8 @@ do_fpdis:
|
|||||||
stxa %g2, [%g3] ASI_DMMU
|
stxa %g2, [%g3] ASI_DMMU
|
||||||
membar #Sync
|
membar #Sync
|
||||||
mov 0x40, %g2
|
mov 0x40, %g2
|
||||||
ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-(
|
membar #Sync
|
||||||
|
ldda [%g1] ASI_BLK_S, %f0
|
||||||
ldda [%g1 + %g2] ASI_BLK_S, %f16
|
ldda [%g1 + %g2] ASI_BLK_S, %f16
|
||||||
add %g1, 0x80, %g1
|
add %g1, 0x80, %g1
|
||||||
ldda [%g1] ASI_BLK_S, %f32
|
ldda [%g1] ASI_BLK_S, %f32
|
||||||
|
@ -28,19 +28,14 @@
|
|||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
|
|
||||||
/* This section from from _start to sparc64_boot_end should fit into
|
/* This section from from _start to sparc64_boot_end should fit into
|
||||||
* 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
|
* 0x0000000000404000 to 0x0000000000408000.
|
||||||
* with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
|
|
||||||
* 0x0000.0000.0040.6000 and empty_bad_page, which is from
|
|
||||||
* 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.globl start, _start, stext, _stext
|
.globl start, _start, stext, _stext
|
||||||
_start:
|
_start:
|
||||||
start:
|
start:
|
||||||
_stext:
|
_stext:
|
||||||
stext:
|
stext:
|
||||||
bootup_user_stack:
|
|
||||||
! 0x0000000000404000
|
! 0x0000000000404000
|
||||||
b sparc64_boot
|
b sparc64_boot
|
||||||
flushw /* Flush register file. */
|
flushw /* Flush register file. */
|
||||||
@ -191,8 +186,9 @@ prom_boot_mapping_phys_low:
|
|||||||
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
|
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
|
||||||
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
|
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
|
||||||
stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
|
stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
|
||||||
srlx %l0, 22, %l3
|
/* PAGE align */
|
||||||
sllx %l3, 22, %l3
|
srlx %l0, 13, %l3
|
||||||
|
sllx %l3, 13, %l3
|
||||||
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
|
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
|
||||||
stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
|
stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
|
||||||
stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
|
stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
|
||||||
@ -211,6 +207,9 @@ prom_boot_mapping_phys_low:
|
|||||||
ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
|
ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
|
||||||
stx %l2, [%l4 + 0x0]
|
stx %l2, [%l4 + 0x0]
|
||||||
ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
|
ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
|
||||||
|
/* 4MB align */
|
||||||
|
srlx %l3, 22, %l3
|
||||||
|
sllx %l3, 22, %l3
|
||||||
stx %l3, [%l4 + 0x8]
|
stx %l3, [%l4 + 0x8]
|
||||||
|
|
||||||
/* Leave service as-is, "call-method" */
|
/* Leave service as-is, "call-method" */
|
||||||
@ -382,32 +381,78 @@ tlb_fixup_done:
|
|||||||
nop
|
nop
|
||||||
/* Not reached... */
|
/* Not reached... */
|
||||||
|
|
||||||
/* IMPORTANT NOTE: Whenever making changes here, check
|
/* This is meant to allow the sharing of this code between
|
||||||
* trampoline.S as well. -jj */
|
* boot processor invocation (via setup_tba() below) and
|
||||||
.globl setup_tba
|
* secondary processor startup (via trampoline.S). The
|
||||||
setup_tba: /* i0 = is_starfire */
|
* former does use this code, the latter does not yet due
|
||||||
save %sp, -160, %sp
|
* to some complexities. That should be fixed up at some
|
||||||
|
* point.
|
||||||
|
*
|
||||||
|
* There used to be enormous complexity wrt. transferring
|
||||||
|
* over from the firwmare's trap table to the Linux kernel's.
|
||||||
|
* For example, there was a chicken & egg problem wrt. building
|
||||||
|
* the OBP page tables, yet needing to be on the Linux kernel
|
||||||
|
* trap table (to translate PAGE_OFFSET addresses) in order to
|
||||||
|
* do that.
|
||||||
|
*
|
||||||
|
* We now handle OBP tlb misses differently, via linear lookups
|
||||||
|
* into the prom_trans[] array. So that specific problem no
|
||||||
|
* longer exists. Yet, unfortunately there are still some issues
|
||||||
|
* preventing trampoline.S from using this code... ho hum.
|
||||||
|
*/
|
||||||
|
.globl setup_trap_table
|
||||||
|
setup_trap_table:
|
||||||
|
save %sp, -192, %sp
|
||||||
|
|
||||||
rdpr %tba, %g7
|
/* Force interrupts to be disabled. */
|
||||||
sethi %hi(prom_tba), %o1
|
rdpr %pstate, %o1
|
||||||
or %o1, %lo(prom_tba), %o1
|
andn %o1, PSTATE_IE, %o1
|
||||||
stx %g7, [%o1]
|
wrpr %o1, 0x0, %pstate
|
||||||
|
wrpr %g0, 15, %pil
|
||||||
|
|
||||||
|
/* Make the firmware call to jump over to the Linux trap table. */
|
||||||
|
call prom_set_trap_table
|
||||||
|
sethi %hi(sparc64_ttable_tl0), %o0
|
||||||
|
|
||||||
|
/* Start using proper page size encodings in ctx register. */
|
||||||
|
sethi %hi(sparc64_kern_pri_context), %g3
|
||||||
|
ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
|
||||||
|
mov PRIMARY_CONTEXT, %g1
|
||||||
|
stxa %g2, [%g1] ASI_DMMU
|
||||||
|
membar #Sync
|
||||||
|
|
||||||
|
/* The Linux trap handlers expect various trap global registers
|
||||||
|
* to be setup with some fixed values. So here we set these
|
||||||
|
* up very carefully. These globals are:
|
||||||
|
*
|
||||||
|
* Alternate Globals (PSTATE_AG):
|
||||||
|
*
|
||||||
|
* %g6 --> current_thread_info()
|
||||||
|
*
|
||||||
|
* MMU Globals (PSTATE_MG):
|
||||||
|
*
|
||||||
|
* %g1 --> TLB_SFSR
|
||||||
|
* %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
|
||||||
|
* _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
|
||||||
|
* ^ 0xfffff80000000000)
|
||||||
|
* (this %g2 value is used for computing the PAGE_OFFSET kernel
|
||||||
|
* TLB entries quickly, the virtual address of the fault XOR'd
|
||||||
|
* with this %g2 value is the PTE to load into the TLB)
|
||||||
|
* %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
|
||||||
|
*
|
||||||
|
* Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
|
||||||
|
*
|
||||||
|
* %g6 --> __irq_work[smp_processor_id()]
|
||||||
|
*/
|
||||||
|
|
||||||
/* Setup "Linux" globals 8-) */
|
|
||||||
rdpr %pstate, %o1
|
rdpr %pstate, %o1
|
||||||
mov %g6, %o2
|
mov %g6, %o2
|
||||||
wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate
|
wrpr %o1, PSTATE_AG, %pstate
|
||||||
sethi %hi(sparc64_ttable_tl0), %g1
|
|
||||||
wrpr %g1, %tba
|
|
||||||
mov %o2, %g6
|
mov %o2, %g6
|
||||||
|
|
||||||
/* Set up MMU globals */
|
|
||||||
wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
|
|
||||||
|
|
||||||
/* Set fixed globals used by dTLB miss handler. */
|
|
||||||
#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
|
#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
|
||||||
#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
|
#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
|
||||||
|
wrpr %o1, PSTATE_MG, %pstate
|
||||||
mov TSB_REG, %g1
|
mov TSB_REG, %g1
|
||||||
stxa %g0, [%g1] ASI_DMMU
|
stxa %g0, [%g1] ASI_DMMU
|
||||||
membar #Sync
|
membar #Sync
|
||||||
@ -419,17 +464,17 @@ setup_tba: /* i0 = is_starfire */
|
|||||||
sllx %g2, 32, %g2
|
sllx %g2, 32, %g2
|
||||||
or %g2, KERN_LOWBITS, %g2
|
or %g2, KERN_LOWBITS, %g2
|
||||||
|
|
||||||
BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base)
|
BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
|
||||||
ba,pt %xcc, spitfire_vpte_base
|
ba,pt %xcc, 9f
|
||||||
nop
|
nop
|
||||||
|
|
||||||
cheetah_vpte_base:
|
8:
|
||||||
sethi %uhi(VPTE_BASE_CHEETAH), %g3
|
sethi %uhi(VPTE_BASE_CHEETAH), %g3
|
||||||
or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
|
or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
|
||||||
ba,pt %xcc, 2f
|
ba,pt %xcc, 2f
|
||||||
sllx %g3, 32, %g3
|
sllx %g3, 32, %g3
|
||||||
|
|
||||||
spitfire_vpte_base:
|
9:
|
||||||
sethi %uhi(VPTE_BASE_SPITFIRE), %g3
|
sethi %uhi(VPTE_BASE_SPITFIRE), %g3
|
||||||
or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
|
or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
|
||||||
sllx %g3, 32, %g3
|
sllx %g3, 32, %g3
|
||||||
@ -455,41 +500,55 @@ spitfire_vpte_base:
|
|||||||
sllx %o2, 32, %o2
|
sllx %o2, 32, %o2
|
||||||
wr %o2, %asr25
|
wr %o2, %asr25
|
||||||
|
|
||||||
/* Ok, we're done setting up all the state our trap mechanims needs,
|
|
||||||
* now get back into normal globals and let the PROM know what is up.
|
|
||||||
*/
|
|
||||||
2:
|
2:
|
||||||
wrpr %g0, %g0, %wstate
|
wrpr %g0, %g0, %wstate
|
||||||
wrpr %o1, PSTATE_IE, %pstate
|
wrpr %o1, 0x0, %pstate
|
||||||
|
|
||||||
call init_irqwork_curcpu
|
call init_irqwork_curcpu
|
||||||
nop
|
nop
|
||||||
|
|
||||||
call prom_set_trap_table
|
/* Now we can turn interrupts back on. */
|
||||||
sethi %hi(sparc64_ttable_tl0), %o0
|
|
||||||
|
|
||||||
/* Start using proper page size encodings in ctx register. */
|
|
||||||
sethi %hi(sparc64_kern_pri_context), %g3
|
|
||||||
ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
|
|
||||||
mov PRIMARY_CONTEXT, %g1
|
|
||||||
stxa %g2, [%g1] ASI_DMMU
|
|
||||||
membar #Sync
|
|
||||||
|
|
||||||
rdpr %pstate, %o1
|
rdpr %pstate, %o1
|
||||||
or %o1, PSTATE_IE, %o1
|
or %o1, PSTATE_IE, %o1
|
||||||
wrpr %o1, 0, %pstate
|
wrpr %o1, 0, %pstate
|
||||||
|
wrpr %g0, 0x0, %pil
|
||||||
|
|
||||||
ret
|
ret
|
||||||
restore
|
restore
|
||||||
|
|
||||||
|
.globl setup_tba
|
||||||
|
setup_tba: /* i0 = is_starfire */
|
||||||
|
save %sp, -192, %sp
|
||||||
|
|
||||||
|
/* The boot processor is the only cpu which invokes this
|
||||||
|
* routine, the other cpus set things up via trampoline.S.
|
||||||
|
* So save the OBP trap table address here.
|
||||||
|
*/
|
||||||
|
rdpr %tba, %g7
|
||||||
|
sethi %hi(prom_tba), %o1
|
||||||
|
or %o1, %lo(prom_tba), %o1
|
||||||
|
stx %g7, [%o1]
|
||||||
|
|
||||||
|
call setup_trap_table
|
||||||
|
nop
|
||||||
|
|
||||||
|
ret
|
||||||
|
restore
|
||||||
|
sparc64_boot_end:
|
||||||
|
|
||||||
|
#include "systbls.S"
|
||||||
|
#include "ktlb.S"
|
||||||
|
#include "etrap.S"
|
||||||
|
#include "rtrap.S"
|
||||||
|
#include "winfixup.S"
|
||||||
|
#include "entry.S"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following skips make sure the trap table in ttable.S is aligned
|
* The following skip makes sure the trap table in ttable.S is aligned
|
||||||
* on a 32K boundary as required by the v9 specs for TBA register.
|
* on a 32K boundary as required by the v9 specs for TBA register.
|
||||||
*/
|
*/
|
||||||
sparc64_boot_end:
|
1:
|
||||||
.skip 0x2000 + _start - sparc64_boot_end
|
.skip 0x4000 + _start - 1b
|
||||||
bootup_user_stack_end:
|
|
||||||
.skip 0x2000
|
|
||||||
|
|
||||||
#ifdef CONFIG_SBUS
|
#ifdef CONFIG_SBUS
|
||||||
/* This is just a hack to fool make depend config.h discovering
|
/* This is just a hack to fool make depend config.h discovering
|
||||||
@ -501,15 +560,6 @@ bootup_user_stack_end:
|
|||||||
! 0x0000000000408000
|
! 0x0000000000408000
|
||||||
|
|
||||||
#include "ttable.S"
|
#include "ttable.S"
|
||||||
#include "systbls.S"
|
|
||||||
#include "ktlb.S"
|
|
||||||
#include "etrap.S"
|
|
||||||
#include "rtrap.S"
|
|
||||||
#include "winfixup.S"
|
|
||||||
#include "entry.S"
|
|
||||||
|
|
||||||
/* This is just anal retentiveness on my part... */
|
|
||||||
.align 16384
|
|
||||||
|
|
||||||
.data
|
.data
|
||||||
.align 8
|
.align 8
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
|
#include <asm/io.h>
|
||||||
#include <asm/sbus.h>
|
#include <asm/sbus.h>
|
||||||
#include <asm/iommu.h>
|
#include <asm/iommu.h>
|
||||||
#include <asm/upa.h>
|
#include <asm/upa.h>
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||||
srax r1, 10, r2
|
srax r1, 10, r2
|
||||||
#define CREATE_VPTE_OFFSET2(r1, r2)
|
#define CREATE_VPTE_OFFSET2(r1, r2) nop
|
||||||
#define CREATE_VPTE_NOP nop
|
|
||||||
#else /* PAGE_SHIFT */
|
#else /* PAGE_SHIFT */
|
||||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||||
srax r1, PAGE_SHIFT, r2
|
srax r1, PAGE_SHIFT, r2
|
||||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||||
sllx r2, 3, r2
|
sllx r2, 3, r2
|
||||||
#define CREATE_VPTE_NOP
|
|
||||||
#endif /* PAGE_SHIFT */
|
#endif /* PAGE_SHIFT */
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* ITLB ** ICACHE line 1: Quick user TLB misses */
|
/* ITLB ** ICACHE line 1: Quick user TLB misses */
|
||||||
|
mov TLB_SFSR, %g1
|
||||||
ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS
|
ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS
|
||||||
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
|
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
|
||||||
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
||||||
@ -43,41 +42,38 @@
|
|||||||
1: brgez,pn %g5, 3f ! Not valid, branch out
|
1: brgez,pn %g5, 3f ! Not valid, branch out
|
||||||
sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot
|
sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot
|
||||||
andcc %g5, %g4, %g0 ! Executable?
|
andcc %g5, %g4, %g0 ! Executable?
|
||||||
|
|
||||||
|
/* ITLB ** ICACHE line 2: Real faults */
|
||||||
be,pn %xcc, 3f ! Nope, branch.
|
be,pn %xcc, 3f ! Nope, branch.
|
||||||
nop ! Delay-slot
|
nop ! Delay-slot
|
||||||
2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB
|
2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB
|
||||||
retry ! Trap return
|
retry ! Trap return
|
||||||
3: rdpr %pstate, %g4 ! Move into alternate globals
|
3: rdpr %pstate, %g4 ! Move into alt-globals
|
||||||
|
|
||||||
/* ITLB ** ICACHE line 2: Real faults */
|
|
||||||
wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate
|
wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate
|
||||||
rdpr %tpc, %g5 ! And load faulting VA
|
rdpr %tpc, %g5 ! And load faulting VA
|
||||||
mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB
|
mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB
|
||||||
sparc64_realfault_common: ! Called by TL0 dtlb_miss too
|
|
||||||
|
/* ITLB ** ICACHE line 3: Finish faults */
|
||||||
|
sparc64_realfault_common: ! Called by dtlb_miss
|
||||||
stb %g4, [%g6 + TI_FAULT_CODE]
|
stb %g4, [%g6 + TI_FAULT_CODE]
|
||||||
stx %g5, [%g6 + TI_FAULT_ADDR]
|
stx %g5, [%g6 + TI_FAULT_ADDR]
|
||||||
ba,pt %xcc, etrap ! Save state
|
ba,pt %xcc, etrap ! Save state
|
||||||
1: rd %pc, %g7 ! ...
|
1: rd %pc, %g7 ! ...
|
||||||
nop
|
|
||||||
|
|
||||||
/* ITLB ** ICACHE line 3: Finish faults + window fixups */
|
|
||||||
call do_sparc64_fault ! Call fault handler
|
call do_sparc64_fault ! Call fault handler
|
||||||
add %sp, PTREGS_OFF, %o0! Compute pt_regs arg
|
add %sp, PTREGS_OFF, %o0! Compute pt_regs arg
|
||||||
ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
|
ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
/* ITLB ** ICACHE line 4: Window fixups */
|
||||||
winfix_trampoline:
|
winfix_trampoline:
|
||||||
rdpr %tpc, %g3 ! Prepare winfixup TNPC
|
rdpr %tpc, %g3 ! Prepare winfixup TNPC
|
||||||
or %g3, 0x7c, %g3 ! Compute offset to branch
|
or %g3, 0x7c, %g3 ! Compute branch offset
|
||||||
wrpr %g3, %tnpc ! Write it into TNPC
|
wrpr %g3, %tnpc ! Write it into TNPC
|
||||||
done ! Do it to it
|
done ! Do it to it
|
||||||
|
|
||||||
/* ITLB ** ICACHE line 4: Unused... */
|
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
CREATE_VPTE_NOP
|
|
||||||
|
|
||||||
#undef CREATE_VPTE_OFFSET1
|
#undef CREATE_VPTE_OFFSET1
|
||||||
#undef CREATE_VPTE_OFFSET2
|
#undef CREATE_VPTE_OFFSET2
|
||||||
#undef CREATE_VPTE_NOP
|
|
||||||
|
@ -58,9 +58,6 @@ vpte_noent:
|
|||||||
done
|
done
|
||||||
|
|
||||||
vpte_insn_obp:
|
vpte_insn_obp:
|
||||||
sethi %hi(prom_pmd_phys), %g5
|
|
||||||
ldx [%g5 + %lo(prom_pmd_phys)], %g5
|
|
||||||
|
|
||||||
/* Behave as if we are at TL0. */
|
/* Behave as if we are at TL0. */
|
||||||
wrpr %g0, 1, %tl
|
wrpr %g0, 1, %tl
|
||||||
rdpr %tpc, %g4 /* Find original faulting iaddr */
|
rdpr %tpc, %g4 /* Find original faulting iaddr */
|
||||||
@ -71,58 +68,57 @@ vpte_insn_obp:
|
|||||||
mov TLB_SFSR, %g1
|
mov TLB_SFSR, %g1
|
||||||
stxa %g4, [%g1 + %g1] ASI_IMMU
|
stxa %g4, [%g1 + %g1] ASI_IMMU
|
||||||
|
|
||||||
/* Get PMD offset. */
|
sethi %hi(prom_trans), %g5
|
||||||
srlx %g4, 23, %g6
|
or %g5, %lo(prom_trans), %g5
|
||||||
and %g6, 0x7ff, %g6
|
|
||||||
sllx %g6, 2, %g6
|
|
||||||
|
|
||||||
/* Load PMD, is it valid? */
|
1: ldx [%g5 + 0x00], %g6 ! base
|
||||||
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
brz,a,pn %g6, longpath ! no more entries, fail
|
||||||
brz,pn %g5, longpath
|
mov TLB_SFSR, %g1 ! and restore %g1
|
||||||
sllx %g5, 11, %g5
|
ldx [%g5 + 0x08], %g1 ! len
|
||||||
|
add %g6, %g1, %g1 ! end
|
||||||
|
cmp %g6, %g4
|
||||||
|
bgu,pt %xcc, 2f
|
||||||
|
cmp %g4, %g1
|
||||||
|
bgeu,pt %xcc, 2f
|
||||||
|
ldx [%g5 + 0x10], %g1 ! PTE
|
||||||
|
|
||||||
/* Get PTE offset. */
|
/* TLB load, restore %g1, and return from trap. */
|
||||||
srlx %g4, 13, %g6
|
sub %g4, %g6, %g6
|
||||||
and %g6, 0x3ff, %g6
|
add %g1, %g6, %g5
|
||||||
sllx %g6, 3, %g6
|
mov TLB_SFSR, %g1
|
||||||
|
|
||||||
/* Load PTE. */
|
|
||||||
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
|
||||||
brgez,pn %g5, longpath
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* TLB load and return from trap. */
|
|
||||||
stxa %g5, [%g0] ASI_ITLB_DATA_IN
|
stxa %g5, [%g0] ASI_ITLB_DATA_IN
|
||||||
retry
|
retry
|
||||||
|
|
||||||
|
2: ba,pt %xcc, 1b
|
||||||
|
add %g5, (3 * 8), %g5 ! next entry
|
||||||
|
|
||||||
kvmap_do_obp:
|
kvmap_do_obp:
|
||||||
sethi %hi(prom_pmd_phys), %g5
|
sethi %hi(prom_trans), %g5
|
||||||
ldx [%g5 + %lo(prom_pmd_phys)], %g5
|
or %g5, %lo(prom_trans), %g5
|
||||||
|
srlx %g4, 13, %g4
|
||||||
|
sllx %g4, 13, %g4
|
||||||
|
|
||||||
/* Get PMD offset. */
|
1: ldx [%g5 + 0x00], %g6 ! base
|
||||||
srlx %g4, 23, %g6
|
brz,a,pn %g6, longpath ! no more entries, fail
|
||||||
and %g6, 0x7ff, %g6
|
mov TLB_SFSR, %g1 ! and restore %g1
|
||||||
sllx %g6, 2, %g6
|
ldx [%g5 + 0x08], %g1 ! len
|
||||||
|
add %g6, %g1, %g1 ! end
|
||||||
|
cmp %g6, %g4
|
||||||
|
bgu,pt %xcc, 2f
|
||||||
|
cmp %g4, %g1
|
||||||
|
bgeu,pt %xcc, 2f
|
||||||
|
ldx [%g5 + 0x10], %g1 ! PTE
|
||||||
|
|
||||||
/* Load PMD, is it valid? */
|
/* TLB load, restore %g1, and return from trap. */
|
||||||
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
sub %g4, %g6, %g6
|
||||||
brz,pn %g5, longpath
|
add %g1, %g6, %g5
|
||||||
sllx %g5, 11, %g5
|
mov TLB_SFSR, %g1
|
||||||
|
|
||||||
/* Get PTE offset. */
|
|
||||||
srlx %g4, 13, %g6
|
|
||||||
and %g6, 0x3ff, %g6
|
|
||||||
sllx %g6, 3, %g6
|
|
||||||
|
|
||||||
/* Load PTE. */
|
|
||||||
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
|
||||||
brgez,pn %g5, longpath
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* TLB load and return from trap. */
|
|
||||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN
|
stxa %g5, [%g0] ASI_DTLB_DATA_IN
|
||||||
retry
|
retry
|
||||||
|
|
||||||
|
2: ba,pt %xcc, 1b
|
||||||
|
add %g5, (3 * 8), %g5 ! next entry
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On a first level data miss, check whether this is to the OBP range (note
|
* On a first level data miss, check whether this is to the OBP range (note
|
||||||
* that such accesses can be made by prom, as well as by kernel using
|
* that such accesses can be made by prom, as well as by kernel using
|
||||||
|
@ -49,12 +49,6 @@ static void __iommu_flushall(struct pci_iommu *iommu)
|
|||||||
|
|
||||||
/* Ensure completion of previous PIO writes. */
|
/* Ensure completion of previous PIO writes. */
|
||||||
(void) pci_iommu_read(iommu->write_complete_reg);
|
(void) pci_iommu_read(iommu->write_complete_reg);
|
||||||
|
|
||||||
/* Now update everyone's flush point. */
|
|
||||||
for (entry = 0; entry < PBM_NCLUSTERS; entry++) {
|
|
||||||
iommu->alloc_info[entry].flush =
|
|
||||||
iommu->alloc_info[entry].next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IOPTE_CONSISTENT(CTX) \
|
#define IOPTE_CONSISTENT(CTX) \
|
||||||
@ -80,120 +74,117 @@ static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
|
|||||||
iopte_val(*iopte) = val;
|
iopte_val(*iopte) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize)
|
/* Based largely upon the ppc64 iommu allocator. */
|
||||||
|
static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages)
|
||||||
{
|
{
|
||||||
int i;
|
struct pci_iommu_arena *arena = &iommu->arena;
|
||||||
|
unsigned long n, i, start, end, limit;
|
||||||
|
int pass;
|
||||||
|
|
||||||
tsbsize /= sizeof(iopte_t);
|
limit = arena->limit;
|
||||||
|
start = arena->hint;
|
||||||
|
pass = 0;
|
||||||
|
|
||||||
for (i = 0; i < tsbsize; i++)
|
again:
|
||||||
|
n = find_next_zero_bit(arena->map, limit, start);
|
||||||
|
end = n + npages;
|
||||||
|
if (unlikely(end >= limit)) {
|
||||||
|
if (likely(pass < 1)) {
|
||||||
|
limit = start;
|
||||||
|
start = 0;
|
||||||
|
__iommu_flushall(iommu);
|
||||||
|
pass++;
|
||||||
|
goto again;
|
||||||
|
} else {
|
||||||
|
/* Scanned the whole thing, give up. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = n; i < end; i++) {
|
||||||
|
if (test_bit(i, arena->map)) {
|
||||||
|
start = i + 1;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = n; i < end; i++)
|
||||||
|
__set_bit(i, arena->map);
|
||||||
|
|
||||||
|
arena->hint = end;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
for (i = base; i < (base + npages); i++)
|
||||||
|
__clear_bit(i, arena->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
|
||||||
|
{
|
||||||
|
unsigned long i, tsbbase, order, sz, num_tsb_entries;
|
||||||
|
|
||||||
|
num_tsb_entries = tsbsize / sizeof(iopte_t);
|
||||||
|
|
||||||
|
/* Setup initial software IOMMU state. */
|
||||||
|
spin_lock_init(&iommu->lock);
|
||||||
|
iommu->ctx_lowest_free = 1;
|
||||||
|
iommu->page_table_map_base = dma_offset;
|
||||||
|
iommu->dma_addr_mask = dma_addr_mask;
|
||||||
|
|
||||||
|
/* Allocate and initialize the free area map. */
|
||||||
|
sz = num_tsb_entries / 8;
|
||||||
|
sz = (sz + 7UL) & ~7UL;
|
||||||
|
iommu->arena.map = kmalloc(sz, GFP_KERNEL);
|
||||||
|
if (!iommu->arena.map) {
|
||||||
|
prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
|
||||||
|
prom_halt();
|
||||||
|
}
|
||||||
|
memset(iommu->arena.map, 0, sz);
|
||||||
|
iommu->arena.limit = num_tsb_entries;
|
||||||
|
|
||||||
|
/* Allocate and initialize the dummy page which we
|
||||||
|
* set inactive IO PTEs to point to.
|
||||||
|
*/
|
||||||
|
iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
|
||||||
|
if (!iommu->dummy_page) {
|
||||||
|
prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n");
|
||||||
|
prom_halt();
|
||||||
|
}
|
||||||
|
memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
|
||||||
|
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
|
||||||
|
|
||||||
|
/* Now allocate and setup the IOMMU page table itself. */
|
||||||
|
order = get_order(tsbsize);
|
||||||
|
tsbbase = __get_free_pages(GFP_KERNEL, order);
|
||||||
|
if (!tsbbase) {
|
||||||
|
prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n");
|
||||||
|
prom_halt();
|
||||||
|
}
|
||||||
|
iommu->page_table = (iopte_t *)tsbbase;
|
||||||
|
|
||||||
|
for (i = 0; i < num_tsb_entries; i++)
|
||||||
iopte_make_dummy(iommu, &iommu->page_table[i]);
|
iopte_make_dummy(iommu, &iommu->page_table[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
|
static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages)
|
||||||
{
|
{
|
||||||
iopte_t *iopte, *limit, *first;
|
long entry;
|
||||||
unsigned long cnum, ent, flush_point;
|
|
||||||
|
|
||||||
cnum = 0;
|
entry = pci_arena_alloc(iommu, npages);
|
||||||
while ((1UL << cnum) < npages)
|
if (unlikely(entry < 0))
|
||||||
cnum++;
|
return NULL;
|
||||||
iopte = (iommu->page_table +
|
|
||||||
(cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
|
|
||||||
|
|
||||||
if (cnum == 0)
|
return iommu->page_table + entry;
|
||||||
limit = (iommu->page_table +
|
|
||||||
iommu->lowest_consistent_map);
|
|
||||||
else
|
|
||||||
limit = (iopte +
|
|
||||||
(1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
|
|
||||||
|
|
||||||
iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);
|
|
||||||
flush_point = iommu->alloc_info[cnum].flush;
|
|
||||||
|
|
||||||
first = iopte;
|
|
||||||
for (;;) {
|
|
||||||
if (IOPTE_IS_DUMMY(iommu, iopte)) {
|
|
||||||
if ((iopte + (1 << cnum)) >= limit)
|
|
||||||
ent = 0;
|
|
||||||
else
|
|
||||||
ent = ent + 1;
|
|
||||||
iommu->alloc_info[cnum].next = ent;
|
|
||||||
if (ent == flush_point)
|
|
||||||
__iommu_flushall(iommu);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iopte += (1 << cnum);
|
|
||||||
ent++;
|
|
||||||
if (iopte >= limit) {
|
|
||||||
iopte = (iommu->page_table +
|
|
||||||
(cnum <<
|
|
||||||
(iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
|
|
||||||
ent = 0;
|
|
||||||
}
|
|
||||||
if (ent == flush_point)
|
|
||||||
__iommu_flushall(iommu);
|
|
||||||
if (iopte == first)
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* I've got your streaming cluster right here buddy boy... */
|
|
||||||
return iopte;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
printk(KERN_EMERG "pci_iommu: alloc_streaming_cluster of npages(%ld) failed!\n",
|
|
||||||
npages);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base,
|
static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages)
|
||||||
unsigned long npages, unsigned long ctx)
|
|
||||||
{
|
{
|
||||||
unsigned long cnum, ent;
|
pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
|
||||||
|
|
||||||
cnum = 0;
|
|
||||||
while ((1UL << cnum) < npages)
|
|
||||||
cnum++;
|
|
||||||
|
|
||||||
ent = (base << (32 - IO_PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits))
|
|
||||||
>> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits);
|
|
||||||
|
|
||||||
/* If the global flush might not have caught this entry,
|
|
||||||
* adjust the flush point such that we will flush before
|
|
||||||
* ever trying to reuse it.
|
|
||||||
*/
|
|
||||||
#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y)))
|
|
||||||
if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush))
|
|
||||||
iommu->alloc_info[cnum].flush = ent;
|
|
||||||
#undef between
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We allocate consistent mappings from the end of cluster zero. */
|
|
||||||
static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long npages)
|
|
||||||
{
|
|
||||||
iopte_t *iopte;
|
|
||||||
|
|
||||||
iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
|
|
||||||
while (iopte > iommu->page_table) {
|
|
||||||
iopte--;
|
|
||||||
if (IOPTE_IS_DUMMY(iommu, iopte)) {
|
|
||||||
unsigned long tmp = npages;
|
|
||||||
|
|
||||||
while (--tmp) {
|
|
||||||
iopte--;
|
|
||||||
if (!IOPTE_IS_DUMMY(iommu, iopte))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (tmp == 0) {
|
|
||||||
u32 entry = (iopte - iommu->page_table);
|
|
||||||
|
|
||||||
if (entry < iommu->lowest_consistent_map)
|
|
||||||
iommu->lowest_consistent_map = entry;
|
|
||||||
return iopte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iommu_alloc_ctx(struct pci_iommu *iommu)
|
static int iommu_alloc_ctx(struct pci_iommu *iommu)
|
||||||
@ -233,7 +224,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
|
|||||||
struct pcidev_cookie *pcp;
|
struct pcidev_cookie *pcp;
|
||||||
struct pci_iommu *iommu;
|
struct pci_iommu *iommu;
|
||||||
iopte_t *iopte;
|
iopte_t *iopte;
|
||||||
unsigned long flags, order, first_page, ctx;
|
unsigned long flags, order, first_page;
|
||||||
void *ret;
|
void *ret;
|
||||||
int npages;
|
int npages;
|
||||||
|
|
||||||
@ -251,9 +242,10 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
|
|||||||
iommu = pcp->pbm->iommu;
|
iommu = pcp->pbm->iommu;
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT);
|
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
|
||||||
if (iopte == NULL) {
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
|
||||||
|
if (unlikely(iopte == NULL)) {
|
||||||
free_pages(first_page, order);
|
free_pages(first_page, order);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -262,31 +254,15 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
|
|||||||
((iopte - iommu->page_table) << IO_PAGE_SHIFT));
|
((iopte - iommu->page_table) << IO_PAGE_SHIFT));
|
||||||
ret = (void *) first_page;
|
ret = (void *) first_page;
|
||||||
npages = size >> IO_PAGE_SHIFT;
|
npages = size >> IO_PAGE_SHIFT;
|
||||||
ctx = 0;
|
|
||||||
if (iommu->iommu_ctxflush)
|
|
||||||
ctx = iommu_alloc_ctx(iommu);
|
|
||||||
first_page = __pa(first_page);
|
first_page = __pa(first_page);
|
||||||
while (npages--) {
|
while (npages--) {
|
||||||
iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
|
iopte_val(*iopte) = (IOPTE_CONSISTENT(0UL) |
|
||||||
IOPTE_WRITE |
|
IOPTE_WRITE |
|
||||||
(first_page & IOPTE_PAGE));
|
(first_page & IOPTE_PAGE));
|
||||||
iopte++;
|
iopte++;
|
||||||
first_page += IO_PAGE_SIZE;
|
first_page += IO_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
u32 daddr = *dma_addrp;
|
|
||||||
|
|
||||||
npages = size >> IO_PAGE_SHIFT;
|
|
||||||
for (i = 0; i < npages; i++) {
|
|
||||||
pci_iommu_write(iommu->iommu_flush, daddr);
|
|
||||||
daddr += IO_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +272,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
|
|||||||
struct pcidev_cookie *pcp;
|
struct pcidev_cookie *pcp;
|
||||||
struct pci_iommu *iommu;
|
struct pci_iommu *iommu;
|
||||||
iopte_t *iopte;
|
iopte_t *iopte;
|
||||||
unsigned long flags, order, npages, i, ctx;
|
unsigned long flags, order, npages;
|
||||||
|
|
||||||
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
|
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
|
||||||
pcp = pdev->sysdata;
|
pcp = pdev->sysdata;
|
||||||
@ -306,46 +282,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
|
|||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
|
|
||||||
if ((iopte - iommu->page_table) ==
|
free_npages(iommu, dvma, npages);
|
||||||
iommu->lowest_consistent_map) {
|
|
||||||
iopte_t *walk = iopte + npages;
|
|
||||||
iopte_t *limit;
|
|
||||||
|
|
||||||
limit = (iommu->page_table +
|
|
||||||
(1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
|
|
||||||
while (walk < limit) {
|
|
||||||
if (!IOPTE_IS_DUMMY(iommu, walk))
|
|
||||||
break;
|
|
||||||
walk++;
|
|
||||||
}
|
|
||||||
iommu->lowest_consistent_map =
|
|
||||||
(walk - iommu->page_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Data for consistent mappings cannot enter the streaming
|
|
||||||
* buffers, so we only need to update the TSB. We flush
|
|
||||||
* the IOMMU here as well to prevent conflicts with the
|
|
||||||
* streaming mapping deferred tlb flush scheme.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ctx = 0;
|
|
||||||
if (iommu->iommu_ctxflush)
|
|
||||||
ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
|
|
||||||
|
|
||||||
for (i = 0; i < npages; i++, iopte++)
|
|
||||||
iopte_make_dummy(iommu, iopte);
|
|
||||||
|
|
||||||
if (iommu->iommu_ctxflush) {
|
|
||||||
pci_iommu_write(iommu->iommu_ctxflush, ctx);
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < npages; i++) {
|
|
||||||
u32 daddr = dvma + (i << IO_PAGE_SHIFT);
|
|
||||||
|
|
||||||
pci_iommu_write(iommu->iommu_flush, daddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iommu_free_ctx(iommu, ctx);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
@ -372,25 +309,27 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
|
|||||||
iommu = pcp->pbm->iommu;
|
iommu = pcp->pbm->iommu;
|
||||||
strbuf = &pcp->pbm->stc;
|
strbuf = &pcp->pbm->stc;
|
||||||
|
|
||||||
if (direction == PCI_DMA_NONE)
|
if (unlikely(direction == PCI_DMA_NONE))
|
||||||
BUG();
|
goto bad_no_ctx;
|
||||||
|
|
||||||
oaddr = (unsigned long)ptr;
|
oaddr = (unsigned long)ptr;
|
||||||
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
|
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
|
||||||
npages >>= IO_PAGE_SHIFT;
|
npages >>= IO_PAGE_SHIFT;
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
|
base = alloc_npages(iommu, npages);
|
||||||
|
ctx = 0;
|
||||||
|
if (iommu->iommu_ctxflush)
|
||||||
|
ctx = iommu_alloc_ctx(iommu);
|
||||||
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
base = alloc_streaming_cluster(iommu, npages);
|
if (unlikely(!base))
|
||||||
if (base == NULL)
|
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
bus_addr = (iommu->page_table_map_base +
|
bus_addr = (iommu->page_table_map_base +
|
||||||
((base - iommu->page_table) << IO_PAGE_SHIFT));
|
((base - iommu->page_table) << IO_PAGE_SHIFT));
|
||||||
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
|
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
|
||||||
base_paddr = __pa(oaddr & IO_PAGE_MASK);
|
base_paddr = __pa(oaddr & IO_PAGE_MASK);
|
||||||
ctx = 0;
|
|
||||||
if (iommu->iommu_ctxflush)
|
|
||||||
ctx = iommu_alloc_ctx(iommu);
|
|
||||||
if (strbuf->strbuf_enabled)
|
if (strbuf->strbuf_enabled)
|
||||||
iopte_protection = IOPTE_STREAMING(ctx);
|
iopte_protection = IOPTE_STREAMING(ctx);
|
||||||
else
|
else
|
||||||
@ -401,12 +340,13 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
|
|||||||
for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
|
for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
|
||||||
iopte_val(*base) = iopte_protection | base_paddr;
|
iopte_val(*base) = iopte_protection | base_paddr;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
iommu_free_ctx(iommu, ctx);
|
||||||
|
bad_no_ctx:
|
||||||
|
if (printk_ratelimit())
|
||||||
|
WARN_ON(1);
|
||||||
return PCI_DMA_ERROR_CODE;
|
return PCI_DMA_ERROR_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,10 +421,13 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
|
|||||||
struct pci_iommu *iommu;
|
struct pci_iommu *iommu;
|
||||||
struct pci_strbuf *strbuf;
|
struct pci_strbuf *strbuf;
|
||||||
iopte_t *base;
|
iopte_t *base;
|
||||||
unsigned long flags, npages, ctx;
|
unsigned long flags, npages, ctx, i;
|
||||||
|
|
||||||
if (direction == PCI_DMA_NONE)
|
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||||
BUG();
|
if (printk_ratelimit())
|
||||||
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcp = pdev->sysdata;
|
pcp = pdev->sysdata;
|
||||||
iommu = pcp->pbm->iommu;
|
iommu = pcp->pbm->iommu;
|
||||||
@ -510,13 +453,14 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
|
|||||||
|
|
||||||
/* Step 1: Kick data out of streaming buffers if necessary. */
|
/* Step 1: Kick data out of streaming buffers if necessary. */
|
||||||
if (strbuf->strbuf_enabled)
|
if (strbuf->strbuf_enabled)
|
||||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx,
|
||||||
|
npages, direction);
|
||||||
|
|
||||||
/* Step 2: Clear out first TSB entry. */
|
/* Step 2: Clear out TSB entries. */
|
||||||
iopte_make_dummy(iommu, base);
|
for (i = 0; i < npages; i++)
|
||||||
|
iopte_make_dummy(iommu, base + i);
|
||||||
|
|
||||||
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
|
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
|
||||||
npages, ctx);
|
|
||||||
|
|
||||||
iommu_free_ctx(iommu, ctx);
|
iommu_free_ctx(iommu, ctx);
|
||||||
|
|
||||||
@ -621,6 +565,8 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
|
|||||||
pci_map_single(pdev,
|
pci_map_single(pdev,
|
||||||
(page_address(sglist->page) + sglist->offset),
|
(page_address(sglist->page) + sglist->offset),
|
||||||
sglist->length, direction);
|
sglist->length, direction);
|
||||||
|
if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
|
||||||
|
return 0;
|
||||||
sglist->dma_length = sglist->length;
|
sglist->dma_length = sglist->length;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -629,21 +575,29 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
|
|||||||
iommu = pcp->pbm->iommu;
|
iommu = pcp->pbm->iommu;
|
||||||
strbuf = &pcp->pbm->stc;
|
strbuf = &pcp->pbm->stc;
|
||||||
|
|
||||||
if (direction == PCI_DMA_NONE)
|
if (unlikely(direction == PCI_DMA_NONE))
|
||||||
BUG();
|
goto bad_no_ctx;
|
||||||
|
|
||||||
/* Step 1: Prepare scatter list. */
|
/* Step 1: Prepare scatter list. */
|
||||||
|
|
||||||
npages = prepare_sg(sglist, nelems);
|
npages = prepare_sg(sglist, nelems);
|
||||||
|
|
||||||
/* Step 2: Allocate a cluster. */
|
/* Step 2: Allocate a cluster and context, if necessary. */
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
|
|
||||||
base = alloc_streaming_cluster(iommu, npages);
|
base = alloc_npages(iommu, npages);
|
||||||
|
ctx = 0;
|
||||||
|
if (iommu->iommu_ctxflush)
|
||||||
|
ctx = iommu_alloc_ctx(iommu);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
if (base == NULL)
|
if (base == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT);
|
|
||||||
|
dma_base = iommu->page_table_map_base +
|
||||||
|
((base - iommu->page_table) << IO_PAGE_SHIFT);
|
||||||
|
|
||||||
/* Step 3: Normalize DMA addresses. */
|
/* Step 3: Normalize DMA addresses. */
|
||||||
used = nelems;
|
used = nelems;
|
||||||
@ -656,30 +610,28 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
|
|||||||
}
|
}
|
||||||
used = nelems - used;
|
used = nelems - used;
|
||||||
|
|
||||||
/* Step 4: Choose a context if necessary. */
|
/* Step 4: Create the mappings. */
|
||||||
ctx = 0;
|
|
||||||
if (iommu->iommu_ctxflush)
|
|
||||||
ctx = iommu_alloc_ctx(iommu);
|
|
||||||
|
|
||||||
/* Step 5: Create the mappings. */
|
|
||||||
if (strbuf->strbuf_enabled)
|
if (strbuf->strbuf_enabled)
|
||||||
iopte_protection = IOPTE_STREAMING(ctx);
|
iopte_protection = IOPTE_STREAMING(ctx);
|
||||||
else
|
else
|
||||||
iopte_protection = IOPTE_CONSISTENT(ctx);
|
iopte_protection = IOPTE_CONSISTENT(ctx);
|
||||||
if (direction != PCI_DMA_TODEVICE)
|
if (direction != PCI_DMA_TODEVICE)
|
||||||
iopte_protection |= IOPTE_WRITE;
|
iopte_protection |= IOPTE_WRITE;
|
||||||
fill_sg (base, sglist, used, nelems, iopte_protection);
|
|
||||||
|
fill_sg(base, sglist, used, nelems, iopte_protection);
|
||||||
|
|
||||||
#ifdef VERIFY_SG
|
#ifdef VERIFY_SG
|
||||||
verify_sglist(sglist, nelems, base, npages);
|
verify_sglist(sglist, nelems, base, npages);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
|
||||||
|
|
||||||
return used;
|
return used;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
iommu_free_ctx(iommu, ctx);
|
||||||
return PCI_DMA_ERROR_CODE;
|
bad_no_ctx:
|
||||||
|
if (printk_ratelimit())
|
||||||
|
WARN_ON(1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unmap a set of streaming mode DMA translations. */
|
/* Unmap a set of streaming mode DMA translations. */
|
||||||
@ -692,8 +644,10 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
|
|||||||
unsigned long flags, ctx, i, npages;
|
unsigned long flags, ctx, i, npages;
|
||||||
u32 bus_addr;
|
u32 bus_addr;
|
||||||
|
|
||||||
if (direction == PCI_DMA_NONE)
|
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||||
BUG();
|
if (printk_ratelimit())
|
||||||
|
WARN_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
pcp = pdev->sysdata;
|
pcp = pdev->sysdata;
|
||||||
iommu = pcp->pbm->iommu;
|
iommu = pcp->pbm->iommu;
|
||||||
@ -705,7 +659,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
|
|||||||
if (sglist[i].dma_length == 0)
|
if (sglist[i].dma_length == 0)
|
||||||
break;
|
break;
|
||||||
i--;
|
i--;
|
||||||
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
|
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) -
|
||||||
|
bus_addr) >> IO_PAGE_SHIFT;
|
||||||
|
|
||||||
base = iommu->page_table +
|
base = iommu->page_table +
|
||||||
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||||
@ -726,11 +681,11 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
|
|||||||
if (strbuf->strbuf_enabled)
|
if (strbuf->strbuf_enabled)
|
||||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||||
|
|
||||||
/* Step 2: Clear out first TSB entry. */
|
/* Step 2: Clear out the TSB entries. */
|
||||||
iopte_make_dummy(iommu, base);
|
for (i = 0; i < npages; i++)
|
||||||
|
iopte_make_dummy(iommu, base + i);
|
||||||
|
|
||||||
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
|
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
|
||||||
npages, ctx);
|
|
||||||
|
|
||||||
iommu_free_ctx(iommu, ctx);
|
iommu_free_ctx(iommu, ctx);
|
||||||
|
|
||||||
|
@ -1207,13 +1207,9 @@ static void psycho_scan_bus(struct pci_controller_info *p)
|
|||||||
static void psycho_iommu_init(struct pci_controller_info *p)
|
static void psycho_iommu_init(struct pci_controller_info *p)
|
||||||
{
|
{
|
||||||
struct pci_iommu *iommu = p->pbm_A.iommu;
|
struct pci_iommu *iommu = p->pbm_A.iommu;
|
||||||
unsigned long tsbbase, i;
|
unsigned long i;
|
||||||
u64 control;
|
u64 control;
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
|
||||||
spin_lock_init(&iommu->lock);
|
|
||||||
iommu->ctx_lowest_free = 1;
|
|
||||||
|
|
||||||
/* Register addresses. */
|
/* Register addresses. */
|
||||||
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
|
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
|
||||||
iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
|
iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
|
||||||
@ -1240,40 +1236,10 @@ static void psycho_iommu_init(struct pci_controller_info *p)
|
|||||||
/* Leave diag mode enabled for full-flushing done
|
/* Leave diag mode enabled for full-flushing done
|
||||||
* in pci_iommu.c
|
* in pci_iommu.c
|
||||||
*/
|
*/
|
||||||
|
pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
|
||||||
|
|
||||||
iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
|
psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE,
|
||||||
if (!iommu->dummy_page) {
|
__pa(iommu->page_table));
|
||||||
prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
|
|
||||||
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
|
|
||||||
|
|
||||||
/* Using assumed page size 8K with 128K entries we need 1MB iommu page
|
|
||||||
* table (128K ioptes * 8 bytes per iopte). This is
|
|
||||||
* page order 7 on UltraSparc.
|
|
||||||
*/
|
|
||||||
tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE));
|
|
||||||
if (!tsbbase) {
|
|
||||||
prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n");
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
iommu->page_table = (iopte_t *)tsbbase;
|
|
||||||
iommu->page_table_sz_bits = 17;
|
|
||||||
iommu->page_table_map_base = 0xc0000000;
|
|
||||||
iommu->dma_addr_mask = 0xffffffff;
|
|
||||||
pci_iommu_table_init(iommu, IO_TSB_SIZE);
|
|
||||||
|
|
||||||
/* We start with no consistent mappings. */
|
|
||||||
iommu->lowest_consistent_map =
|
|
||||||
1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);
|
|
||||||
|
|
||||||
for (i = 0; i < PBM_NCLUSTERS; i++) {
|
|
||||||
iommu->alloc_info[i].flush = 0;
|
|
||||||
iommu->alloc_info[i].next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
|
|
||||||
|
|
||||||
control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
|
control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
|
||||||
control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
|
control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
|
||||||
@ -1281,7 +1247,7 @@ static void psycho_iommu_init(struct pci_controller_info *p)
|
|||||||
psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
|
psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
|
||||||
|
|
||||||
/* If necessary, hook us up for starfire IRQ translations. */
|
/* If necessary, hook us up for starfire IRQ translations. */
|
||||||
if(this_is_starfire)
|
if (this_is_starfire)
|
||||||
p->starfire_cookie = starfire_hookup(p->pbm_A.portid);
|
p->starfire_cookie = starfire_hookup(p->pbm_A.portid);
|
||||||
else
|
else
|
||||||
p->starfire_cookie = NULL;
|
p->starfire_cookie = NULL;
|
||||||
|
@ -1267,13 +1267,9 @@ static void sabre_iommu_init(struct pci_controller_info *p,
|
|||||||
u32 dma_mask)
|
u32 dma_mask)
|
||||||
{
|
{
|
||||||
struct pci_iommu *iommu = p->pbm_A.iommu;
|
struct pci_iommu *iommu = p->pbm_A.iommu;
|
||||||
unsigned long tsbbase, i, order;
|
unsigned long i;
|
||||||
u64 control;
|
u64 control;
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
|
||||||
spin_lock_init(&iommu->lock);
|
|
||||||
iommu->ctx_lowest_free = 1;
|
|
||||||
|
|
||||||
/* Register addresses. */
|
/* Register addresses. */
|
||||||
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
|
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
|
||||||
iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
|
iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
|
||||||
@ -1295,26 +1291,10 @@ static void sabre_iommu_init(struct pci_controller_info *p,
|
|||||||
/* Leave diag mode enabled for full-flushing done
|
/* Leave diag mode enabled for full-flushing done
|
||||||
* in pci_iommu.c
|
* in pci_iommu.c
|
||||||
*/
|
*/
|
||||||
|
pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask);
|
||||||
|
|
||||||
iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
|
sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE,
|
||||||
if (!iommu->dummy_page) {
|
__pa(iommu->page_table));
|
||||||
prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
|
|
||||||
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
|
|
||||||
|
|
||||||
tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
|
|
||||||
if (!tsbbase) {
|
|
||||||
prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
iommu->page_table = (iopte_t *)tsbbase;
|
|
||||||
iommu->page_table_map_base = dvma_offset;
|
|
||||||
iommu->dma_addr_mask = dma_mask;
|
|
||||||
pci_iommu_table_init(iommu, PAGE_SIZE << order);
|
|
||||||
|
|
||||||
sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
|
|
||||||
|
|
||||||
control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
|
control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
|
||||||
control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
|
control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
|
||||||
@ -1322,11 +1302,9 @@ static void sabre_iommu_init(struct pci_controller_info *p,
|
|||||||
switch(tsbsize) {
|
switch(tsbsize) {
|
||||||
case 64:
|
case 64:
|
||||||
control |= SABRE_IOMMU_TSBSZ_64K;
|
control |= SABRE_IOMMU_TSBSZ_64K;
|
||||||
iommu->page_table_sz_bits = 16;
|
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128:
|
||||||
control |= SABRE_IOMMU_TSBSZ_128K;
|
control |= SABRE_IOMMU_TSBSZ_128K;
|
||||||
iommu->page_table_sz_bits = 17;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
|
prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
|
||||||
@ -1334,15 +1312,6 @@ static void sabre_iommu_init(struct pci_controller_info *p,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
|
sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
|
||||||
|
|
||||||
/* We start with no consistent mappings. */
|
|
||||||
iommu->lowest_consistent_map =
|
|
||||||
1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);
|
|
||||||
|
|
||||||
for (i = 0; i < PBM_NCLUSTERS; i++) {
|
|
||||||
iommu->alloc_info[i].flush = 0;
|
|
||||||
iommu->alloc_info[i].next = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pbm_register_toplevel_resources(struct pci_controller_info *p,
|
static void pbm_register_toplevel_resources(struct pci_controller_info *p,
|
||||||
|
@ -1765,7 +1765,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
|
|||||||
static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||||
{
|
{
|
||||||
struct pci_iommu *iommu = pbm->iommu;
|
struct pci_iommu *iommu = pbm->iommu;
|
||||||
unsigned long tsbbase, i, tagbase, database, order;
|
unsigned long i, tagbase, database;
|
||||||
u32 vdma[2], dma_mask;
|
u32 vdma[2], dma_mask;
|
||||||
u64 control;
|
u64 control;
|
||||||
int err, tsbsize;
|
int err, tsbsize;
|
||||||
@ -1800,10 +1800,6 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||||||
prom_halt();
|
prom_halt();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
|
||||||
spin_lock_init(&iommu->lock);
|
|
||||||
iommu->ctx_lowest_free = 1;
|
|
||||||
|
|
||||||
/* Register addresses, SCHIZO has iommu ctx flushing. */
|
/* Register addresses, SCHIZO has iommu ctx flushing. */
|
||||||
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
|
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
|
||||||
iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
|
iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
|
||||||
@ -1832,56 +1828,9 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||||||
/* Leave diag mode enabled for full-flushing done
|
/* Leave diag mode enabled for full-flushing done
|
||||||
* in pci_iommu.c
|
* in pci_iommu.c
|
||||||
*/
|
*/
|
||||||
|
pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
|
||||||
|
|
||||||
iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
|
schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table));
|
||||||
if (!iommu->dummy_page) {
|
|
||||||
prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
|
|
||||||
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
|
|
||||||
|
|
||||||
/* Using assumed page size 8K with 128K entries we need 1MB iommu page
|
|
||||||
* table (128K ioptes * 8 bytes per iopte). This is
|
|
||||||
* page order 7 on UltraSparc.
|
|
||||||
*/
|
|
||||||
order = get_order(tsbsize * 8 * 1024);
|
|
||||||
tsbbase = __get_free_pages(GFP_KERNEL, order);
|
|
||||||
if (!tsbbase) {
|
|
||||||
prom_printf("%s: Error, gfp(tsb) failed.\n", pbm->name);
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
|
|
||||||
iommu->page_table = (iopte_t *)tsbbase;
|
|
||||||
iommu->page_table_map_base = vdma[0];
|
|
||||||
iommu->dma_addr_mask = dma_mask;
|
|
||||||
pci_iommu_table_init(iommu, PAGE_SIZE << order);
|
|
||||||
|
|
||||||
switch (tsbsize) {
|
|
||||||
case 64:
|
|
||||||
iommu->page_table_sz_bits = 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 128:
|
|
||||||
iommu->page_table_sz_bits = 17;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
|
|
||||||
prom_halt();
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* We start with no consistent mappings. */
|
|
||||||
iommu->lowest_consistent_map =
|
|
||||||
1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);
|
|
||||||
|
|
||||||
for (i = 0; i < PBM_NCLUSTERS; i++) {
|
|
||||||
iommu->alloc_info[i].flush = 0;
|
|
||||||
iommu->alloc_info[i].next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
schizo_write(iommu->iommu_tsbbase, __pa(tsbbase));
|
|
||||||
|
|
||||||
control = schizo_read(iommu->iommu_control);
|
control = schizo_read(iommu->iommu_control);
|
||||||
control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ);
|
control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/ebus.h>
|
#include <asm/ebus.h>
|
||||||
|
#include <asm/isa.h>
|
||||||
#include <asm/auxio.h>
|
#include <asm/auxio.h>
|
||||||
|
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
@ -100,46 +101,83 @@ static int powerd(void *__unused)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init has_button_interrupt(struct linux_ebus_device *edev)
|
static int __init has_button_interrupt(unsigned int irq, int prom_node)
|
||||||
{
|
{
|
||||||
if (edev->irqs[0] == PCI_IRQ_NONE)
|
if (irq == PCI_IRQ_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
if (!prom_node_has_property(edev->prom_node, "button"))
|
if (!prom_node_has_property(prom_node, "button"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init power_init(void)
|
static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
|
||||||
{
|
{
|
||||||
struct linux_ebus *ebus;
|
struct linux_ebus *ebus;
|
||||||
struct linux_ebus_device *edev;
|
struct linux_ebus_device *edev;
|
||||||
|
|
||||||
|
for_each_ebus(ebus) {
|
||||||
|
for_each_ebusdev(edev, ebus) {
|
||||||
|
if (!strcmp(edev->prom_name, "power")) {
|
||||||
|
*resp = &edev->resource[0];
|
||||||
|
*irq_p = edev->irqs[0];
|
||||||
|
*prom_node_p = edev->prom_node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
|
||||||
|
{
|
||||||
|
struct sparc_isa_bridge *isa_bus;
|
||||||
|
struct sparc_isa_device *isa_dev;
|
||||||
|
|
||||||
|
for_each_isa(isa_bus) {
|
||||||
|
for_each_isadev(isa_dev, isa_bus) {
|
||||||
|
if (!strcmp(isa_dev->prom_name, "power")) {
|
||||||
|
*resp = &isa_dev->resource;
|
||||||
|
*irq_p = isa_dev->irq;
|
||||||
|
*prom_node_p = isa_dev->prom_node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init power_init(void)
|
||||||
|
{
|
||||||
|
struct resource *res = NULL;
|
||||||
|
unsigned int irq;
|
||||||
|
int prom_node;
|
||||||
static int invoked;
|
static int invoked;
|
||||||
|
|
||||||
if (invoked)
|
if (invoked)
|
||||||
return;
|
return;
|
||||||
invoked = 1;
|
invoked = 1;
|
||||||
|
|
||||||
for_each_ebus(ebus) {
|
if (!power_probe_ebus(&res, &irq, &prom_node))
|
||||||
for_each_ebusdev(edev, ebus) {
|
goto found;
|
||||||
if (!strcmp(edev->prom_name, "power"))
|
|
||||||
goto found;
|
if (!power_probe_isa(&res, &irq, &prom_node))
|
||||||
}
|
goto found;
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
power_reg = ioremap(edev->resource[0].start, 0x4);
|
power_reg = ioremap(res->start, 0x4);
|
||||||
printk("power: Control reg at %p ... ", power_reg);
|
printk("power: Control reg at %p ... ", power_reg);
|
||||||
poweroff_method = machine_halt; /* able to use the standard halt */
|
poweroff_method = machine_halt; /* able to use the standard halt */
|
||||||
if (has_button_interrupt(edev)) {
|
if (has_button_interrupt(irq, prom_node)) {
|
||||||
if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
|
if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
|
||||||
printk("Failed to start power daemon.\n");
|
printk("Failed to start power daemon.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printk("powerd running.\n");
|
printk("powerd running.\n");
|
||||||
|
|
||||||
if (request_irq(edev->irqs[0],
|
if (request_irq(irq,
|
||||||
power_handler, SA_SHIRQ, "power", NULL) < 0)
|
power_handler, SA_SHIRQ, "power", NULL) < 0)
|
||||||
printk("power: Error, cannot register IRQ handler.\n");
|
printk("power: Error, cannot register IRQ handler.\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -312,32 +312,33 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5
|
|||||||
wr %g1, FPRS_FEF, %fprs
|
wr %g1, FPRS_FEF, %fprs
|
||||||
ldx [%o1 + %o5], %g1
|
ldx [%o1 + %o5], %g1
|
||||||
add %g6, TI_XFSR, %o1
|
add %g6, TI_XFSR, %o1
|
||||||
membar #StoreLoad | #LoadLoad
|
|
||||||
sll %o0, 8, %o2
|
sll %o0, 8, %o2
|
||||||
add %g6, TI_FPREGS, %o3
|
add %g6, TI_FPREGS, %o3
|
||||||
brz,pn %l6, 1f
|
brz,pn %l6, 1f
|
||||||
add %g6, TI_FPREGS+0x40, %o4
|
add %g6, TI_FPREGS+0x40, %o4
|
||||||
|
|
||||||
|
membar #Sync
|
||||||
ldda [%o3 + %o2] ASI_BLK_P, %f0
|
ldda [%o3 + %o2] ASI_BLK_P, %f0
|
||||||
ldda [%o4 + %o2] ASI_BLK_P, %f16
|
ldda [%o4 + %o2] ASI_BLK_P, %f16
|
||||||
|
membar #Sync
|
||||||
1: andcc %l2, FPRS_DU, %g0
|
1: andcc %l2, FPRS_DU, %g0
|
||||||
be,pn %icc, 1f
|
be,pn %icc, 1f
|
||||||
wr %g1, 0, %gsr
|
wr %g1, 0, %gsr
|
||||||
add %o2, 0x80, %o2
|
add %o2, 0x80, %o2
|
||||||
|
membar #Sync
|
||||||
ldda [%o3 + %o2] ASI_BLK_P, %f32
|
ldda [%o3 + %o2] ASI_BLK_P, %f32
|
||||||
ldda [%o4 + %o2] ASI_BLK_P, %f48
|
ldda [%o4 + %o2] ASI_BLK_P, %f48
|
||||||
|
|
||||||
1: membar #Sync
|
1: membar #Sync
|
||||||
ldx [%o1 + %o5], %fsr
|
ldx [%o1 + %o5], %fsr
|
||||||
2: stb %l5, [%g6 + TI_FPDEPTH]
|
2: stb %l5, [%g6 + TI_FPDEPTH]
|
||||||
ba,pt %xcc, rt_continue
|
ba,pt %xcc, rt_continue
|
||||||
nop
|
nop
|
||||||
5: wr %g0, FPRS_FEF, %fprs
|
5: wr %g0, FPRS_FEF, %fprs
|
||||||
membar #StoreLoad | #LoadLoad
|
|
||||||
sll %o0, 8, %o2
|
sll %o0, 8, %o2
|
||||||
|
|
||||||
add %g6, TI_FPREGS+0x80, %o3
|
add %g6, TI_FPREGS+0x80, %o3
|
||||||
add %g6, TI_FPREGS+0xc0, %o4
|
add %g6, TI_FPREGS+0xc0, %o4
|
||||||
|
membar #Sync
|
||||||
ldda [%o3 + %o2] ASI_BLK_P, %f32
|
ldda [%o3 + %o2] ASI_BLK_P, %f32
|
||||||
ldda [%o4 + %o2] ASI_BLK_P, %f48
|
ldda [%o4 + %o2] ASI_BLK_P, %f48
|
||||||
membar #Sync
|
membar #Sync
|
||||||
|
@ -1001,13 +1001,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
|
|||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern unsigned long xcall_promstop;
|
|
||||||
|
|
||||||
void smp_promstop_others(void)
|
|
||||||
{
|
|
||||||
smp_cross_call(&xcall_promstop, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
|
#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
|
||||||
#define prof_counter(__cpu) cpu_data(__cpu).counter
|
#define prof_counter(__cpu) cpu_data(__cpu).counter
|
||||||
|
|
||||||
|
@ -59,15 +59,17 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
|
|||||||
be,pn %icc, 9b
|
be,pn %icc, 9b
|
||||||
add %g6, TI_FPREGS, %g2
|
add %g6, TI_FPREGS, %g2
|
||||||
andcc %o5, FPRS_DL, %g0
|
andcc %o5, FPRS_DL, %g0
|
||||||
membar #StoreStore | #LoadStore
|
|
||||||
|
|
||||||
be,pn %icc, 4f
|
be,pn %icc, 4f
|
||||||
add %g6, TI_FPREGS+0x40, %g3
|
add %g6, TI_FPREGS+0x40, %g3
|
||||||
|
membar #Sync
|
||||||
stda %f0, [%g2 + %g1] ASI_BLK_P
|
stda %f0, [%g2 + %g1] ASI_BLK_P
|
||||||
stda %f16, [%g3 + %g1] ASI_BLK_P
|
stda %f16, [%g3 + %g1] ASI_BLK_P
|
||||||
|
membar #Sync
|
||||||
andcc %o5, FPRS_DU, %g0
|
andcc %o5, FPRS_DU, %g0
|
||||||
be,pn %icc, 5f
|
be,pn %icc, 5f
|
||||||
4: add %g1, 128, %g1
|
4: add %g1, 128, %g1
|
||||||
|
membar #Sync
|
||||||
stda %f32, [%g2 + %g1] ASI_BLK_P
|
stda %f32, [%g2 + %g1] ASI_BLK_P
|
||||||
|
|
||||||
stda %f48, [%g3 + %g1] ASI_BLK_P
|
stda %f48, [%g3 + %g1] ASI_BLK_P
|
||||||
@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
|
|||||||
sll %g1, 5, %g1
|
sll %g1, 5, %g1
|
||||||
add %g6, TI_FPREGS+0xc0, %g3
|
add %g6, TI_FPREGS+0xc0, %g3
|
||||||
wr %g0, FPRS_FEF, %fprs
|
wr %g0, FPRS_FEF, %fprs
|
||||||
membar #StoreStore | #LoadStore
|
membar #Sync
|
||||||
stda %f32, [%g2 + %g1] ASI_BLK_P
|
stda %f32, [%g2 + %g1] ASI_BLK_P
|
||||||
stda %f48, [%g3 + %g1] ASI_BLK_P
|
stda %f48, [%g3 + %g1] ASI_BLK_P
|
||||||
membar #Sync
|
membar #Sync
|
||||||
@ -128,8 +130,8 @@ VISenterhalf:
|
|||||||
be,pn %icc, 4f
|
be,pn %icc, 4f
|
||||||
add %g6, TI_FPREGS, %g2
|
add %g6, TI_FPREGS, %g2
|
||||||
|
|
||||||
membar #StoreStore | #LoadStore
|
|
||||||
add %g6, TI_FPREGS+0x40, %g3
|
add %g6, TI_FPREGS+0x40, %g3
|
||||||
|
membar #Sync
|
||||||
stda %f0, [%g2 + %g1] ASI_BLK_P
|
stda %f0, [%g2 + %g1] ASI_BLK_P
|
||||||
stda %f16, [%g3 + %g1] ASI_BLK_P
|
stda %f16, [%g3 + %g1] ASI_BLK_P
|
||||||
membar #Sync
|
membar #Sync
|
||||||
|
@ -105,7 +105,7 @@ static void __init read_obp_memory(const char *property,
|
|||||||
regs[i].phys_addr = base;
|
regs[i].phys_addr = base;
|
||||||
regs[i].reg_size = size;
|
regs[i].reg_size = size;
|
||||||
}
|
}
|
||||||
sort(regs, ents, sizeof(struct linux_prom64_registers),
|
sort(regs, ents, sizeof(struct linux_prom64_registers),
|
||||||
cmp_p64, NULL);
|
cmp_p64, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,8 +367,11 @@ struct linux_prom_translation {
|
|||||||
unsigned long size;
|
unsigned long size;
|
||||||
unsigned long data;
|
unsigned long data;
|
||||||
};
|
};
|
||||||
static struct linux_prom_translation prom_trans[512] __initdata;
|
|
||||||
static unsigned int prom_trans_ents __initdata;
|
/* Exported for kernel TLB miss handling in ktlb.S */
|
||||||
|
struct linux_prom_translation prom_trans[512] __read_mostly;
|
||||||
|
unsigned int prom_trans_ents __read_mostly;
|
||||||
|
unsigned int swapper_pgd_zero __read_mostly;
|
||||||
|
|
||||||
extern unsigned long prom_boot_page;
|
extern unsigned long prom_boot_page;
|
||||||
extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
|
extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
|
||||||
@ -378,122 +381,57 @@ extern void register_prom_callbacks(void);
|
|||||||
/* Exported for SMP bootup purposes. */
|
/* Exported for SMP bootup purposes. */
|
||||||
unsigned long kern_locked_tte_data;
|
unsigned long kern_locked_tte_data;
|
||||||
|
|
||||||
/* Exported for kernel TLB miss handling in ktlb.S */
|
|
||||||
unsigned long prom_pmd_phys __read_mostly;
|
|
||||||
unsigned int swapper_pgd_zero __read_mostly;
|
|
||||||
|
|
||||||
static pmd_t *prompmd __read_mostly;
|
|
||||||
|
|
||||||
#define BASE_PAGE_SIZE 8192
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Translate PROM's mapping we capture at boot time into physical address.
|
* Translate PROM's mapping we capture at boot time into physical address.
|
||||||
* The second parameter is only set from prom_callback() invocations.
|
* The second parameter is only set from prom_callback() invocations.
|
||||||
*/
|
*/
|
||||||
unsigned long prom_virt_to_phys(unsigned long promva, int *error)
|
unsigned long prom_virt_to_phys(unsigned long promva, int *error)
|
||||||
{
|
{
|
||||||
pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
|
int i;
|
||||||
pte_t *ptep;
|
|
||||||
unsigned long base;
|
|
||||||
|
|
||||||
if (pmd_none(*pmdp)) {
|
for (i = 0; i < prom_trans_ents; i++) {
|
||||||
if (error)
|
struct linux_prom_translation *p = &prom_trans[i];
|
||||||
*error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
|
|
||||||
if (!pte_present(*ptep)) {
|
|
||||||
if (error)
|
|
||||||
*error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
*error = 0;
|
|
||||||
return pte_val(*ptep);
|
|
||||||
}
|
|
||||||
base = pte_val(*ptep) & _PAGE_PADDR;
|
|
||||||
|
|
||||||
return base + (promva & (BASE_PAGE_SIZE - 1));
|
if (promva >= p->virt &&
|
||||||
|
promva < (p->virt + p->size)) {
|
||||||
|
unsigned long base = p->data & _PAGE_PADDR;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = 0;
|
||||||
|
return base + (promva & (8192 - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
*error = 1;
|
||||||
|
return 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The obp translations are saved based on 8k pagesize, since obp can
|
/* The obp translations are saved based on 8k pagesize, since obp can
|
||||||
* use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
|
* use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
|
||||||
* HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte
|
* HI_OBP_ADDRESS range are handled in ktlb.S and do not use the vpte
|
||||||
* scheme (also, see rant in inherit_locked_prom_mappings()).
|
* scheme (also, see rant in inherit_locked_prom_mappings()).
|
||||||
*/
|
*/
|
||||||
static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data)
|
|
||||||
{
|
|
||||||
unsigned long vaddr;
|
|
||||||
|
|
||||||
for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
|
|
||||||
unsigned long val;
|
|
||||||
pmd_t *pmd;
|
|
||||||
pte_t *pte;
|
|
||||||
|
|
||||||
pmd = prompmd + ((vaddr >> 23) & 0x7ff);
|
|
||||||
if (pmd_none(*pmd)) {
|
|
||||||
pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE,
|
|
||||||
PAGE_SIZE);
|
|
||||||
if (!pte)
|
|
||||||
prom_halt();
|
|
||||||
memset(pte, 0, BASE_PAGE_SIZE);
|
|
||||||
pmd_set(pmd, pte);
|
|
||||||
}
|
|
||||||
pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff);
|
|
||||||
|
|
||||||
val = data;
|
|
||||||
|
|
||||||
/* Clear diag TTE bits. */
|
|
||||||
if (tlb_type == spitfire)
|
|
||||||
val &= ~0x0003fe0000000000UL;
|
|
||||||
|
|
||||||
set_pte_at(&init_mm, vaddr, pte,
|
|
||||||
__pte(val | _PAGE_MODIFIED));
|
|
||||||
|
|
||||||
data += BASE_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int in_obp_range(unsigned long vaddr)
|
static inline int in_obp_range(unsigned long vaddr)
|
||||||
{
|
{
|
||||||
return (vaddr >= LOW_OBP_ADDRESS &&
|
return (vaddr >= LOW_OBP_ADDRESS &&
|
||||||
vaddr < HI_OBP_ADDRESS);
|
vaddr < HI_OBP_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OBP_PMD_SIZE 2048
|
static int cmp_ptrans(const void *a, const void *b)
|
||||||
static void __init build_obp_pgtable(void)
|
|
||||||
{
|
{
|
||||||
unsigned long i;
|
const struct linux_prom_translation *x = a, *y = b;
|
||||||
|
|
||||||
prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE);
|
if (x->virt > y->virt)
|
||||||
if (!prompmd)
|
return 1;
|
||||||
prom_halt();
|
if (x->virt < y->virt)
|
||||||
|
return -1;
|
||||||
memset(prompmd, 0, OBP_PMD_SIZE);
|
return 0;
|
||||||
|
|
||||||
prom_pmd_phys = __pa(prompmd);
|
|
||||||
|
|
||||||
for (i = 0; i < prom_trans_ents; i++) {
|
|
||||||
unsigned long start, end;
|
|
||||||
|
|
||||||
if (!in_obp_range(prom_trans[i].virt))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
start = prom_trans[i].virt;
|
|
||||||
end = start + prom_trans[i].size;
|
|
||||||
if (end > HI_OBP_ADDRESS)
|
|
||||||
end = HI_OBP_ADDRESS;
|
|
||||||
|
|
||||||
build_obp_range(start, end, prom_trans[i].data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read OBP translations property into 'prom_trans[]'.
|
/* Read OBP translations property into 'prom_trans[]'. */
|
||||||
* Return the number of entries.
|
|
||||||
*/
|
|
||||||
static void __init read_obp_translations(void)
|
static void __init read_obp_translations(void)
|
||||||
{
|
{
|
||||||
int n, node;
|
int n, node, ents, first, last, i;
|
||||||
|
|
||||||
node = prom_finddevice("/virtual-memory");
|
node = prom_finddevice("/virtual-memory");
|
||||||
n = prom_getproplen(node, "translations");
|
n = prom_getproplen(node, "translations");
|
||||||
@ -515,7 +453,41 @@ static void __init read_obp_translations(void)
|
|||||||
|
|
||||||
n = n / sizeof(struct linux_prom_translation);
|
n = n / sizeof(struct linux_prom_translation);
|
||||||
|
|
||||||
prom_trans_ents = n;
|
ents = n;
|
||||||
|
|
||||||
|
sort(prom_trans, ents, sizeof(struct linux_prom_translation),
|
||||||
|
cmp_ptrans, NULL);
|
||||||
|
|
||||||
|
/* Now kick out all the non-OBP entries. */
|
||||||
|
for (i = 0; i < ents; i++) {
|
||||||
|
if (in_obp_range(prom_trans[i].virt))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first = i;
|
||||||
|
for (; i < ents; i++) {
|
||||||
|
if (!in_obp_range(prom_trans[i].virt))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = i;
|
||||||
|
|
||||||
|
for (i = 0; i < (last - first); i++) {
|
||||||
|
struct linux_prom_translation *src = &prom_trans[i + first];
|
||||||
|
struct linux_prom_translation *dest = &prom_trans[i];
|
||||||
|
|
||||||
|
*dest = *src;
|
||||||
|
}
|
||||||
|
for (; i < ents; i++) {
|
||||||
|
struct linux_prom_translation *dest = &prom_trans[i];
|
||||||
|
dest->virt = dest->size = dest->data = 0x0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prom_trans_ents = last - first;
|
||||||
|
|
||||||
|
if (tlb_type == spitfire) {
|
||||||
|
/* Clear diag TTE bits. */
|
||||||
|
for (i = 0; i < prom_trans_ents; i++)
|
||||||
|
prom_trans[i].data &= ~0x0003fe0000000000UL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init remap_kernel(void)
|
static void __init remap_kernel(void)
|
||||||
@ -553,21 +525,18 @@ static void __init remap_kernel(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void __init inherit_prom_mappings_pre(void)
|
static void __init inherit_prom_mappings(void)
|
||||||
{
|
{
|
||||||
read_obp_translations();
|
read_obp_translations();
|
||||||
|
|
||||||
/* Now fixup OBP's idea about where we really are mapped. */
|
/* Now fixup OBP's idea about where we really are mapped. */
|
||||||
prom_printf("Remapping the kernel... ");
|
prom_printf("Remapping the kernel... ");
|
||||||
remap_kernel();
|
remap_kernel();
|
||||||
|
|
||||||
prom_printf("done.\n");
|
prom_printf("done.\n");
|
||||||
}
|
|
||||||
|
|
||||||
static void __init inherit_prom_mappings_post(void)
|
prom_printf("Registering callbacks... ");
|
||||||
{
|
|
||||||
build_obp_pgtable();
|
|
||||||
register_prom_callbacks();
|
register_prom_callbacks();
|
||||||
|
prom_printf("done.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The OBP specifications for sun4u mark 0xfffffffc00000000 and
|
/* The OBP specifications for sun4u mark 0xfffffffc00000000 and
|
||||||
@ -1519,7 +1488,7 @@ void __init paging_init(void)
|
|||||||
|
|
||||||
swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
|
swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
|
||||||
|
|
||||||
inherit_prom_mappings_pre();
|
inherit_prom_mappings();
|
||||||
|
|
||||||
/* Ok, we can use our TLB miss and window trap handlers safely.
|
/* Ok, we can use our TLB miss and window trap handlers safely.
|
||||||
* We need to do a quick peek here to see if we are on StarFire
|
* We need to do a quick peek here to see if we are on StarFire
|
||||||
@ -1530,23 +1499,15 @@ void __init paging_init(void)
|
|||||||
extern void setup_tba(int);
|
extern void setup_tba(int);
|
||||||
setup_tba(this_is_starfire);
|
setup_tba(this_is_starfire);
|
||||||
}
|
}
|
||||||
__flush_tlb_all();
|
|
||||||
|
|
||||||
/* Everything from this point forward, until we are done with
|
inherit_locked_prom_mappings(1);
|
||||||
* inherit_prom_mappings_post(), must complete successfully
|
|
||||||
* without calling into the firmware. The firwmare page tables
|
__flush_tlb_all();
|
||||||
* have not been built, but we are running on the Linux kernel's
|
|
||||||
* trap table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Setup bootmem... */
|
/* Setup bootmem... */
|
||||||
pages_avail = 0;
|
pages_avail = 0;
|
||||||
last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
|
last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
|
||||||
|
|
||||||
inherit_prom_mappings_post();
|
|
||||||
|
|
||||||
inherit_locked_prom_mappings(1);
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||||
kernel_physical_mapping_init();
|
kernel_physical_mapping_init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -453,22 +453,6 @@ xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
|
|||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
||||||
.globl xcall_promstop
|
|
||||||
xcall_promstop:
|
|
||||||
rdpr %pstate, %g2
|
|
||||||
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
|
|
||||||
rdpr %pil, %g2
|
|
||||||
wrpr %g0, 15, %pil
|
|
||||||
sethi %hi(109f), %g7
|
|
||||||
b,pt %xcc, etrap_irq
|
|
||||||
109: or %g7, %lo(109b), %g7
|
|
||||||
flushw
|
|
||||||
call prom_stopself
|
|
||||||
nop
|
|
||||||
/* We should not return, just spin if we do... */
|
|
||||||
1: b,a,pt %xcc, 1b
|
|
||||||
nop
|
|
||||||
|
|
||||||
.data
|
.data
|
||||||
|
|
||||||
errata32_hwbug:
|
errata32_hwbug:
|
||||||
|
@ -68,19 +68,11 @@ void prom_cmdline(void)
|
|||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
extern void smp_promstop_others(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Drop into the prom, but completely terminate the program.
|
/* Drop into the prom, but completely terminate the program.
|
||||||
* No chance of continuing.
|
* No chance of continuing.
|
||||||
*/
|
*/
|
||||||
void prom_halt(void)
|
void prom_halt(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
smp_promstop_others();
|
|
||||||
udelay(8000);
|
|
||||||
#endif
|
|
||||||
again:
|
again:
|
||||||
p1275_cmd("exit", P1275_INOUT(0, 0));
|
p1275_cmd("exit", P1275_INOUT(0, 0));
|
||||||
goto again; /* PROM is out to get me -DaveM */
|
goto again; /* PROM is out to get me -DaveM */
|
||||||
@ -88,10 +80,6 @@ void prom_halt(void)
|
|||||||
|
|
||||||
void prom_halt_power_off(void)
|
void prom_halt_power_off(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
smp_promstop_others();
|
|
||||||
udelay(8000);
|
|
||||||
#endif
|
|
||||||
p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
|
p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
|
||||||
|
|
||||||
/* if nothing else helps, we just halt */
|
/* if nothing else helps, we just halt */
|
||||||
|
@ -152,7 +152,7 @@ archclean:
|
|||||||
$(SYMLINK_HEADERS):
|
$(SYMLINK_HEADERS):
|
||||||
@echo ' SYMLINK $@'
|
@echo ' SYMLINK $@'
|
||||||
ifneq ($(KBUILD_SRC),)
|
ifneq ($(KBUILD_SRC),)
|
||||||
ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
|
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
|
||||||
else
|
else
|
||||||
$(Q)cd $(TOPDIR)/$(dir $@) ; \
|
$(Q)cd $(TOPDIR)/$(dir $@) ; \
|
||||||
ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
|
ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
|
||||||
|
@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o
|
|||||||
net-objs := net_kern.o net_user.o
|
net-objs := net_kern.o net_user.o
|
||||||
mconsole-objs := mconsole_kern.o mconsole_user.o
|
mconsole-objs := mconsole_kern.o mconsole_user.o
|
||||||
hostaudio-objs := hostaudio_kern.o
|
hostaudio-objs := hostaudio_kern.o
|
||||||
ubd-objs := ubd_kern.o
|
ubd-objs := ubd_kern.o ubd_user.o
|
||||||
port-objs := port_kern.o port_user.o
|
port-objs := port_kern.o port_user.o
|
||||||
harddog-objs := harddog_kern.o harddog_user.o
|
harddog-objs := harddog_kern.o harddog_user.o
|
||||||
|
|
||||||
|
@ -3,15 +3,40 @@
|
|||||||
|
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
|
|
||||||
#if defined(__BIG_ENDIAN)
|
#if defined(__KERNEL__)
|
||||||
# define ntohll(x) (x)
|
|
||||||
# define htonll(x) (x)
|
# include <asm/byteorder.h>
|
||||||
#elif defined(__LITTLE_ENDIAN)
|
|
||||||
# define ntohll(x) bswap_64(x)
|
# if defined(__BIG_ENDIAN)
|
||||||
# define htonll(x) bswap_64(x)
|
# define ntohll(x) (x)
|
||||||
|
# define htonll(x) (x)
|
||||||
|
# elif defined(__LITTLE_ENDIAN)
|
||||||
|
# define ntohll(x) be64_to_cpu(x)
|
||||||
|
# define htonll(x) cpu_to_be64(x)
|
||||||
|
# else
|
||||||
|
# error "Could not determine byte order"
|
||||||
|
# endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "__BYTE_ORDER not defined"
|
/* For the definition of ntohl, htonl and __BYTE_ORDER */
|
||||||
|
#include <endian.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#if defined(__BYTE_ORDER)
|
||||||
|
|
||||||
|
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
# define ntohll(x) (x)
|
||||||
|
# define htonll(x) (x)
|
||||||
|
# elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
# define ntohll(x) bswap_64(x)
|
||||||
|
# define htonll(x) bswap_64(x)
|
||||||
|
# else
|
||||||
|
# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* ! defined(__BYTE_ORDER) */
|
||||||
|
# error "Could not determine byte order: __BYTE_ORDER not defined"
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* ! defined(__KERNEL__) */
|
||||||
|
|
||||||
extern int init_cow_file(int fd, char *cow_file, char *backing_file,
|
extern int init_cow_file(int fd, char *cow_file, char *backing_file,
|
||||||
int sectorsize, int alignment, int *bitmap_offset_out,
|
int sectorsize, int alignment, int *bitmap_offset_out,
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include "linux/blkpg.h"
|
#include "linux/blkpg.h"
|
||||||
#include "linux/genhd.h"
|
#include "linux/genhd.h"
|
||||||
#include "linux/spinlock.h"
|
#include "linux/spinlock.h"
|
||||||
#include "asm/atomic.h"
|
|
||||||
#include "asm/segment.h"
|
#include "asm/segment.h"
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "asm/irq.h"
|
#include "asm/irq.h"
|
||||||
@ -54,21 +53,20 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "mem_kern.h"
|
#include "mem_kern.h"
|
||||||
#include "cow.h"
|
#include "cow.h"
|
||||||
#include "aio.h"
|
|
||||||
|
|
||||||
enum ubd_req { UBD_READ, UBD_WRITE };
|
enum ubd_req { UBD_READ, UBD_WRITE };
|
||||||
|
|
||||||
struct io_thread_req {
|
struct io_thread_req {
|
||||||
enum aio_type op;
|
enum ubd_req op;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
unsigned long offsets[2];
|
unsigned long offsets[2];
|
||||||
unsigned long long offset;
|
unsigned long long offset;
|
||||||
unsigned long length;
|
unsigned long length;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
int sectorsize;
|
int sectorsize;
|
||||||
int bitmap_offset;
|
unsigned long sector_mask;
|
||||||
long bitmap_start;
|
unsigned long long cow_offset;
|
||||||
long bitmap_end;
|
unsigned long bitmap_words[2];
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,31 +80,28 @@ extern int create_cow_file(char *cow_file, char *backing_file,
|
|||||||
unsigned long *bitmap_len_out,
|
unsigned long *bitmap_len_out,
|
||||||
int *data_offset_out);
|
int *data_offset_out);
|
||||||
extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
|
extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
|
||||||
extern void do_io(struct io_thread_req *req, struct request *r,
|
extern void do_io(struct io_thread_req *req);
|
||||||
unsigned long *bitmap);
|
|
||||||
|
|
||||||
static inline int ubd_test_bit(__u64 bit, void *data)
|
static inline int ubd_test_bit(__u64 bit, unsigned char *data)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = data;
|
|
||||||
__u64 n;
|
__u64 n;
|
||||||
int bits, off;
|
int bits, off;
|
||||||
|
|
||||||
bits = sizeof(buffer[0]) * 8;
|
bits = sizeof(data[0]) * 8;
|
||||||
n = bit / bits;
|
n = bit / bits;
|
||||||
off = bit % bits;
|
off = bit % bits;
|
||||||
return((buffer[n] & (1 << off)) != 0);
|
return((data[n] & (1 << off)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ubd_set_bit(__u64 bit, void *data)
|
static inline void ubd_set_bit(__u64 bit, unsigned char *data)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = data;
|
|
||||||
__u64 n;
|
__u64 n;
|
||||||
int bits, off;
|
int bits, off;
|
||||||
|
|
||||||
bits = sizeof(buffer[0]) * 8;
|
bits = sizeof(data[0]) * 8;
|
||||||
n = bit / bits;
|
n = bit / bits;
|
||||||
off = bit % bits;
|
off = bit % bits;
|
||||||
buffer[n] |= (1 << off);
|
data[n] |= (1 << off);
|
||||||
}
|
}
|
||||||
/*End stuff from ubd_user.h*/
|
/*End stuff from ubd_user.h*/
|
||||||
|
|
||||||
@ -115,6 +110,8 @@ static inline void ubd_set_bit(__u64 bit, void *data)
|
|||||||
static DEFINE_SPINLOCK(ubd_io_lock);
|
static DEFINE_SPINLOCK(ubd_io_lock);
|
||||||
static DEFINE_SPINLOCK(ubd_lock);
|
static DEFINE_SPINLOCK(ubd_lock);
|
||||||
|
|
||||||
|
static void (*do_ubd)(void);
|
||||||
|
|
||||||
static int ubd_open(struct inode * inode, struct file * filp);
|
static int ubd_open(struct inode * inode, struct file * filp);
|
||||||
static int ubd_release(struct inode * inode, struct file * file);
|
static int ubd_release(struct inode * inode, struct file * file);
|
||||||
static int ubd_ioctl(struct inode * inode, struct file * file,
|
static int ubd_ioctl(struct inode * inode, struct file * file,
|
||||||
@ -161,8 +158,6 @@ struct cow {
|
|||||||
int data_offset;
|
int data_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SG 64
|
|
||||||
|
|
||||||
struct ubd {
|
struct ubd {
|
||||||
char *file;
|
char *file;
|
||||||
int count;
|
int count;
|
||||||
@ -173,7 +168,6 @@ struct ubd {
|
|||||||
int no_cow;
|
int no_cow;
|
||||||
struct cow cow;
|
struct cow cow;
|
||||||
struct platform_device pdev;
|
struct platform_device pdev;
|
||||||
struct scatterlist sg[MAX_SG];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_COW { \
|
#define DEFAULT_COW { \
|
||||||
@ -466,114 +460,81 @@ __uml_help(fakehd,
|
|||||||
);
|
);
|
||||||
|
|
||||||
static void do_ubd_request(request_queue_t * q);
|
static void do_ubd_request(request_queue_t * q);
|
||||||
static int in_ubd;
|
|
||||||
|
/* Only changed by ubd_init, which is an initcall. */
|
||||||
|
int thread_fd = -1;
|
||||||
|
|
||||||
/* Changed by ubd_handler, which is serialized because interrupts only
|
/* Changed by ubd_handler, which is serialized because interrupts only
|
||||||
* happen on CPU 0.
|
* happen on CPU 0.
|
||||||
*/
|
*/
|
||||||
int intr_count = 0;
|
int intr_count = 0;
|
||||||
|
|
||||||
static void ubd_end_request(struct request *req, int bytes, int uptodate)
|
|
||||||
{
|
|
||||||
if (!end_that_request_first(req, uptodate, bytes >> 9)) {
|
|
||||||
add_disk_randomness(req->rq_disk);
|
|
||||||
end_that_request_last(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* call ubd_finish if you need to serialize */
|
/* call ubd_finish if you need to serialize */
|
||||||
static void __ubd_finish(struct request *req, int bytes)
|
static void __ubd_finish(struct request *req, int error)
|
||||||
{
|
{
|
||||||
if(bytes < 0){
|
int nsect;
|
||||||
ubd_end_request(req, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubd_end_request(req, bytes, 1);
|
if(error){
|
||||||
|
end_request(req, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsect = req->current_nr_sectors;
|
||||||
|
req->sector += nsect;
|
||||||
|
req->buffer += nsect << 9;
|
||||||
|
req->errors = 0;
|
||||||
|
req->nr_sectors -= nsect;
|
||||||
|
req->current_nr_sectors = 0;
|
||||||
|
end_request(req, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ubd_finish(struct request *req, int bytes)
|
static inline void ubd_finish(struct request *req, int error)
|
||||||
{
|
{
|
||||||
spin_lock(&ubd_io_lock);
|
spin_lock(&ubd_io_lock);
|
||||||
__ubd_finish(req, bytes);
|
__ubd_finish(req, error);
|
||||||
spin_unlock(&ubd_io_lock);
|
spin_unlock(&ubd_io_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bitmap_io {
|
/* Called without ubd_io_lock held */
|
||||||
atomic_t count;
|
static void ubd_handler(void)
|
||||||
struct aio_context aio;
|
{
|
||||||
};
|
struct io_thread_req req;
|
||||||
|
struct request *rq = elv_next_request(ubd_queue);
|
||||||
|
int n;
|
||||||
|
|
||||||
struct ubd_aio {
|
do_ubd = NULL;
|
||||||
struct aio_context aio;
|
intr_count++;
|
||||||
struct request *req;
|
n = os_read_file(thread_fd, &req, sizeof(req));
|
||||||
int len;
|
if(n != sizeof(req)){
|
||||||
struct bitmap_io *bitmap;
|
printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
|
||||||
void *bitmap_buf;
|
"err = %d\n", os_getpid(), -n);
|
||||||
};
|
spin_lock(&ubd_io_lock);
|
||||||
|
end_request(rq, 0);
|
||||||
static int ubd_reply_fd = -1;
|
spin_unlock(&ubd_io_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubd_finish(rq, req.error);
|
||||||
|
reactivate_fd(thread_fd, UBD_IRQ);
|
||||||
|
do_ubd_request(ubd_queue);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
|
static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
|
||||||
{
|
{
|
||||||
struct aio_thread_reply reply;
|
ubd_handler();
|
||||||
struct ubd_aio *aio;
|
|
||||||
struct request *req;
|
|
||||||
int err, n, fd = (int) (long) dev;
|
|
||||||
|
|
||||||
while(1){
|
|
||||||
err = os_read_file(fd, &reply, sizeof(reply));
|
|
||||||
if(err == -EAGAIN)
|
|
||||||
break;
|
|
||||||
if(err < 0){
|
|
||||||
printk("ubd_aio_handler - read returned err %d\n",
|
|
||||||
-err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
aio = container_of(reply.data, struct ubd_aio, aio);
|
|
||||||
n = reply.err;
|
|
||||||
|
|
||||||
if(n == 0){
|
|
||||||
req = aio->req;
|
|
||||||
req->nr_sectors -= aio->len >> 9;
|
|
||||||
|
|
||||||
if((aio->bitmap != NULL) &&
|
|
||||||
(atomic_dec_and_test(&aio->bitmap->count))){
|
|
||||||
aio->aio = aio->bitmap->aio;
|
|
||||||
aio->len = 0;
|
|
||||||
kfree(aio->bitmap);
|
|
||||||
aio->bitmap = NULL;
|
|
||||||
submit_aio(&aio->aio);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if((req->nr_sectors == 0) &&
|
|
||||||
(aio->bitmap == NULL)){
|
|
||||||
int len = req->hard_nr_sectors << 9;
|
|
||||||
ubd_finish(req, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(aio->bitmap_buf != NULL)
|
|
||||||
kfree(aio->bitmap_buf);
|
|
||||||
kfree(aio);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(n < 0){
|
|
||||||
ubd_finish(aio->req, n);
|
|
||||||
if(aio->bitmap != NULL)
|
|
||||||
kfree(aio->bitmap);
|
|
||||||
if(aio->bitmap_buf != NULL)
|
|
||||||
kfree(aio->bitmap_buf);
|
|
||||||
kfree(aio);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reactivate_fd(fd, UBD_IRQ);
|
|
||||||
|
|
||||||
do_ubd_request(ubd_queue);
|
|
||||||
|
|
||||||
return(IRQ_HANDLED);
|
return(IRQ_HANDLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only changed by ubd_init, which is an initcall. */
|
||||||
|
static int io_pid = -1;
|
||||||
|
|
||||||
|
void kill_io_thread(void)
|
||||||
|
{
|
||||||
|
if(io_pid != -1)
|
||||||
|
os_kill_process(io_pid, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__uml_exitcall(kill_io_thread);
|
||||||
|
|
||||||
static int ubd_file_size(struct ubd *dev, __u64 *size_out)
|
static int ubd_file_size(struct ubd *dev, __u64 *size_out)
|
||||||
{
|
{
|
||||||
char *file;
|
char *file;
|
||||||
@ -608,7 +569,7 @@ static int ubd_open_dev(struct ubd *dev)
|
|||||||
&dev->cow.data_offset, create_ptr);
|
&dev->cow.data_offset, create_ptr);
|
||||||
|
|
||||||
if((dev->fd == -ENOENT) && create_cow){
|
if((dev->fd == -ENOENT) && create_cow){
|
||||||
dev->fd = create_cow_file(dev->file, dev->cow.file,
|
dev->fd = create_cow_file(dev->file, dev->cow.file,
|
||||||
dev->openflags, 1 << 9, PAGE_SIZE,
|
dev->openflags, 1 << 9, PAGE_SIZE,
|
||||||
&dev->cow.bitmap_offset,
|
&dev->cow.bitmap_offset,
|
||||||
&dev->cow.bitmap_len,
|
&dev->cow.bitmap_len,
|
||||||
@ -870,10 +831,6 @@ int ubd_init(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr);
|
|
||||||
if(ubd_reply_fd < 0)
|
|
||||||
printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd);
|
|
||||||
|
|
||||||
devfs_mk_dir("ubd");
|
devfs_mk_dir("ubd");
|
||||||
if (register_blkdev(MAJOR_NR, "ubd"))
|
if (register_blkdev(MAJOR_NR, "ubd"))
|
||||||
return -1;
|
return -1;
|
||||||
@ -884,7 +841,6 @@ int ubd_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk_queue_max_hw_segments(ubd_queue, MAX_SG);
|
|
||||||
if (fake_major != MAJOR_NR) {
|
if (fake_major != MAJOR_NR) {
|
||||||
char name[sizeof("ubd_nnn\0")];
|
char name[sizeof("ubd_nnn\0")];
|
||||||
|
|
||||||
@ -896,12 +852,40 @@ int ubd_init(void)
|
|||||||
driver_register(&ubd_driver);
|
driver_register(&ubd_driver);
|
||||||
for (i = 0; i < MAX_DEV; i++)
|
for (i = 0; i < MAX_DEV; i++)
|
||||||
ubd_add(i);
|
ubd_add(i);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
late_initcall(ubd_init);
|
late_initcall(ubd_init);
|
||||||
|
|
||||||
|
int ubd_driver_init(void){
|
||||||
|
unsigned long stack;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
|
||||||
|
if(global_openflags.s){
|
||||||
|
printk(KERN_INFO "ubd: Synchronous mode\n");
|
||||||
|
/* Letting ubd=sync be like using ubd#s= instead of ubd#= is
|
||||||
|
* enough. So use anyway the io thread. */
|
||||||
|
}
|
||||||
|
stack = alloc_stack(0, 0);
|
||||||
|
io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
|
||||||
|
&thread_fd);
|
||||||
|
if(io_pid < 0){
|
||||||
|
printk(KERN_ERR
|
||||||
|
"ubd : Failed to start I/O thread (errno = %d) - "
|
||||||
|
"falling back to synchronous I/O\n", -io_pid);
|
||||||
|
io_pid = -1;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
|
||||||
|
SA_INTERRUPT, "ubd", ubd_dev);
|
||||||
|
if(err != 0)
|
||||||
|
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
|
||||||
|
return(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_initcall(ubd_driver_init);
|
||||||
|
|
||||||
static int ubd_open(struct inode *inode, struct file *filp)
|
static int ubd_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||||
@ -939,55 +923,105 @@ static int ubd_release(struct inode * inode, struct file * file)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap)
|
static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
|
||||||
|
__u64 *cow_offset, unsigned long *bitmap,
|
||||||
|
__u64 bitmap_offset, unsigned long *bitmap_words,
|
||||||
|
__u64 bitmap_len)
|
||||||
{
|
{
|
||||||
__u64 sector = req->offset / req->sectorsize;
|
__u64 sector = io_offset >> 9;
|
||||||
int i;
|
int i, update_bitmap = 0;
|
||||||
|
|
||||||
for(i = 0; i < req->length / req->sectorsize; i++){
|
for(i = 0; i < length >> 9; i++){
|
||||||
if(ubd_test_bit(sector + i, bitmap))
|
if(cow_mask != NULL)
|
||||||
continue;
|
ubd_set_bit(i, (unsigned char *) cow_mask);
|
||||||
|
if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
|
||||||
|
continue;
|
||||||
|
|
||||||
if(req->bitmap_start == -1)
|
update_bitmap = 1;
|
||||||
req->bitmap_start = sector + i;
|
ubd_set_bit(sector + i, (unsigned char *) bitmap);
|
||||||
req->bitmap_end = sector + i + 1;
|
}
|
||||||
|
|
||||||
ubd_set_bit(sector + i, bitmap);
|
if(!update_bitmap)
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
*cow_offset = sector / (sizeof(unsigned long) * 8);
|
||||||
|
|
||||||
|
/* This takes care of the case where we're exactly at the end of the
|
||||||
|
* device, and *cow_offset + 1 is off the end. So, just back it up
|
||||||
|
* by one word. Thanks to Lynn Kerby for the fix and James McMechan
|
||||||
|
* for the original diagnosis.
|
||||||
|
*/
|
||||||
|
if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
|
||||||
|
sizeof(unsigned long) - 1))
|
||||||
|
(*cow_offset)--;
|
||||||
|
|
||||||
|
bitmap_words[0] = bitmap[*cow_offset];
|
||||||
|
bitmap_words[1] = bitmap[*cow_offset + 1];
|
||||||
|
|
||||||
|
*cow_offset *= sizeof(unsigned long);
|
||||||
|
*cow_offset += bitmap_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
|
||||||
|
__u64 bitmap_offset, __u64 bitmap_len)
|
||||||
|
{
|
||||||
|
__u64 sector = req->offset >> 9;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(req->length > (sizeof(req->sector_mask) * 8) << 9)
|
||||||
|
panic("Operation too long");
|
||||||
|
|
||||||
|
if(req->op == UBD_READ) {
|
||||||
|
for(i = 0; i < req->length >> 9; i++){
|
||||||
|
if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
|
||||||
|
ubd_set_bit(i, (unsigned char *)
|
||||||
|
&req->sector_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else cowify_bitmap(req->offset, req->length, &req->sector_mask,
|
||||||
|
&req->cow_offset, bitmap, bitmap_offset,
|
||||||
|
req->bitmap_words, bitmap_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called with ubd_io_lock held */
|
/* Called with ubd_io_lock held */
|
||||||
static int prepare_request(struct request *req, struct io_thread_req *io_req,
|
static int prepare_request(struct request *req, struct io_thread_req *io_req)
|
||||||
unsigned long long offset, int page_offset,
|
|
||||||
int len, struct page *page)
|
|
||||||
{
|
{
|
||||||
struct gendisk *disk = req->rq_disk;
|
struct gendisk *disk = req->rq_disk;
|
||||||
struct ubd *dev = disk->private_data;
|
struct ubd *dev = disk->private_data;
|
||||||
|
__u64 offset;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(req->rq_status == RQ_INACTIVE) return(1);
|
||||||
|
|
||||||
/* This should be impossible now */
|
/* This should be impossible now */
|
||||||
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
|
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
|
||||||
printk("Write attempted on readonly ubd device %s\n",
|
printk("Write attempted on readonly ubd device %s\n",
|
||||||
disk->disk_name);
|
disk->disk_name);
|
||||||
ubd_end_request(req, 0, 0);
|
end_request(req, 0);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offset = ((__u64) req->sector) << 9;
|
||||||
|
len = req->current_nr_sectors << 9;
|
||||||
|
|
||||||
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
|
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
|
||||||
io_req->fds[1] = dev->fd;
|
io_req->fds[1] = dev->fd;
|
||||||
|
io_req->cow_offset = -1;
|
||||||
io_req->offset = offset;
|
io_req->offset = offset;
|
||||||
io_req->length = len;
|
io_req->length = len;
|
||||||
io_req->error = 0;
|
io_req->error = 0;
|
||||||
io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE;
|
io_req->sector_mask = 0;
|
||||||
|
|
||||||
|
io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
|
||||||
io_req->offsets[0] = 0;
|
io_req->offsets[0] = 0;
|
||||||
io_req->offsets[1] = dev->cow.data_offset;
|
io_req->offsets[1] = dev->cow.data_offset;
|
||||||
io_req->buffer = page_address(page) + page_offset;
|
io_req->buffer = req->buffer;
|
||||||
io_req->sectorsize = 1 << 9;
|
io_req->sectorsize = 1 << 9;
|
||||||
io_req->bitmap_offset = dev->cow.bitmap_offset;
|
|
||||||
io_req->bitmap_start = -1;
|
|
||||||
io_req->bitmap_end = -1;
|
|
||||||
|
|
||||||
if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE))
|
if(dev->cow.file != NULL)
|
||||||
cowify_bitmap(io_req, dev->cow.bitmap);
|
cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
|
||||||
|
dev->cow.bitmap_len);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -996,36 +1030,30 @@ static void do_ubd_request(request_queue_t *q)
|
|||||||
{
|
{
|
||||||
struct io_thread_req io_req;
|
struct io_thread_req io_req;
|
||||||
struct request *req;
|
struct request *req;
|
||||||
__u64 sector;
|
int err, n;
|
||||||
int err;
|
|
||||||
|
|
||||||
if(in_ubd)
|
if(thread_fd == -1){
|
||||||
return;
|
while((req = elv_next_request(q)) != NULL){
|
||||||
in_ubd = 1;
|
err = prepare_request(req, &io_req);
|
||||||
while((req = elv_next_request(q)) != NULL){
|
if(!err){
|
||||||
struct gendisk *disk = req->rq_disk;
|
do_io(&io_req);
|
||||||
struct ubd *dev = disk->private_data;
|
__ubd_finish(req, io_req.error);
|
||||||
int n, i;
|
}
|
||||||
|
}
|
||||||
blkdev_dequeue_request(req);
|
}
|
||||||
|
else {
|
||||||
sector = req->sector;
|
if(do_ubd || (req = elv_next_request(q)) == NULL)
|
||||||
n = blk_rq_map_sg(q, req, dev->sg);
|
return;
|
||||||
|
err = prepare_request(req, &io_req);
|
||||||
for(i = 0; i < n; i++){
|
if(!err){
|
||||||
struct scatterlist *sg = &dev->sg[i];
|
do_ubd = ubd_handler;
|
||||||
|
n = os_write_file(thread_fd, (char *) &io_req,
|
||||||
err = prepare_request(req, &io_req, sector << 9,
|
sizeof(io_req));
|
||||||
sg->offset, sg->length,
|
if(n != sizeof(io_req))
|
||||||
sg->page);
|
printk("write to io thread failed, "
|
||||||
if(err)
|
"errno = %d\n", -n);
|
||||||
continue;
|
|
||||||
|
|
||||||
sector += sg->length >> 9;
|
|
||||||
do_io(&io_req, req, dev->cow.bitmap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in_ubd = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ubd_ioctl(struct inode * inode, struct file * file,
|
static int ubd_ioctl(struct inode * inode, struct file * file,
|
||||||
@ -1241,95 +1269,131 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
|
|||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap)
|
static int update_bitmap(struct io_thread_req *req)
|
||||||
{
|
{
|
||||||
struct ubd_aio *aio;
|
int n;
|
||||||
struct bitmap_io *bitmap_io = NULL;
|
|
||||||
char *buf;
|
|
||||||
void *bitmap_buf = NULL;
|
|
||||||
unsigned long len, sector;
|
|
||||||
int nsectors, start, end, bit, err;
|
|
||||||
__u64 off;
|
|
||||||
|
|
||||||
if(req->bitmap_start != -1){
|
if(req->cow_offset == -1)
|
||||||
/* Round up to the nearest word */
|
return(0);
|
||||||
int round = sizeof(unsigned long);
|
|
||||||
len = (req->bitmap_end - req->bitmap_start +
|
|
||||||
round * 8 - 1) / (round * 8);
|
|
||||||
len *= round;
|
|
||||||
|
|
||||||
off = req->bitmap_start / (8 * round);
|
n = os_seek_file(req->fds[1], req->cow_offset);
|
||||||
off *= round;
|
if(n < 0){
|
||||||
|
printk("do_io - bitmap lseek failed : err = %d\n", -n);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL);
|
n = os_write_file(req->fds[1], &req->bitmap_words,
|
||||||
if(bitmap_io == NULL){
|
sizeof(req->bitmap_words));
|
||||||
printk("Failed to kmalloc bitmap IO\n");
|
if(n != sizeof(req->bitmap_words)){
|
||||||
req->error = 1;
|
printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
|
||||||
return;
|
req->fds[1]);
|
||||||
}
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
bitmap_buf = kmalloc(len, GFP_KERNEL);
|
return(0);
|
||||||
if(bitmap_buf == NULL){
|
|
||||||
printk("do_io : kmalloc of bitmap chunk "
|
|
||||||
"failed\n");
|
|
||||||
kfree(bitmap_io);
|
|
||||||
req->error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len);
|
|
||||||
|
|
||||||
*bitmap_io = ((struct bitmap_io)
|
|
||||||
{ .count = ATOMIC_INIT(0),
|
|
||||||
.aio = INIT_AIO(AIO_WRITE, req->fds[1],
|
|
||||||
bitmap_buf, len,
|
|
||||||
req->bitmap_offset + off,
|
|
||||||
ubd_reply_fd) } );
|
|
||||||
}
|
|
||||||
|
|
||||||
nsectors = req->length / req->sectorsize;
|
|
||||||
start = 0;
|
|
||||||
end = nsectors;
|
|
||||||
bit = 0;
|
|
||||||
do {
|
|
||||||
if(bitmap != NULL){
|
|
||||||
sector = req->offset / req->sectorsize;
|
|
||||||
bit = ubd_test_bit(sector + start, bitmap);
|
|
||||||
end = start;
|
|
||||||
while((end < nsectors) &&
|
|
||||||
(ubd_test_bit(sector + end, bitmap) == bit))
|
|
||||||
end++;
|
|
||||||
}
|
|
||||||
|
|
||||||
off = req->offsets[bit] + req->offset +
|
|
||||||
start * req->sectorsize;
|
|
||||||
len = (end - start) * req->sectorsize;
|
|
||||||
buf = &req->buffer[start * req->sectorsize];
|
|
||||||
|
|
||||||
aio = kmalloc(sizeof(*aio), GFP_KERNEL);
|
|
||||||
if(aio == NULL){
|
|
||||||
req->error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aio = ((struct ubd_aio)
|
|
||||||
{ .aio = INIT_AIO(req->op, req->fds[bit], buf,
|
|
||||||
len, off, ubd_reply_fd),
|
|
||||||
.len = len,
|
|
||||||
.req = r,
|
|
||||||
.bitmap = bitmap_io,
|
|
||||||
.bitmap_buf = bitmap_buf });
|
|
||||||
|
|
||||||
if(aio->bitmap != NULL)
|
|
||||||
atomic_inc(&aio->bitmap->count);
|
|
||||||
|
|
||||||
err = submit_aio(&aio->aio);
|
|
||||||
if(err){
|
|
||||||
printk("do_io - submit_aio failed, "
|
|
||||||
"err = %d\n", err);
|
|
||||||
req->error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = end;
|
|
||||||
} while(start < nsectors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_io(struct io_thread_req *req)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
unsigned long len;
|
||||||
|
int n, nsectors, start, end, bit;
|
||||||
|
int err;
|
||||||
|
__u64 off;
|
||||||
|
|
||||||
|
nsectors = req->length / req->sectorsize;
|
||||||
|
start = 0;
|
||||||
|
do {
|
||||||
|
bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
|
||||||
|
end = start;
|
||||||
|
while((end < nsectors) &&
|
||||||
|
(ubd_test_bit(end, (unsigned char *)
|
||||||
|
&req->sector_mask) == bit))
|
||||||
|
end++;
|
||||||
|
|
||||||
|
off = req->offset + req->offsets[bit] +
|
||||||
|
start * req->sectorsize;
|
||||||
|
len = (end - start) * req->sectorsize;
|
||||||
|
buf = &req->buffer[start * req->sectorsize];
|
||||||
|
|
||||||
|
err = os_seek_file(req->fds[bit], off);
|
||||||
|
if(err < 0){
|
||||||
|
printk("do_io - lseek failed : err = %d\n", -err);
|
||||||
|
req->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(req->op == UBD_READ){
|
||||||
|
n = 0;
|
||||||
|
do {
|
||||||
|
buf = &buf[n];
|
||||||
|
len -= n;
|
||||||
|
n = os_read_file(req->fds[bit], buf, len);
|
||||||
|
if (n < 0) {
|
||||||
|
printk("do_io - read failed, err = %d "
|
||||||
|
"fd = %d\n", -n, req->fds[bit]);
|
||||||
|
req->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while((n < len) && (n != 0));
|
||||||
|
if (n < len) memset(&buf[n], 0, len - n);
|
||||||
|
} else {
|
||||||
|
n = os_write_file(req->fds[bit], buf, len);
|
||||||
|
if(n != len){
|
||||||
|
printk("do_io - write failed err = %d "
|
||||||
|
"fd = %d\n", -n, req->fds[bit]);
|
||||||
|
req->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start = end;
|
||||||
|
} while(start < nsectors);
|
||||||
|
|
||||||
|
req->error = update_bitmap(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Changed in start_io_thread, which is serialized by being called only
|
||||||
|
* from ubd_init, which is an initcall.
|
||||||
|
*/
|
||||||
|
int kernel_fd = -1;
|
||||||
|
|
||||||
|
/* Only changed by the io thread */
|
||||||
|
int io_count = 0;
|
||||||
|
|
||||||
|
int io_thread(void *arg)
|
||||||
|
{
|
||||||
|
struct io_thread_req req;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ignore_sigwinch_sig();
|
||||||
|
while(1){
|
||||||
|
n = os_read_file(kernel_fd, &req, sizeof(req));
|
||||||
|
if(n != sizeof(req)){
|
||||||
|
if(n < 0)
|
||||||
|
printk("io_thread - read failed, fd = %d, "
|
||||||
|
"err = %d\n", kernel_fd, -n);
|
||||||
|
else {
|
||||||
|
printk("io_thread - short read, fd = %d, "
|
||||||
|
"length = %d\n", kernel_fd, n);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
io_count++;
|
||||||
|
do_io(&req);
|
||||||
|
n = os_write_file(kernel_fd, &req, sizeof(req));
|
||||||
|
if(n != sizeof(req))
|
||||||
|
printk("io_thread - write failed, fd = %d, err = %d\n",
|
||||||
|
kernel_fd, -n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||||
|
* Emacs will notice this stuff at the end of the file and automatically
|
||||||
|
* adjust the settings for this buffer only. This must remain at the end
|
||||||
|
* of the file.
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Local variables:
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
75
arch/um/drivers/ubd_user.c
Normal file
75
arch/um/drivers/ubd_user.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
||||||
|
* Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
|
||||||
|
* Licensed under the GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "asm/types.h"
|
||||||
|
#include "user_util.h"
|
||||||
|
#include "kern_util.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "ubd_user.h"
|
||||||
|
#include "os.h"
|
||||||
|
#include "cow.h"
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
void ignore_sigwinch_sig(void)
|
||||||
|
{
|
||||||
|
signal(SIGWINCH, SIG_IGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
int start_io_thread(unsigned long sp, int *fd_out)
|
||||||
|
{
|
||||||
|
int pid, fds[2], err;
|
||||||
|
|
||||||
|
err = os_pipe(fds, 1, 1);
|
||||||
|
if(err < 0){
|
||||||
|
printk("start_io_thread - os_pipe failed, err = %d\n", -err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_fd = fds[0];
|
||||||
|
*fd_out = fds[1];
|
||||||
|
|
||||||
|
pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
|
||||||
|
NULL);
|
||||||
|
if(pid < 0){
|
||||||
|
printk("start_io_thread - clone failed : errno = %d\n", errno);
|
||||||
|
err = -errno;
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pid);
|
||||||
|
|
||||||
|
out_close:
|
||||||
|
os_close_file(fds[0]);
|
||||||
|
os_close_file(fds[1]);
|
||||||
|
kernel_fd = -1;
|
||||||
|
*fd_out = -1;
|
||||||
|
out:
|
||||||
|
return(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||||
|
* Emacs will notice this stuff at the end of the file and automatically
|
||||||
|
* adjust the settings for this buffer only. This must remain at the end
|
||||||
|
* of the file.
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Local variables:
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
@ -14,27 +14,15 @@ struct aio_thread_reply {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct aio_context {
|
struct aio_context {
|
||||||
enum aio_type type;
|
|
||||||
int fd;
|
|
||||||
void *data;
|
|
||||||
int len;
|
|
||||||
unsigned long long offset;
|
|
||||||
int reply_fd;
|
int reply_fd;
|
||||||
struct aio_context *next;
|
struct aio_context *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \
|
|
||||||
aio_reply_fd) \
|
|
||||||
{ .type = aio_type, \
|
|
||||||
.fd = aio_fd, \
|
|
||||||
.data = aio_data, \
|
|
||||||
.len = aio_len, \
|
|
||||||
.offset = aio_offset, \
|
|
||||||
.reply_fd = aio_reply_fd }
|
|
||||||
|
|
||||||
#define INIT_AIO_CONTEXT { .reply_fd = -1, \
|
#define INIT_AIO_CONTEXT { .reply_fd = -1, \
|
||||||
.next = NULL }
|
.next = NULL }
|
||||||
|
|
||||||
extern int submit_aio(struct aio_context *aio);
|
extern int submit_aio(enum aio_type type, int fd, char *buf, int len,
|
||||||
|
unsigned long long offset, int reply_fd,
|
||||||
|
struct aio_context *aio);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#ifndef __OS_H__
|
#ifndef __OS_H__
|
||||||
#define __OS_H__
|
#define __OS_H__
|
||||||
|
|
||||||
|
#include "uml-config.h"
|
||||||
#include "asm/types.h"
|
#include "asm/types.h"
|
||||||
#include "../os/include/file.h"
|
#include "../os/include/file.h"
|
||||||
|
|
||||||
@ -159,7 +160,11 @@ extern int can_do_skas(void);
|
|||||||
|
|
||||||
/* Make sure they are clear when running in TT mode. Required by
|
/* Make sure they are clear when running in TT mode. Required by
|
||||||
* SEGV_MAYBE_FIXABLE */
|
* SEGV_MAYBE_FIXABLE */
|
||||||
|
#ifdef UML_CONFIG_MODE_SKAS
|
||||||
#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
|
#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
|
||||||
|
#else
|
||||||
|
#define clear_can_do_skas() do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* mem.c */
|
/* mem.c */
|
||||||
extern int create_mem_file(unsigned long len);
|
extern int create_mem_file(unsigned long len);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -17,31 +16,18 @@
|
|||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "mode.h"
|
#include "mode.h"
|
||||||
|
|
||||||
|
struct aio_thread_req {
|
||||||
|
enum aio_type type;
|
||||||
|
int io_fd;
|
||||||
|
unsigned long long offset;
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
struct aio_context *aio;
|
||||||
|
};
|
||||||
|
|
||||||
static int aio_req_fd_r = -1;
|
static int aio_req_fd_r = -1;
|
||||||
static int aio_req_fd_w = -1;
|
static int aio_req_fd_w = -1;
|
||||||
|
|
||||||
static int update_aio(struct aio_context *aio, int res)
|
|
||||||
{
|
|
||||||
if(res < 0)
|
|
||||||
aio->len = res;
|
|
||||||
else if((res == 0) && (aio->type == AIO_READ)){
|
|
||||||
/* This is the EOF case - we have hit the end of the file
|
|
||||||
* and it ends in a partial block, so we fill the end of
|
|
||||||
* the block with zeros and claim success.
|
|
||||||
*/
|
|
||||||
memset(aio->data, 0, aio->len);
|
|
||||||
aio->len = 0;
|
|
||||||
}
|
|
||||||
else if(res > 0){
|
|
||||||
aio->len -= res;
|
|
||||||
aio->data += res;
|
|
||||||
aio->offset += res;
|
|
||||||
return aio->len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_AIO_ABI)
|
#if defined(HAVE_AIO_ABI)
|
||||||
#include <linux/aio_abi.h>
|
#include <linux/aio_abi.h>
|
||||||
|
|
||||||
@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
|
|||||||
* that it now backs the mmapped area.
|
* that it now backs the mmapped area.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int do_aio(aio_context_t ctx, struct aio_context *aio)
|
static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
|
||||||
|
int len, unsigned long long offset, struct aio_context *aio)
|
||||||
{
|
{
|
||||||
struct iocb iocb, *iocbp = &iocb;
|
struct iocb iocb, *iocbp = &iocb;
|
||||||
char c;
|
char c;
|
||||||
@ -88,39 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio)
|
|||||||
|
|
||||||
iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
|
iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
|
||||||
.aio_reqprio = 0,
|
.aio_reqprio = 0,
|
||||||
.aio_fildes = aio->fd,
|
.aio_fildes = fd,
|
||||||
.aio_buf = (unsigned long) aio->data,
|
.aio_buf = (unsigned long) buf,
|
||||||
.aio_nbytes = aio->len,
|
.aio_nbytes = len,
|
||||||
.aio_offset = aio->offset,
|
.aio_offset = offset,
|
||||||
.aio_reserved1 = 0,
|
.aio_reserved1 = 0,
|
||||||
.aio_reserved2 = 0,
|
.aio_reserved2 = 0,
|
||||||
.aio_reserved3 = 0 });
|
.aio_reserved3 = 0 });
|
||||||
|
|
||||||
switch(aio->type){
|
switch(type){
|
||||||
case AIO_READ:
|
case AIO_READ:
|
||||||
iocb.aio_lio_opcode = IOCB_CMD_PREAD;
|
iocb.aio_lio_opcode = IOCB_CMD_PREAD;
|
||||||
|
err = io_submit(ctx, 1, &iocbp);
|
||||||
break;
|
break;
|
||||||
case AIO_WRITE:
|
case AIO_WRITE:
|
||||||
iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
|
iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
|
||||||
|
err = io_submit(ctx, 1, &iocbp);
|
||||||
break;
|
break;
|
||||||
case AIO_MMAP:
|
case AIO_MMAP:
|
||||||
iocb.aio_lio_opcode = IOCB_CMD_PREAD;
|
iocb.aio_lio_opcode = IOCB_CMD_PREAD;
|
||||||
iocb.aio_buf = (unsigned long) &c;
|
iocb.aio_buf = (unsigned long) &c;
|
||||||
iocb.aio_nbytes = sizeof(c);
|
iocb.aio_nbytes = sizeof(c);
|
||||||
|
err = io_submit(ctx, 1, &iocbp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("Bogus op in do_aio - %d\n", aio->type);
|
printk("Bogus op in do_aio - %d\n", type);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = io_submit(ctx, 1, &iocbp);
|
|
||||||
if(err > 0)
|
if(err > 0)
|
||||||
err = 0;
|
err = 0;
|
||||||
else
|
else
|
||||||
err = -errno;
|
err = -errno;
|
||||||
|
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +117,8 @@ static aio_context_t ctx = 0;
|
|||||||
static int aio_thread(void *arg)
|
static int aio_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct aio_thread_reply reply;
|
struct aio_thread_reply reply;
|
||||||
struct aio_context *aio;
|
|
||||||
struct io_event event;
|
struct io_event event;
|
||||||
int err, n;
|
int err, n, reply_fd;
|
||||||
|
|
||||||
signal(SIGWINCH, SIG_IGN);
|
signal(SIGWINCH, SIG_IGN);
|
||||||
|
|
||||||
@ -144,22 +131,14 @@ static int aio_thread(void *arg)
|
|||||||
"errno = %d\n", errno);
|
"errno = %d\n", errno);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* This is safe as we've just a pointer here. */
|
|
||||||
aio = (struct aio_context *) (long) event.data;
|
|
||||||
if(update_aio(aio, event.res)){
|
|
||||||
do_aio(ctx, aio);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply = ((struct aio_thread_reply)
|
reply = ((struct aio_thread_reply)
|
||||||
{ .data = aio,
|
{ .data = (void *) (long) event.data,
|
||||||
.err = aio->len });
|
.err = event.res });
|
||||||
err = os_write_file(aio->reply_fd, &reply,
|
reply_fd = ((struct aio_context *) reply.data)->reply_fd;
|
||||||
sizeof(reply));
|
err = os_write_file(reply_fd, &reply, sizeof(reply));
|
||||||
if(err != sizeof(reply))
|
if(err != sizeof(reply))
|
||||||
printk("aio_thread - write failed, "
|
printk("aio_thread - write failed, fd = %d, "
|
||||||
"fd = %d, err = %d\n", aio->reply_fd,
|
"err = %d\n", aio_req_fd_r, -err);
|
||||||
-err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -167,35 +146,35 @@ static int aio_thread(void *arg)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int do_not_aio(struct aio_context *aio)
|
static int do_not_aio(struct aio_thread_req *req)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
switch(aio->type){
|
switch(req->type){
|
||||||
case AIO_READ:
|
case AIO_READ:
|
||||||
err = os_seek_file(aio->fd, aio->offset);
|
err = os_seek_file(req->io_fd, req->offset);
|
||||||
if(err)
|
if(err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = os_read_file(aio->fd, aio->data, aio->len);
|
err = os_read_file(req->io_fd, req->buf, req->len);
|
||||||
break;
|
break;
|
||||||
case AIO_WRITE:
|
case AIO_WRITE:
|
||||||
err = os_seek_file(aio->fd, aio->offset);
|
err = os_seek_file(req->io_fd, req->offset);
|
||||||
if(err)
|
if(err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = os_write_file(aio->fd, aio->data, aio->len);
|
err = os_write_file(req->io_fd, req->buf, req->len);
|
||||||
break;
|
break;
|
||||||
case AIO_MMAP:
|
case AIO_MMAP:
|
||||||
err = os_seek_file(aio->fd, aio->offset);
|
err = os_seek_file(req->io_fd, req->offset);
|
||||||
if(err)
|
if(err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = os_read_file(aio->fd, &c, sizeof(c));
|
err = os_read_file(req->io_fd, &c, sizeof(c));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("do_not_aio - bad request type : %d\n", aio->type);
|
printk("do_not_aio - bad request type : %d\n", req->type);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -206,14 +185,14 @@ static int do_not_aio(struct aio_context *aio)
|
|||||||
|
|
||||||
static int not_aio_thread(void *arg)
|
static int not_aio_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct aio_context *aio;
|
struct aio_thread_req req;
|
||||||
struct aio_thread_reply reply;
|
struct aio_thread_reply reply;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
signal(SIGWINCH, SIG_IGN);
|
signal(SIGWINCH, SIG_IGN);
|
||||||
while(1){
|
while(1){
|
||||||
err = os_read_file(aio_req_fd_r, &aio, sizeof(aio));
|
err = os_read_file(aio_req_fd_r, &req, sizeof(req));
|
||||||
if(err != sizeof(aio)){
|
if(err != sizeof(req)){
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
printk("not_aio_thread - read failed, "
|
printk("not_aio_thread - read failed, "
|
||||||
"fd = %d, err = %d\n", aio_req_fd_r,
|
"fd = %d, err = %d\n", aio_req_fd_r,
|
||||||
@ -224,34 +203,17 @@ static int not_aio_thread(void *arg)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
again:
|
err = do_not_aio(&req);
|
||||||
err = do_not_aio(aio);
|
reply = ((struct aio_thread_reply) { .data = req.aio,
|
||||||
|
.err = err });
|
||||||
if(update_aio(aio, err))
|
err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
|
||||||
goto again;
|
|
||||||
|
|
||||||
reply = ((struct aio_thread_reply) { .data = aio,
|
|
||||||
.err = aio->len });
|
|
||||||
err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
|
|
||||||
if(err != sizeof(reply))
|
if(err != sizeof(reply))
|
||||||
printk("not_aio_thread - write failed, fd = %d, "
|
printk("not_aio_thread - write failed, fd = %d, "
|
||||||
"err = %d\n", aio_req_fd_r, -err);
|
"err = %d\n", aio_req_fd_r, -err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int submit_aio_24(struct aio_context *aio)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = os_write_file(aio_req_fd_w, &aio, sizeof(aio));
|
|
||||||
if(err == sizeof(aio))
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int aio_pid = -1;
|
static int aio_pid = -1;
|
||||||
static int (*submit_proc)(struct aio_context *aio);
|
|
||||||
|
|
||||||
static int init_aio_24(void)
|
static int init_aio_24(void)
|
||||||
{
|
{
|
||||||
@ -283,33 +245,11 @@ static int init_aio_24(void)
|
|||||||
#endif
|
#endif
|
||||||
printk("2.6 host AIO support not used - falling back to I/O "
|
printk("2.6 host AIO support not used - falling back to I/O "
|
||||||
"thread\n");
|
"thread\n");
|
||||||
|
|
||||||
submit_proc = submit_aio_24;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_AIO_ABI
|
#ifdef HAVE_AIO_ABI
|
||||||
#define DEFAULT_24_AIO 0
|
#define DEFAULT_24_AIO 0
|
||||||
static int submit_aio_26(struct aio_context *aio)
|
|
||||||
{
|
|
||||||
struct aio_thread_reply reply;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = do_aio(ctx, aio);
|
|
||||||
if(err){
|
|
||||||
reply = ((struct aio_thread_reply) { .data = aio,
|
|
||||||
.err = err });
|
|
||||||
err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
|
|
||||||
if(err != sizeof(reply))
|
|
||||||
printk("submit_aio_26 - write failed, "
|
|
||||||
"fd = %d, err = %d\n", aio->reply_fd, -err);
|
|
||||||
else err = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_aio_26(void)
|
static int init_aio_26(void)
|
||||||
{
|
{
|
||||||
unsigned long stack;
|
unsigned long stack;
|
||||||
@ -330,22 +270,39 @@ static int init_aio_26(void)
|
|||||||
aio_pid = err;
|
aio_pid = err;
|
||||||
|
|
||||||
printk("Using 2.6 host AIO\n");
|
printk("Using 2.6 host AIO\n");
|
||||||
|
|
||||||
submit_proc = submit_aio_26;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
|
||||||
|
unsigned long long offset, struct aio_context *aio)
|
||||||
|
{
|
||||||
|
struct aio_thread_reply reply;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
|
||||||
|
if(err){
|
||||||
|
reply = ((struct aio_thread_reply) { .data = aio,
|
||||||
|
.err = err });
|
||||||
|
err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
|
||||||
|
if(err != sizeof(reply))
|
||||||
|
printk("submit_aio_26 - write failed, "
|
||||||
|
"fd = %d, err = %d\n", aio->reply_fd, -err);
|
||||||
|
else err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_24_AIO 1
|
#define DEFAULT_24_AIO 1
|
||||||
static int submit_aio_26(struct aio_context *aio)
|
static int init_aio_26(void)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_aio_26(void)
|
static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
|
||||||
|
unsigned long long offset, struct aio_context *aio)
|
||||||
{
|
{
|
||||||
submit_proc = submit_aio_26;
|
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -412,7 +369,33 @@ static void exit_aio(void)
|
|||||||
|
|
||||||
__uml_exitcall(exit_aio);
|
__uml_exitcall(exit_aio);
|
||||||
|
|
||||||
int submit_aio(struct aio_context *aio)
|
static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
|
||||||
|
unsigned long long offset, struct aio_context *aio)
|
||||||
{
|
{
|
||||||
return (*submit_proc)(aio);
|
struct aio_thread_req req = { .type = type,
|
||||||
|
.io_fd = io_fd,
|
||||||
|
.offset = offset,
|
||||||
|
.buf = buf,
|
||||||
|
.len = len,
|
||||||
|
.aio = aio,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = os_write_file(aio_req_fd_w, &req, sizeof(req));
|
||||||
|
if(err == sizeof(req))
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
|
||||||
|
unsigned long long offset, int reply_fd,
|
||||||
|
struct aio_context *aio)
|
||||||
|
{
|
||||||
|
aio->reply_fd = reply_fd;
|
||||||
|
if(aio_24)
|
||||||
|
return submit_aio_24(type, io_fd, buf, len, offset, aio);
|
||||||
|
else {
|
||||||
|
return submit_aio_26(type, io_fd, buf, len, offset, aio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,11 +143,22 @@ static int __init skas0_cmd_param(char *str, int* add)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The two __uml_setup would conflict, without this stupid alias. */
|
||||||
|
|
||||||
|
static int __init mode_skas0_cmd_param(char *str, int* add)
|
||||||
|
__attribute__((alias("skas0_cmd_param")));
|
||||||
|
|
||||||
__uml_setup("skas0", skas0_cmd_param,
|
__uml_setup("skas0", skas0_cmd_param,
|
||||||
"skas0\n"
|
"skas0\n"
|
||||||
" Disables SKAS3 usage, so that SKAS0 is used, unless \n"
|
" Disables SKAS3 usage, so that SKAS0 is used, unless \n"
|
||||||
" you specify mode=tt.\n\n");
|
" you specify mode=tt.\n\n");
|
||||||
|
|
||||||
|
__uml_setup("mode=skas0", mode_skas0_cmd_param,
|
||||||
|
"mode=skas0\n"
|
||||||
|
" Disables SKAS3 usage, so that SKAS0 is used, unless you \n"
|
||||||
|
" specify mode=tt. Note that this was recently added - on \n"
|
||||||
|
" older kernels you must use simply \"skas0\".\n\n");
|
||||||
|
|
||||||
static int force_sysemu_disabled = 0;
|
static int force_sysemu_disabled = 0;
|
||||||
|
|
||||||
static int __init nosysemu_cmd_param(char *str, int* add)
|
static int __init nosysemu_cmd_param(char *str, int* add)
|
||||||
|
@ -7,8 +7,8 @@ USER_SINGLE_OBJS := \
|
|||||||
USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
|
USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
|
||||||
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
|
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
|
||||||
|
|
||||||
$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
|
$(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \
|
||||||
$(CFLAGS_$(notdir $@))
|
c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
|
||||||
$(USER_OBJS): cmd_checksrc =
|
$(USER_OBJS): cmd_checksrc =
|
||||||
$(USER_OBJS): quiet_cmd_checksrc =
|
$(USER_OBJS): quiet_cmd_checksrc =
|
||||||
$(USER_OBJS): cmd_force_checksrc =
|
$(USER_OBJS): cmd_force_checksrc =
|
||||||
|
@ -10,6 +10,22 @@
|
|||||||
#include "uml-config.h"
|
#include "uml-config.h"
|
||||||
#include "sysdep/sigcontext.h"
|
#include "sysdep/sigcontext.h"
|
||||||
#include "sysdep/faultinfo.h"
|
#include "sysdep/faultinfo.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
|
||||||
|
* in the libc headers anywhere.
|
||||||
|
*/
|
||||||
|
struct rt_sigframe
|
||||||
|
{
|
||||||
|
char *pretcode;
|
||||||
|
struct ucontext uc;
|
||||||
|
struct siginfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Copied here from <linux/kernel.h> - we're userspace. */
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
||||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||||
stub_segv_handler(int sig)
|
stub_segv_handler(int sig)
|
||||||
@ -17,16 +33,19 @@ stub_segv_handler(int sig)
|
|||||||
struct ucontext *uc;
|
struct ucontext *uc;
|
||||||
|
|
||||||
__asm__("movq %%rdx, %0" : "=g" (uc) :);
|
__asm__("movq %%rdx, %0" : "=g" (uc) :);
|
||||||
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
|
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
|
||||||
&uc->uc_mcontext);
|
&uc->uc_mcontext);
|
||||||
|
|
||||||
__asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid));
|
__asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid));
|
||||||
__asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;"
|
__asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;"
|
||||||
"syscall": : "g" (__NR_kill), "g" (SIGUSR1));
|
"syscall": : "g" (__NR_kill), "g" (SIGUSR1) :
|
||||||
/* Two popqs to restore the stack to the state just before entering
|
"%rdi", "%rax", "%rsi");
|
||||||
* the handler, one pops the return address, the other pops the frame
|
/* sys_sigreturn expects that the stack pointer will be 8 bytes into
|
||||||
* pointer.
|
* the signal frame. So, we use the ucontext pointer, which we know
|
||||||
|
* already, to get the signal frame pointer, and add 8 to that.
|
||||||
*/
|
*/
|
||||||
__asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g"
|
__asm__("movq %0, %%rsp": :
|
||||||
(__NR_rt_sigreturn));
|
"g" ((unsigned long) container_of(uc, struct rt_sigframe,
|
||||||
|
uc) + 8));
|
||||||
|
__asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn));
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
|
|||||||
rsp = (unsigned long) ka->sa.sa_restorer;
|
rsp = (unsigned long) ka->sa.sa_restorer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void __user *)((rsp - frame_size) & -8UL);
|
rsp -= frame_size;
|
||||||
|
/* Align the stack pointer according to the i386 ABI,
|
||||||
|
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
|
||||||
|
rsp = ((rsp + 4) & -16ul) - 4;
|
||||||
|
return (void __user *) rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
||||||
|
@ -87,6 +87,10 @@ void __init setup_per_cpu_areas(void)
|
|||||||
int i;
|
int i;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
prefill_possible_map();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Copy section for each CPU (we discard the original) */
|
/* Copy section for each CPU (we discard the original) */
|
||||||
size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
|
size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
|
||||||
#ifdef CONFIG_MODULES
|
#ifdef CONFIG_MODULES
|
||||||
|
@ -892,7 +892,7 @@ static __init void disable_smp(void)
|
|||||||
* those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range.
|
* those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range.
|
||||||
* - Ashok Raj
|
* - Ashok Raj
|
||||||
*/
|
*/
|
||||||
static void prefill_possible_map(void)
|
__init void prefill_possible_map(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < NR_CPUS; i++)
|
for (i = 0; i < NR_CPUS; i++)
|
||||||
@ -967,10 +967,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
current_cpu_data = boot_cpu_data;
|
current_cpu_data = boot_cpu_data;
|
||||||
current_thread_info()->cpu = 0; /* needed? */
|
current_thread_info()->cpu = 0; /* needed? */
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
prefill_possible_map();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (smp_sanity_check(max_cpus) < 0) {
|
if (smp_sanity_check(max_cpus) < 0) {
|
||||||
printk(KERN_INFO "SMP disabled\n");
|
printk(KERN_INFO "SMP disabled\n");
|
||||||
disable_smp();
|
disable_smp();
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <asm/proto.h>
|
#include <asm/proto.h>
|
||||||
|
#include <asm/page.h>
|
||||||
|
#include <asm/pgtable.h>
|
||||||
|
|
||||||
struct saved_context saved_context;
|
struct saved_context saved_context;
|
||||||
|
|
||||||
@ -140,4 +142,129 @@ void fix_processor_context(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOFTWARE_SUSPEND
|
||||||
|
/* Defined in arch/x86_64/kernel/suspend_asm.S */
|
||||||
|
extern int restore_image(void);
|
||||||
|
|
||||||
|
pgd_t *temp_level4_pgt;
|
||||||
|
|
||||||
|
static void **pages;
|
||||||
|
|
||||||
|
static inline void *__add_page(void)
|
||||||
|
{
|
||||||
|
void **c;
|
||||||
|
|
||||||
|
c = (void **)get_usable_page(GFP_ATOMIC);
|
||||||
|
if (c) {
|
||||||
|
*c = pages;
|
||||||
|
pages = c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *__next_page(void)
|
||||||
|
{
|
||||||
|
void **c;
|
||||||
|
|
||||||
|
c = pages;
|
||||||
|
if (c) {
|
||||||
|
pages = *c;
|
||||||
|
*c = NULL;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to allocate as many usable pages as needed and daisy chain them.
|
||||||
|
* If one allocation fails, free the pages allocated so far
|
||||||
|
*/
|
||||||
|
static int alloc_usable_pages(unsigned long n)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
pages = NULL;
|
||||||
|
do
|
||||||
|
if (!__add_page())
|
||||||
|
break;
|
||||||
|
while (--n);
|
||||||
|
if (n) {
|
||||||
|
p = __next_page();
|
||||||
|
while (p) {
|
||||||
|
free_page((unsigned long)p);
|
||||||
|
p = __next_page();
|
||||||
|
}
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
|
||||||
|
{
|
||||||
|
long i, j;
|
||||||
|
|
||||||
|
i = pud_index(address);
|
||||||
|
pud = pud + i;
|
||||||
|
for (; i < PTRS_PER_PUD; pud++, i++) {
|
||||||
|
unsigned long paddr;
|
||||||
|
pmd_t *pmd;
|
||||||
|
|
||||||
|
paddr = address + i*PUD_SIZE;
|
||||||
|
if (paddr >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pmd = (pmd_t *)__next_page();
|
||||||
|
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
|
||||||
|
for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
|
||||||
|
unsigned long pe;
|
||||||
|
|
||||||
|
if (paddr >= end)
|
||||||
|
break;
|
||||||
|
pe = _PAGE_NX | _PAGE_PSE | _KERNPG_TABLE | paddr;
|
||||||
|
pe &= __supported_pte_mask;
|
||||||
|
set_pmd(pmd, __pmd(pe));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_up_temporary_mappings(void)
|
||||||
|
{
|
||||||
|
unsigned long start, end, next;
|
||||||
|
|
||||||
|
temp_level4_pgt = (pgd_t *)__next_page();
|
||||||
|
|
||||||
|
/* It is safe to reuse the original kernel mapping */
|
||||||
|
set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
|
||||||
|
init_level4_pgt[pgd_index(__START_KERNEL_map)]);
|
||||||
|
|
||||||
|
/* Set up the direct mapping from scratch */
|
||||||
|
start = (unsigned long)pfn_to_kaddr(0);
|
||||||
|
end = (unsigned long)pfn_to_kaddr(end_pfn);
|
||||||
|
|
||||||
|
for (; start < end; start = next) {
|
||||||
|
pud_t *pud = (pud_t *)__next_page();
|
||||||
|
next = start + PGDIR_SIZE;
|
||||||
|
if (next > end)
|
||||||
|
next = end;
|
||||||
|
res_phys_pud_init(pud, __pa(start), __pa(next));
|
||||||
|
set_pgd(temp_level4_pgt + pgd_index(start),
|
||||||
|
mk_kernel_pgd(__pa(pud)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int swsusp_arch_resume(void)
|
||||||
|
{
|
||||||
|
unsigned long n;
|
||||||
|
|
||||||
|
n = ((end_pfn << PAGE_SHIFT) + PUD_SIZE - 1) >> PUD_SHIFT;
|
||||||
|
n += (n + PTRS_PER_PUD - 1) / PTRS_PER_PUD + 1;
|
||||||
|
pr_debug("swsusp_arch_resume(): pages needed = %lu\n", n);
|
||||||
|
if (alloc_usable_pages(n)) {
|
||||||
|
free_eaten_memory();
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
/* We have got enough memory and from now on we cannot recover */
|
||||||
|
set_up_temporary_mappings();
|
||||||
|
restore_image();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SOFTWARE_SUSPEND */
|
||||||
|
@ -39,12 +39,13 @@ ENTRY(swsusp_arch_suspend)
|
|||||||
call swsusp_save
|
call swsusp_save
|
||||||
ret
|
ret
|
||||||
|
|
||||||
ENTRY(swsusp_arch_resume)
|
ENTRY(restore_image)
|
||||||
/* set up cr3 */
|
/* switch to temporary page tables */
|
||||||
leaq init_level4_pgt(%rip),%rax
|
movq $__PAGE_OFFSET, %rdx
|
||||||
subq $__START_KERNEL_map,%rax
|
movq temp_level4_pgt(%rip), %rax
|
||||||
movq %rax,%cr3
|
subq %rdx, %rax
|
||||||
|
movq %rax, %cr3
|
||||||
|
/* Flush TLB */
|
||||||
movq mmu_cr4_features(%rip), %rax
|
movq mmu_cr4_features(%rip), %rax
|
||||||
movq %rax, %rdx
|
movq %rax, %rdx
|
||||||
andq $~(1<<7), %rdx # PGE
|
andq $~(1<<7), %rdx # PGE
|
||||||
@ -69,6 +70,10 @@ loop:
|
|||||||
movq pbe_next(%rdx), %rdx
|
movq pbe_next(%rdx), %rdx
|
||||||
jmp loop
|
jmp loop
|
||||||
done:
|
done:
|
||||||
|
/* go back to the original page tables */
|
||||||
|
leaq init_level4_pgt(%rip), %rax
|
||||||
|
subq $__START_KERNEL_map, %rax
|
||||||
|
movq %rax, %cr3
|
||||||
/* Flush TLB, including "global" things (vmalloc) */
|
/* Flush TLB, including "global" things (vmalloc) */
|
||||||
movq mmu_cr4_features(%rip), %rax
|
movq mmu_cr4_features(%rip), %rax
|
||||||
movq %rax, %rdx
|
movq %rax, %rdx
|
||||||
|
@ -220,8 +220,6 @@ void global_flush_tlb(void)
|
|||||||
down_read(&init_mm.mmap_sem);
|
down_read(&init_mm.mmap_sem);
|
||||||
df = xchg(&df_list, NULL);
|
df = xchg(&df_list, NULL);
|
||||||
up_read(&init_mm.mmap_sem);
|
up_read(&init_mm.mmap_sem);
|
||||||
if (!df)
|
|
||||||
return;
|
|
||||||
flush_map((df && !df->next) ? df->address : 0);
|
flush_map((df && !df->next) ? df->address : 0);
|
||||||
for (; df; df = next_df) {
|
for (; df; df = next_df) {
|
||||||
next_df = df->next;
|
next_df = df->next;
|
||||||
|
@ -58,9 +58,8 @@ acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
|
|||||||
return_VALUE(-EAGAIN);
|
return_VALUE(-EAGAIN);
|
||||||
|
|
||||||
result = acpi_bus_receive_event(&event);
|
result = acpi_bus_receive_event(&event);
|
||||||
if (result) {
|
if (result)
|
||||||
return_VALUE(-EIO);
|
return_VALUE(result);
|
||||||
}
|
|
||||||
|
|
||||||
chars_remaining = sprintf(str, "%s %s %08x %08x\n",
|
chars_remaining = sprintf(str, "%s %s %08x %08x\n",
|
||||||
event.device_class ? event.
|
event.device_class ? event.
|
||||||
|
@ -795,7 +795,7 @@ static void drain_rx_pools (amb_dev * dev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void fill_rx_pool (amb_dev * dev, unsigned char pool,
|
static inline void fill_rx_pool (amb_dev * dev, unsigned char pool,
|
||||||
unsigned int __nocast priority)
|
gfp_t priority)
|
||||||
{
|
{
|
||||||
rx_in rx;
|
rx_in rx;
|
||||||
amb_rxq * rxq;
|
amb_rxq * rxq;
|
||||||
|
@ -1374,8 +1374,7 @@ static void reset_chip (struct fs_dev *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __devinit *aligned_kmalloc (int size, unsigned int __nocast flags,
|
static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment)
|
||||||
int alignment)
|
|
||||||
{
|
{
|
||||||
void *t;
|
void *t;
|
||||||
|
|
||||||
@ -1466,7 +1465,7 @@ static inline int nr_buffers_in_freepool (struct fs_dev *dev, struct freepool *f
|
|||||||
working again after that... -- REW */
|
working again after that... -- REW */
|
||||||
|
|
||||||
static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
|
static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
|
||||||
unsigned int __nocast gfp_flags)
|
gfp_t gfp_flags)
|
||||||
{
|
{
|
||||||
struct FS_BPENTRY *qe, *ne;
|
struct FS_BPENTRY *qe, *ne;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -178,7 +178,7 @@ fore200e_irq_itoa(int irq)
|
|||||||
|
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
fore200e_kmalloc(int size, unsigned int __nocast flags)
|
fore200e_kmalloc(int size, gfp_t flags)
|
||||||
{
|
{
|
||||||
void *chunk = kzalloc(size, flags);
|
void *chunk = kzalloc(size, flags);
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ dma_pool_create (const char *name, struct device *dev,
|
|||||||
|
|
||||||
|
|
||||||
static struct dma_page *
|
static struct dma_page *
|
||||||
pool_alloc_page (struct dma_pool *pool, unsigned int __nocast mem_flags)
|
pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
struct dma_page *page;
|
struct dma_page *page;
|
||||||
int mapsize;
|
int mapsize;
|
||||||
@ -262,8 +262,7 @@ dma_pool_destroy (struct dma_pool *pool)
|
|||||||
* If such a memory block can't be allocated, null is returned.
|
* If such a memory block can't be allocated, null is returned.
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
dma_pool_alloc (struct dma_pool *pool, unsigned int __nocast mem_flags,
|
dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle)
|
||||||
dma_addr_t *handle)
|
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct dma_page *page;
|
struct dma_page *page;
|
||||||
|
@ -229,7 +229,7 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *pkt_rb_alloc(unsigned int __nocast gfp_mask, void *data)
|
static void *pkt_rb_alloc(gfp_t gfp_mask, void *data)
|
||||||
{
|
{
|
||||||
return kmalloc(sizeof(struct pkt_rb_node), gfp_mask);
|
return kmalloc(sizeof(struct pkt_rb_node), gfp_mask);
|
||||||
}
|
}
|
||||||
@ -2082,7 +2082,7 @@ static int pkt_close(struct inode *inode, struct file *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *psd_pool_alloc(unsigned int __nocast gfp_mask, void *data)
|
static void *psd_pool_alloc(gfp_t gfp_mask, void *data)
|
||||||
{
|
{
|
||||||
return kmalloc(sizeof(struct packet_stacked_data), gfp_mask);
|
return kmalloc(sizeof(struct packet_stacked_data), gfp_mask);
|
||||||
}
|
}
|
||||||
|
@ -201,15 +201,15 @@ static int verify_command(struct file *file, unsigned char *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And root can do any command.. */
|
||||||
|
if (capable(CAP_SYS_RAWIO))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
cmd_type[cmd[0]] = CMD_WARNED;
|
cmd_type[cmd[0]] = CMD_WARNED;
|
||||||
printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]);
|
printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And root can do any command.. */
|
|
||||||
if (capable(CAP_SYS_RAWIO))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Otherwise fail it with an "Operation not permitted" */
|
/* Otherwise fail it with an "Operation not permitted" */
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ static void bpa10x_complete(struct urb *urb, struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe,
|
static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe,
|
||||||
size_t size, unsigned int __nocast flags, void *data)
|
size_t size, gfp_t flags, void *data)
|
||||||
{
|
{
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
struct usb_ctrlrequest *cr;
|
struct usb_ctrlrequest *cr;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user