mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
Merge branch 'merge'
This commit is contained in:
commit
7a0c58d051
@ -19,6 +19,7 @@ Contents:
|
||||
- Control dependencies.
|
||||
- SMP barrier pairing.
|
||||
- Examples of memory barrier sequences.
|
||||
- Read memory barriers vs load speculation.
|
||||
|
||||
(*) Explicit kernel barriers.
|
||||
|
||||
@ -248,7 +249,7 @@ And there are a number of things that _must_ or _must_not_ be assumed:
|
||||
we may get either of:
|
||||
|
||||
STORE *A = X; Y = LOAD *A;
|
||||
STORE *A = Y;
|
||||
STORE *A = Y = X;
|
||||
|
||||
|
||||
=========================
|
||||
@ -344,9 +345,12 @@ Memory barriers come in four basic varieties:
|
||||
|
||||
(4) General memory barriers.
|
||||
|
||||
A general memory barrier is a combination of both a read memory barrier
|
||||
and a write memory barrier. It is a partial ordering over both loads and
|
||||
stores.
|
||||
A general memory barrier gives a guarantee that all the LOAD and STORE
|
||||
operations specified before the barrier will appear to happen before all
|
||||
the LOAD and STORE operations specified after the barrier with respect to
|
||||
the other components of the system.
|
||||
|
||||
A general memory barrier is a partial ordering over both loads and stores.
|
||||
|
||||
General memory barriers imply both read and write memory barriers, and so
|
||||
can substitute for either.
|
||||
@ -546,9 +550,9 @@ write barrier, though, again, a general barrier is viable:
|
||||
=============== ===============
|
||||
a = 1;
|
||||
<write barrier>
|
||||
b = 2; x = a;
|
||||
b = 2; x = b;
|
||||
<read barrier>
|
||||
y = b;
|
||||
y = a;
|
||||
|
||||
Or:
|
||||
|
||||
@ -563,6 +567,18 @@ Or:
|
||||
Basically, the read barrier always has to be there, even though it can be of
|
||||
the "weaker" type.
|
||||
|
||||
[!] Note that the stores before the write barrier would normally be expected to
|
||||
match the loads after the read barrier or data dependency barrier, and vice
|
||||
versa:
|
||||
|
||||
CPU 1 CPU 2
|
||||
=============== ===============
|
||||
a = 1; }---- --->{ v = c
|
||||
b = 2; } \ / { w = d
|
||||
<write barrier> \ <read barrier>
|
||||
c = 3; } / \ { x = a;
|
||||
d = 4; }---- --->{ y = b;
|
||||
|
||||
|
||||
EXAMPLES OF MEMORY BARRIER SEQUENCES
|
||||
------------------------------------
|
||||
@ -600,8 +616,8 @@ STORE B, STORE C } all occuring before the unordered set of { STORE D, STORE E
|
||||
| | +------+
|
||||
+-------+ : :
|
||||
|
|
||||
| Sequence in which stores committed to memory system
|
||||
| by CPU 1
|
||||
| Sequence in which stores are committed to the
|
||||
| memory system by CPU 1
|
||||
V
|
||||
|
||||
|
||||
@ -683,14 +699,12 @@ then the following will occur:
|
||||
| : : | |
|
||||
| : : | CPU 2 |
|
||||
| +-------+ | |
|
||||
\ | X->9 |------>| |
|
||||
\ +-------+ | |
|
||||
----->| B->2 | | |
|
||||
+-------+ | |
|
||||
Makes sure all effects ---> ddddddddddddddddd | |
|
||||
prior to the store of C +-------+ | |
|
||||
are perceptible to | B->2 |------>| |
|
||||
successive loads +-------+ | |
|
||||
| | X->9 |------>| |
|
||||
| +-------+ | |
|
||||
Makes sure all effects ---> \ ddddddddddddddddd | |
|
||||
prior to the store of C \ +-------+ | |
|
||||
are perceptible to ----->| B->2 |------>| |
|
||||
subsequent loads +-------+ | |
|
||||
: : +-------+
|
||||
|
||||
|
||||
@ -699,73 +713,239 @@ following sequence of events:
|
||||
|
||||
CPU 1 CPU 2
|
||||
======================= =======================
|
||||
{ A = 0, B = 9 }
|
||||
STORE A=1
|
||||
STORE B=2
|
||||
STORE C=3
|
||||
<write barrier>
|
||||
STORE D=4
|
||||
STORE E=5
|
||||
LOAD A
|
||||
STORE B=2
|
||||
LOAD B
|
||||
LOAD C
|
||||
LOAD D
|
||||
LOAD E
|
||||
LOAD A
|
||||
|
||||
Without intervention, CPU 2 may then choose to perceive the events on CPU 1 in
|
||||
some effectively random order, despite the write barrier issued by CPU 1:
|
||||
|
||||
+-------+ : :
|
||||
| | +------+
|
||||
| |------>| C=3 | }
|
||||
| | : +------+ }
|
||||
| | : | A=1 | }
|
||||
| | : +------+ }
|
||||
| CPU 1 | : | B=2 | }---
|
||||
| | +------+ } \
|
||||
| | wwwwwwwwwwwww} \
|
||||
| | +------+ } \ : : +-------+
|
||||
| | : | E=5 | } \ +-------+ | |
|
||||
| | : +------+ } \ { | C->3 |------>| |
|
||||
| |------>| D=4 | } \ { +-------+ : | |
|
||||
| | +------+ \ { | E->5 | : | |
|
||||
+-------+ : : \ { +-------+ : | |
|
||||
Transfer -->{ | A->1 | : | CPU 2 |
|
||||
from CPU 1 { +-------+ : | |
|
||||
to CPU 2 { | D->4 | : | |
|
||||
{ +-------+ : | |
|
||||
{ | B->2 |------>| |
|
||||
+-------+ | |
|
||||
: : +-------+
|
||||
+-------+ : : : :
|
||||
| | +------+ +-------+
|
||||
| |------>| A=1 |------ --->| A->0 |
|
||||
| | +------+ \ +-------+
|
||||
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
|
||||
| | +------+ | +-------+
|
||||
| |------>| B=2 |--- | : :
|
||||
| | +------+ \ | : : +-------+
|
||||
+-------+ : : \ | +-------+ | |
|
||||
---------->| B->2 |------>| |
|
||||
| +-------+ | CPU 2 |
|
||||
| | A->0 |------>| |
|
||||
| +-------+ | |
|
||||
| : : +-------+
|
||||
\ : :
|
||||
\ +-------+
|
||||
---->| A->1 |
|
||||
+-------+
|
||||
: :
|
||||
|
||||
|
||||
If, however, a read barrier were to be placed between the load of C and the
|
||||
load of D on CPU 2, then the partial ordering imposed by CPU 1 will be
|
||||
perceived correctly by CPU 2.
|
||||
If, however, a read barrier were to be placed between the load of E and the
|
||||
load of A on CPU 2:
|
||||
|
||||
+-------+ : :
|
||||
| | +------+
|
||||
| |------>| C=3 | }
|
||||
| | : +------+ }
|
||||
| | : | A=1 | }---
|
||||
| | : +------+ } \
|
||||
| CPU 1 | : | B=2 | } \
|
||||
| | +------+ \
|
||||
| | wwwwwwwwwwwwwwww \
|
||||
| | +------+ \ : : +-------+
|
||||
| | : | E=5 | } \ +-------+ | |
|
||||
| | : +------+ }--- \ { | C->3 |------>| |
|
||||
| |------>| D=4 | } \ \ { +-------+ : | |
|
||||
| | +------+ \ -->{ | B->2 | : | |
|
||||
+-------+ : : \ { +-------+ : | |
|
||||
\ { | A->1 | : | CPU 2 |
|
||||
\ +-------+ | |
|
||||
At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
|
||||
barrier causes all effects \ +-------+ | |
|
||||
prior to the storage of C \ { | E->5 | : | |
|
||||
to be perceptible to CPU 2 -->{ +-------+ : | |
|
||||
{ | D->4 |------>| |
|
||||
+-------+ | |
|
||||
: : +-------+
|
||||
CPU 1 CPU 2
|
||||
======================= =======================
|
||||
{ A = 0, B = 9 }
|
||||
STORE A=1
|
||||
<write barrier>
|
||||
STORE B=2
|
||||
LOAD B
|
||||
<read barrier>
|
||||
LOAD A
|
||||
|
||||
then the partial ordering imposed by CPU 1 will be perceived correctly by CPU
|
||||
2:
|
||||
|
||||
+-------+ : : : :
|
||||
| | +------+ +-------+
|
||||
| |------>| A=1 |------ --->| A->0 |
|
||||
| | +------+ \ +-------+
|
||||
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
|
||||
| | +------+ | +-------+
|
||||
| |------>| B=2 |--- | : :
|
||||
| | +------+ \ | : : +-------+
|
||||
+-------+ : : \ | +-------+ | |
|
||||
---------->| B->2 |------>| |
|
||||
| +-------+ | CPU 2 |
|
||||
| : : | |
|
||||
| : : | |
|
||||
At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
|
||||
barrier causes all effects \ +-------+ | |
|
||||
prior to the storage of B ---->| A->1 |------>| |
|
||||
to be perceptible to CPU 2 +-------+ | |
|
||||
: : +-------+
|
||||
|
||||
|
||||
To illustrate this more completely, consider what could happen if the code
|
||||
contained a load of A either side of the read barrier:
|
||||
|
||||
CPU 1 CPU 2
|
||||
======================= =======================
|
||||
{ A = 0, B = 9 }
|
||||
STORE A=1
|
||||
<write barrier>
|
||||
STORE B=2
|
||||
LOAD B
|
||||
LOAD A [first load of A]
|
||||
<read barrier>
|
||||
LOAD A [second load of A]
|
||||
|
||||
Even though the two loads of A both occur after the load of B, they may both
|
||||
come up with different values:
|
||||
|
||||
+-------+ : : : :
|
||||
| | +------+ +-------+
|
||||
| |------>| A=1 |------ --->| A->0 |
|
||||
| | +------+ \ +-------+
|
||||
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
|
||||
| | +------+ | +-------+
|
||||
| |------>| B=2 |--- | : :
|
||||
| | +------+ \ | : : +-------+
|
||||
+-------+ : : \ | +-------+ | |
|
||||
---------->| B->2 |------>| |
|
||||
| +-------+ | CPU 2 |
|
||||
| : : | |
|
||||
| : : | |
|
||||
| +-------+ | |
|
||||
| | A->0 |------>| 1st |
|
||||
| +-------+ | |
|
||||
At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
|
||||
barrier causes all effects \ +-------+ | |
|
||||
prior to the storage of B ---->| A->1 |------>| 2nd |
|
||||
to be perceptible to CPU 2 +-------+ | |
|
||||
: : +-------+
|
||||
|
||||
|
||||
But it may be that the update to A from CPU 1 becomes perceptible to CPU 2
|
||||
before the read barrier completes anyway:
|
||||
|
||||
+-------+ : : : :
|
||||
| | +------+ +-------+
|
||||
| |------>| A=1 |------ --->| A->0 |
|
||||
| | +------+ \ +-------+
|
||||
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
|
||||
| | +------+ | +-------+
|
||||
| |------>| B=2 |--- | : :
|
||||
| | +------+ \ | : : +-------+
|
||||
+-------+ : : \ | +-------+ | |
|
||||
---------->| B->2 |------>| |
|
||||
| +-------+ | CPU 2 |
|
||||
| : : | |
|
||||
\ : : | |
|
||||
\ +-------+ | |
|
||||
---->| A->1 |------>| 1st |
|
||||
+-------+ | |
|
||||
rrrrrrrrrrrrrrrrr | |
|
||||
+-------+ | |
|
||||
| A->1 |------>| 2nd |
|
||||
+-------+ | |
|
||||
: : +-------+
|
||||
|
||||
|
||||
The guarantee is that the second load will always come up with A == 1 if the
|
||||
load of B came up with B == 2. No such guarantee exists for the first load of
|
||||
A; that may come up with either A == 0 or A == 1.
|
||||
|
||||
|
||||
READ MEMORY BARRIERS VS LOAD SPECULATION
|
||||
----------------------------------------
|
||||
|
||||
Many CPUs speculate with loads: that is they see that they will need to load an
|
||||
item from memory, and they find a time where they're not using the bus for any
|
||||
other loads, and so do the load in advance - even though they haven't actually
|
||||
got to that point in the instruction execution flow yet. This permits the
|
||||
actual load instruction to potentially complete immediately because the CPU
|
||||
already has the value to hand.
|
||||
|
||||
It may turn out that the CPU didn't actually need the value - perhaps because a
|
||||
branch circumvented the load - in which case it can discard the value or just
|
||||
cache it for later use.
|
||||
|
||||
Consider:
|
||||
|
||||
CPU 1 CPU 2
|
||||
======================= =======================
|
||||
LOAD B
|
||||
DIVIDE } Divide instructions generally
|
||||
DIVIDE } take a long time to perform
|
||||
LOAD A
|
||||
|
||||
Which might appear as this:
|
||||
|
||||
: : +-------+
|
||||
+-------+ | |
|
||||
--->| B->2 |------>| |
|
||||
+-------+ | CPU 2 |
|
||||
: :DIVIDE | |
|
||||
+-------+ | |
|
||||
The CPU being busy doing a ---> --->| A->0 |~~~~ | |
|
||||
division speculates on the +-------+ ~ | |
|
||||
LOAD of A : : ~ | |
|
||||
: :DIVIDE | |
|
||||
: : ~ | |
|
||||
Once the divisions are complete --> : : ~-->| |
|
||||
the CPU can then perform the : : | |
|
||||
LOAD with immediate effect : : +-------+
|
||||
|
||||
|
||||
Placing a read barrier or a data dependency barrier just before the second
|
||||
load:
|
||||
|
||||
CPU 1 CPU 2
|
||||
======================= =======================
|
||||
LOAD B
|
||||
DIVIDE
|
||||
DIVIDE
|
||||
<read barrier>
|
||||
LOAD A
|
||||
|
||||
will force any value speculatively obtained to be reconsidered to an extent
|
||||
dependent on the type of barrier used. If there was no change made to the
|
||||
speculated memory location, then the speculated value will just be used:
|
||||
|
||||
: : +-------+
|
||||
+-------+ | |
|
||||
--->| B->2 |------>| |
|
||||
+-------+ | CPU 2 |
|
||||
: :DIVIDE | |
|
||||
+-------+ | |
|
||||
The CPU being busy doing a ---> --->| A->0 |~~~~ | |
|
||||
division speculates on the +-------+ ~ | |
|
||||
LOAD of A : : ~ | |
|
||||
: :DIVIDE | |
|
||||
: : ~ | |
|
||||
: : ~ | |
|
||||
rrrrrrrrrrrrrrrr~ | |
|
||||
: : ~ | |
|
||||
: : ~-->| |
|
||||
: : | |
|
||||
: : +-------+
|
||||
|
||||
|
||||
but if there was an update or an invalidation from another CPU pending, then
|
||||
the speculation will be cancelled and the value reloaded:
|
||||
|
||||
: : +-------+
|
||||
+-------+ | |
|
||||
--->| B->2 |------>| |
|
||||
+-------+ | CPU 2 |
|
||||
: :DIVIDE | |
|
||||
+-------+ | |
|
||||
The CPU being busy doing a ---> --->| A->0 |~~~~ | |
|
||||
division speculates on the +-------+ ~ | |
|
||||
LOAD of A : : ~ | |
|
||||
: :DIVIDE | |
|
||||
: : ~ | |
|
||||
: : ~ | |
|
||||
rrrrrrrrrrrrrrrrr | |
|
||||
+-------+ | |
|
||||
The speculation is discarded ---> --->| A->1 |------>| |
|
||||
and an updated value is +-------+ | |
|
||||
retrieved : : +-------+
|
||||
|
||||
|
||||
========================
|
||||
@ -901,7 +1081,7 @@ IMPLICIT KERNEL MEMORY BARRIERS
|
||||
===============================
|
||||
|
||||
Some of the other functions in the linux kernel imply memory barriers, amongst
|
||||
which are locking, scheduling and memory allocation functions.
|
||||
which are locking and scheduling functions.
|
||||
|
||||
This specification is a _minimum_ guarantee; any particular architecture may
|
||||
provide more substantial guarantees, but these may not be relied upon outside
|
||||
@ -966,6 +1146,20 @@ equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
|
||||
barriers is that the effects instructions outside of a critical section may
|
||||
seep into the inside of the critical section.
|
||||
|
||||
A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
|
||||
because it is possible for an access preceding the LOCK to happen after the
|
||||
LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
|
||||
two accesses can themselves then cross:
|
||||
|
||||
*A = a;
|
||||
LOCK
|
||||
UNLOCK
|
||||
*B = b;
|
||||
|
||||
may occur as:
|
||||
|
||||
LOCK, STORE *B, STORE *A, UNLOCK
|
||||
|
||||
Locks and semaphores may not provide any guarantee of ordering on UP compiled
|
||||
systems, and so cannot be counted on in such a situation to actually achieve
|
||||
anything at all - especially with respect to I/O accesses - unless combined
|
||||
@ -1016,8 +1210,6 @@ Other functions that imply barriers:
|
||||
|
||||
(*) schedule() and similar imply full memory barriers.
|
||||
|
||||
(*) Memory allocation and release functions imply full memory barriers.
|
||||
|
||||
|
||||
=================================
|
||||
INTER-CPU LOCKING BARRIER EFFECTS
|
||||
|
@ -214,12 +214,13 @@ hardware.
|
||||
The interaction of the iflag bits is as follows (parity error
|
||||
given as an example):
|
||||
Parity error INPCK IGNPAR
|
||||
None n/a n/a character received
|
||||
Yes n/a 0 character discarded
|
||||
Yes 0 1 character received, marked as
|
||||
n/a 0 n/a character received, marked as
|
||||
TTY_NORMAL
|
||||
Yes 1 1 character received, marked as
|
||||
None 1 n/a character received, marked as
|
||||
TTY_NORMAL
|
||||
Yes 1 0 character received, marked as
|
||||
TTY_PARITY
|
||||
Yes 1 1 character discarded
|
||||
|
||||
Other flags may be used (eg, xon/xoff characters) if your
|
||||
hardware supports hardware "soft" flow control.
|
||||
|
17
MAINTAINERS
17
MAINTAINERS
@ -568,6 +568,18 @@ L: linuxppc-dev@ozlabs.org
|
||||
W: http://www.penguinppc.org/ppc64/
|
||||
S: Supported
|
||||
|
||||
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
|
||||
P: Michael Chan
|
||||
M: mchan@broadcom.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
BROADCOM TG3 GIGABIT ETHERNET DRIVER
|
||||
P: Michael Chan
|
||||
M: mchan@broadcom.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
BTTV VIDEO4LINUX DRIVER
|
||||
P: Mauro Carvalho Chehab
|
||||
M: mchehab@infradead.org
|
||||
@ -1877,6 +1889,11 @@ L: linux-kernel@vger.kernel.org
|
||||
W: http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html
|
||||
S: Maintained
|
||||
|
||||
MULTIMEDIA CARD SUBSYSTEM
|
||||
P: Russell King
|
||||
M: rmk+mmc@arm.linux.org.uk
|
||||
S: Maintained
|
||||
|
||||
MULTISOUND SOUND DRIVER
|
||||
P: Andrew Veliath
|
||||
M: andrewtv@usa.net
|
||||
|
4
Makefile
4
Makefile
@ -1,8 +1,8 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 17
|
||||
EXTRAVERSION =-rc5
|
||||
NAME=Lordi Rules
|
||||
EXTRAVERSION =-rc6
|
||||
NAME=Crazed Snow-Weasel
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
|
@ -182,7 +182,6 @@ EXPORT_SYMBOL(smp_num_cpus);
|
||||
EXPORT_SYMBOL(smp_call_function);
|
||||
EXPORT_SYMBOL(smp_call_function_on_cpu);
|
||||
EXPORT_SYMBOL(_atomic_dec_and_lock);
|
||||
EXPORT_SYMBOL(cpu_present_mask);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
|
@ -94,7 +94,7 @@ common_shutdown_1(void *generic_ptr)
|
||||
if (cpuid != boot_cpuid) {
|
||||
flags |= 0x00040000UL; /* "remain halted" */
|
||||
*pflags = flags;
|
||||
clear_bit(cpuid, &cpu_present_mask);
|
||||
cpu_clear(cpuid, cpu_present_map);
|
||||
halt();
|
||||
}
|
||||
#endif
|
||||
@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Wait for the secondaries to halt. */
|
||||
cpu_clear(boot_cpuid, cpu_possible_map);
|
||||
while (cpus_weight(cpu_possible_map))
|
||||
cpu_clear(boot_cpuid, cpu_present_map);
|
||||
while (cpus_weight(cpu_present_map))
|
||||
barrier();
|
||||
#endif
|
||||
|
||||
|
@ -68,7 +68,6 @@ enum ipi_message_type {
|
||||
static int smp_secondary_alive __initdata = 0;
|
||||
|
||||
/* Which cpus ids came online. */
|
||||
cpumask_t cpu_present_mask;
|
||||
cpumask_t cpu_online_map;
|
||||
|
||||
EXPORT_SYMBOL(cpu_online_map);
|
||||
@ -439,7 +438,7 @@ setup_smp(void)
|
||||
if ((cpu->flags & 0x1cc) == 0x1cc) {
|
||||
smp_num_probed++;
|
||||
/* Assume here that "whami" == index */
|
||||
cpu_set(i, cpu_present_mask);
|
||||
cpu_set(i, cpu_present_map);
|
||||
cpu->pal_revision = boot_cpu_palrev;
|
||||
}
|
||||
|
||||
@ -450,11 +449,10 @@ setup_smp(void)
|
||||
}
|
||||
} else {
|
||||
smp_num_probed = 1;
|
||||
cpu_set(boot_cpuid, cpu_present_mask);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
|
||||
smp_num_probed, cpu_possible_map.bits[0]);
|
||||
printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
|
||||
smp_num_probed, cpu_present_map.bits[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -473,7 +471,7 @@ smp_prepare_cpus(unsigned int max_cpus)
|
||||
|
||||
/* Nothing to do on a UP box, or when told not to. */
|
||||
if (smp_num_probed == 1 || max_cpus == 0) {
|
||||
cpu_present_mask = cpumask_of_cpu(boot_cpuid);
|
||||
cpu_present_map = cpumask_of_cpu(boot_cpuid);
|
||||
printk(KERN_INFO "SMP mode deactivated.\n");
|
||||
return;
|
||||
}
|
||||
@ -486,10 +484,6 @@ smp_prepare_cpus(unsigned int max_cpus)
|
||||
void __devinit
|
||||
smp_prepare_boot_cpu(void)
|
||||
{
|
||||
/*
|
||||
* Mark the boot cpu (current cpu) as online
|
||||
*/
|
||||
cpu_set(smp_processor_id(), cpu_online_map);
|
||||
}
|
||||
|
||||
int __devinit
|
||||
|
@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask)
|
||||
register int bcpu = boot_cpuid;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpumask_t cpm = cpu_present_mask;
|
||||
cpumask_t cpm = cpu_present_map;
|
||||
volatile unsigned long *dim0, *dim1, *dim2, *dim3;
|
||||
unsigned long mask0, mask1, mask2, mask3, dummy;
|
||||
|
||||
|
@ -101,7 +101,7 @@ config DEBUG_S3C2410_UART
|
||||
help
|
||||
Choice for UART for kernel low-level using S3C2410 UARTS,
|
||||
should be between zero and two. The port must have been
|
||||
initalised by the boot-loader before use.
|
||||
initialised by the boot-loader before use.
|
||||
|
||||
The uncompressor code port configuration is now handled
|
||||
by CONFIG_S3C2410_LOWLEVEL_UART_PORT.
|
||||
|
@ -111,21 +111,21 @@ static void __init ts72xx_map_io(void)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char ts72xx_rtc_readb(unsigned long addr)
|
||||
static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
|
||||
{
|
||||
__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
|
||||
return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
|
||||
}
|
||||
|
||||
static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
|
||||
static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
|
||||
{
|
||||
__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
|
||||
__raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
|
||||
}
|
||||
|
||||
static struct m48t86_ops ts72xx_rtc_ops = {
|
||||
.readb = ts72xx_rtc_readb,
|
||||
.writeb = ts72xx_rtc_writeb,
|
||||
.readbyte = ts72xx_rtc_readbyte,
|
||||
.writebyte = ts72xx_rtc_writebyte,
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_rtc_device = {
|
||||
|
@ -178,8 +178,12 @@ static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
|
||||
|
||||
static void ixp23xx_irq_mask(unsigned int irq)
|
||||
{
|
||||
volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
volatile unsigned long *intr_reg;
|
||||
|
||||
if (irq >= 56)
|
||||
irq += 8;
|
||||
|
||||
intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
*intr_reg &= ~(1 << (irq % 32));
|
||||
}
|
||||
|
||||
@ -199,17 +203,25 @@ static void ixp23xx_irq_ack(unsigned int irq)
|
||||
*/
|
||||
static void ixp23xx_irq_level_unmask(unsigned int irq)
|
||||
{
|
||||
volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
volatile unsigned long *intr_reg;
|
||||
|
||||
ixp23xx_irq_ack(irq);
|
||||
|
||||
if (irq >= 56)
|
||||
irq += 8;
|
||||
|
||||
intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
*intr_reg |= (1 << (irq % 32));
|
||||
}
|
||||
|
||||
static void ixp23xx_irq_edge_unmask(unsigned int irq)
|
||||
{
|
||||
volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
volatile unsigned long *intr_reg;
|
||||
|
||||
if (irq >= 56)
|
||||
irq += 8;
|
||||
|
||||
intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
|
||||
*intr_reg |= (1 << (irq % 32));
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ config IXP4XX_INDIRECT_PCI
|
||||
2) If > 64MB of memory space is required, the IXP4xx can be
|
||||
configured to use indirect registers to access PCI This allows
|
||||
for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus.
|
||||
The disadvantadge of this is that every PCI access requires
|
||||
The disadvantage of this is that every PCI access requires
|
||||
three local register accesses plus a spinlock, but in some
|
||||
cases the performance hit is acceptable. In addition, you cannot
|
||||
mmap() PCI devices in this case due to the indirect nature
|
||||
|
@ -493,6 +493,7 @@ static void __init mainstone_map_io(void)
|
||||
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
|
||||
/* Maintainer: MontaVista Software Inc. */
|
||||
.phys_io = 0x40000000,
|
||||
.boot_params = 0xa0000100, /* BLOB boot parameter setting */
|
||||
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
||||
.map_io = mainstone_map_io,
|
||||
.init_irq = mainstone_init_irq,
|
||||
|
@ -170,7 +170,7 @@ config S3C2410_PM_DEBUG
|
||||
depends on ARCH_S3C2410 && PM
|
||||
help
|
||||
Say Y here if you want verbose debugging from the PM Suspend and
|
||||
Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt`
|
||||
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
for more information.
|
||||
|
||||
config S3C2410_PM_CHECK
|
||||
|
@ -5,17 +5,34 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <asm/pci-direct.h>
|
||||
#include <asm/acpi.h>
|
||||
#include <asm/apic.h>
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
static int nvidia_hpet_detected __initdata;
|
||||
|
||||
static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
|
||||
{
|
||||
nvidia_hpet_detected = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init check_bridge(int vendor, int device)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
/* According to Nvidia all timer overrides are bogus. Just ignore
|
||||
them all. */
|
||||
/* According to Nvidia all timer overrides are bogus unless HPET
|
||||
is enabled. */
|
||||
if (vendor == PCI_VENDOR_ID_NVIDIA) {
|
||||
acpi_skip_timer_override = 1;
|
||||
nvidia_hpet_detected = 0;
|
||||
acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
|
||||
if (nvidia_hpet_detected == 0) {
|
||||
acpi_skip_timer_override = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) {
|
||||
|
@ -1547,15 +1547,18 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (efi_enabled)
|
||||
efi_map_memmap();
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
check_acpi_pci(); /* Checks more than just ACPI actually */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
* Parse the ACPI tables for possible boot-time SMP configuration.
|
||||
*/
|
||||
acpi_boot_table_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
check_acpi_pci(); /* Checks more than just ACPI actually */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
acpi_boot_init();
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
|
||||
|
@ -1,10 +1,9 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, assuming a version of
|
||||
* pmon is the boot code.
|
||||
* PROM library initialisation code, assuming YAMON is the boot loader.
|
||||
*
|
||||
* Copyright 2000,2001 MontaVista Software Inc.
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
@ -49,9 +48,9 @@ extern char **prom_argv, **prom_envp;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
/* char *val; */
|
||||
}t_env_var;
|
||||
char *name;
|
||||
char *val;
|
||||
} t_env_var;
|
||||
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
@ -85,21 +84,16 @@ char *prom_getenv(char *envname)
|
||||
{
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* Environment variables are stored in the form of "memsize=64".
|
||||
*/
|
||||
|
||||
t_env_var *env = (t_env_var *)prom_envp;
|
||||
int i;
|
||||
|
||||
i = strlen(envname);
|
||||
|
||||
while(env->name) {
|
||||
if(strncmp(envname, env->name, i) == 0) {
|
||||
return(env->name + strlen(envname) + 1);
|
||||
}
|
||||
while (env->name) {
|
||||
if (strcmp(envname, env->name) == 0)
|
||||
return env->val;
|
||||
env++;
|
||||
}
|
||||
return(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
|
@ -112,6 +112,11 @@ sdsleep:
|
||||
mtc0 k0, CP0_PAGEMASK
|
||||
lw k0, 0x14(sp)
|
||||
mtc0 k0, CP0_CONFIG
|
||||
|
||||
/* We need to catch the ealry Alchemy SOCs with
|
||||
* the write-only Config[OD] bit and set it back to one...
|
||||
*/
|
||||
jal au1x00_fixup_config_od
|
||||
lw $1, PT_R1(sp)
|
||||
lw $2, PT_R2(sp)
|
||||
lw $3, PT_R3(sp)
|
||||
|
@ -86,7 +86,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -86,7 +86,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -149,7 +149,7 @@ void serial_set(int channel, unsigned long baud)
|
||||
#else
|
||||
/*
|
||||
* Note: Set baud rate, hardcoded here for rate of 115200
|
||||
* since became unsure of above "buad rate" algorithm (??).
|
||||
* since became unsure of above "baud rate" algorithm (??).
|
||||
*/
|
||||
outreg(channel, LCR, 0x83);
|
||||
outreg(channel, DLM, 0x00); // See note above
|
||||
|
@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -72,7 +72,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -206,7 +206,7 @@ static inline void check_daddi(void)
|
||||
"daddi %0, %1, %3\n\t"
|
||||
".set pop"
|
||||
: "=r" (v), "=&r" (tmp)
|
||||
: "I" (0xffffffffffffdb9a), "I" (0x1234));
|
||||
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
|
||||
set_except_vector(12, handler);
|
||||
local_irq_restore(flags);
|
||||
|
||||
@ -224,7 +224,7 @@ static inline void check_daddi(void)
|
||||
"dsrl %1, %1, 1\n\t"
|
||||
"daddi %0, %1, %3"
|
||||
: "=r" (v), "=&r" (tmp)
|
||||
: "I" (0xffffffffffffdb9a), "I" (0x1234));
|
||||
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
|
||||
set_except_vector(12, handler);
|
||||
local_irq_restore(flags);
|
||||
|
||||
@ -280,7 +280,7 @@ static inline void check_daddiu(void)
|
||||
"daddu %1, %2\n\t"
|
||||
".set pop"
|
||||
: "=&r" (v), "=&r" (w), "=&r" (tmp)
|
||||
: "I" (0xffffffffffffdb9a), "I" (0x1234));
|
||||
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
|
||||
|
||||
if (v == w) {
|
||||
printk("no.\n");
|
||||
@ -296,7 +296,7 @@ static inline void check_daddiu(void)
|
||||
"addiu %1, $0, %4\n\t"
|
||||
"daddu %1, %2"
|
||||
: "=&r" (v), "=&r" (w), "=&r" (tmp)
|
||||
: "I" (0xffffffffffffdb9a), "I" (0x1234));
|
||||
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
|
||||
|
||||
if (v == w) {
|
||||
printk("yes.\n");
|
||||
|
@ -655,7 +655,7 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
|
||||
case PRID_IMP_SB1:
|
||||
c->cputype = CPU_SB1;
|
||||
/* FPU in pass1 is known to have issues. */
|
||||
if ((c->processor_id & 0xff) < 0x20)
|
||||
if ((c->processor_id & 0xff) < 0x02)
|
||||
c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
|
||||
break;
|
||||
case PRID_IMP_SB1A:
|
||||
|
@ -288,6 +288,9 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
|
||||
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF_MIPS_R_SYM(rel[i]);
|
||||
if (!sym->st_value) {
|
||||
/* Ignore unresolved weak symbol */
|
||||
if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
||||
continue;
|
||||
printk(KERN_WARNING "%s: Unknown symbol %s\n",
|
||||
me->name, strtab + sym->st_name);
|
||||
return -ENOENT;
|
||||
@ -325,6 +328,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
|
||||
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF_MIPS_R_SYM(rel[i]);
|
||||
if (!sym->st_value) {
|
||||
/* Ignore unresolved weak symbol */
|
||||
if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
||||
continue;
|
||||
printk(KERN_WARNING "%s: Unknown symbol %s\n",
|
||||
me->name, strtab + sym->st_name);
|
||||
return -ENOENT;
|
||||
|
@ -209,7 +209,7 @@ sys_call_table:
|
||||
PTR sys_fork
|
||||
PTR sys_read
|
||||
PTR sys_write
|
||||
PTR sys_open /* 4005 */
|
||||
PTR compat_sys_open /* 4005 */
|
||||
PTR sys_close
|
||||
PTR sys_waitpid
|
||||
PTR sys_creat
|
||||
|
@ -246,7 +246,7 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
|
||||
#ifdef CONFIG_64BIT
|
||||
/* HACK: Guess if the sign extension was forgotten */
|
||||
if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
|
||||
start |= 0xffffffff00000000;
|
||||
start |= 0xffffffff00000000UL;
|
||||
#endif
|
||||
|
||||
end = start + size;
|
||||
@ -355,8 +355,6 @@ static inline void bootmem_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
memory_present(0, first_usable_pfn, max_low_pfn);
|
||||
|
||||
/* Initialize the boot-time allocator with low memory only. */
|
||||
bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
|
||||
|
||||
@ -410,6 +408,7 @@ static inline void bootmem_init(void)
|
||||
|
||||
/* Register lowmem ranges */
|
||||
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
|
||||
memory_present(0, curr_pfn, curr_pfn + size - 1);
|
||||
}
|
||||
|
||||
/* Reserve the bootmap memory. */
|
||||
@ -419,17 +418,20 @@ static inline void bootmem_init(void)
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
initrd_below_start_ok = 1;
|
||||
if (initrd_start) {
|
||||
unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
|
||||
unsigned long initrd_size = ((unsigned char *)initrd_end) -
|
||||
((unsigned char *)initrd_start);
|
||||
const int width = sizeof(long) * 2;
|
||||
|
||||
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
|
||||
(void *)initrd_start, initrd_size);
|
||||
|
||||
if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
|
||||
printk("initrd extends beyond end of memory "
|
||||
"(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
|
||||
sizeof(long) * 2,
|
||||
(unsigned long long)CPHYSADDR(initrd_end),
|
||||
sizeof(long) * 2,
|
||||
(unsigned long long)PFN_PHYS(max_low_pfn));
|
||||
width,
|
||||
(unsigned long long) CPHYSADDR(initrd_end),
|
||||
width,
|
||||
(unsigned long long) PFN_PHYS(max_low_pfn));
|
||||
initrd_start = initrd_end = 0;
|
||||
initrd_reserve_bootmem = 0;
|
||||
}
|
||||
|
@ -247,6 +247,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
current_thread_info()->cpu = 0;
|
||||
smp_tune_scheduling();
|
||||
plat_prepare_cpus(max_cpus);
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
cpu_present_map = cpu_possible_map;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* preload SMP state for boot cpu */
|
||||
@ -442,7 +445,7 @@ static int __init topology_init(void)
|
||||
int cpu;
|
||||
int ret;
|
||||
|
||||
for_each_cpu(cpu) {
|
||||
for_each_present_cpu(cpu) {
|
||||
ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
|
||||
if (ret)
|
||||
printk(KERN_WARNING "topology_init: register_cpu %d "
|
||||
|
@ -276,8 +276,7 @@ void sys_set_thread_area(unsigned long addr)
|
||||
|
||||
asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
|
||||
{
|
||||
int tmp, len;
|
||||
char __user *name;
|
||||
int tmp;
|
||||
|
||||
switch(cmd) {
|
||||
case MIPS_ATOMIC_SET:
|
||||
|
@ -819,15 +819,30 @@ asmlinkage void do_watch(struct pt_regs *regs)
|
||||
|
||||
asmlinkage void do_mcheck(struct pt_regs *regs)
|
||||
{
|
||||
const int field = 2 * sizeof(unsigned long);
|
||||
int multi_match = regs->cp0_status & ST0_TS;
|
||||
|
||||
show_regs(regs);
|
||||
dump_tlb_all();
|
||||
|
||||
if (multi_match) {
|
||||
printk("Index : %0x\n", read_c0_index());
|
||||
printk("Pagemask: %0x\n", read_c0_pagemask());
|
||||
printk("EntryHi : %0*lx\n", field, read_c0_entryhi());
|
||||
printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
|
||||
printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
|
||||
printk("\n");
|
||||
dump_tlb_all();
|
||||
}
|
||||
|
||||
show_code((unsigned int *) regs->cp0_epc);
|
||||
|
||||
/*
|
||||
* Some chips may have other causes of machine check (e.g. SB1
|
||||
* graduation timer)
|
||||
*/
|
||||
panic("Caught Machine Check exception - %scaused by multiple "
|
||||
"matching entries in the TLB.",
|
||||
(regs->cp0_status & ST0_TS) ? "" : "not ");
|
||||
(multi_match) ? "" : "not ");
|
||||
}
|
||||
|
||||
asmlinkage void do_mt(struct pt_regs *regs)
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
ieee754dp ieee754dp_fint(int x)
|
||||
{
|
||||
COMPXDP;
|
||||
u64 xm;
|
||||
int xe;
|
||||
int xs;
|
||||
|
||||
CLEARCX;
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
ieee754dp ieee754dp_flong(s64 x)
|
||||
{
|
||||
COMPXDP;
|
||||
u64 xm;
|
||||
int xe;
|
||||
int xs;
|
||||
|
||||
CLEARCX;
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
ieee754sp ieee754sp_fint(int x)
|
||||
{
|
||||
COMPXSP;
|
||||
unsigned xm;
|
||||
int xe;
|
||||
int xs;
|
||||
|
||||
CLEARCX;
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
ieee754sp ieee754sp_flong(s64 x)
|
||||
{
|
||||
COMPXDP; /* <--- need 64-bit mantissa temp */
|
||||
u64 xm; /* <--- need 64-bit mantissa temp */
|
||||
int xe;
|
||||
int xs;
|
||||
|
||||
CLEARCX;
|
||||
|
||||
|
@ -1161,6 +1161,31 @@ static void __init setup_scache(void)
|
||||
c->options |= MIPS_CPU_SUBSET_CACHES;
|
||||
}
|
||||
|
||||
void au1x00_fixup_config_od(void)
|
||||
{
|
||||
/*
|
||||
* c0_config.od (bit 19) was write only (and read as 0)
|
||||
* on the early revisions of Alchemy SOCs. It disables the bus
|
||||
* transaction overlapping and needs to be set to fix various errata.
|
||||
*/
|
||||
switch (read_c0_prid()) {
|
||||
case 0x00030100: /* Au1000 DA */
|
||||
case 0x00030201: /* Au1000 HA */
|
||||
case 0x00030202: /* Au1000 HB */
|
||||
case 0x01030200: /* Au1500 AB */
|
||||
/*
|
||||
* Au1100 errata actually keeps silence about this bit, so we set it
|
||||
* just in case for those revisions that require it to be set according
|
||||
* to arch/mips/au1000/common/cputable.c
|
||||
*/
|
||||
case 0x02030200: /* Au1100 AB */
|
||||
case 0x02030201: /* Au1100 BA */
|
||||
case 0x02030202: /* Au1100 BC */
|
||||
set_c0_config(1 << 19);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void coherency_setup(void)
|
||||
{
|
||||
change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
|
||||
@ -1181,6 +1206,15 @@ static inline void coherency_setup(void)
|
||||
case CPU_R4400MC:
|
||||
clear_c0_config(CONF_CU);
|
||||
break;
|
||||
/*
|
||||
* We need to catch the ealry Alchemy SOCs with
|
||||
* the write-only co_config.od bit and set it back to one...
|
||||
*/
|
||||
case CPU_AU1000: /* rev. DA, HA, HB */
|
||||
case CPU_AU1100: /* rev. AB, BA, BC ?? */
|
||||
case CPU_AU1500: /* rev. AB */
|
||||
au1x00_fixup_config_od();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ void __init mem_init(void)
|
||||
for (tmp = 0; tmp < max_low_pfn; tmp++)
|
||||
if (page_is_ram(tmp)) {
|
||||
ram++;
|
||||
if (PageReserved(mem_map+tmp))
|
||||
if (PageReserved(pfn_to_page(tmp)))
|
||||
reservedpages++;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
|
||||
/* disable interrupts */
|
||||
UART16550_WRITE(OFS_INTR_ENABLE, 0);
|
||||
|
||||
/* set up buad rate */
|
||||
/* set up baud rate */
|
||||
{
|
||||
uint32 divisor;
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
#include "op_impl.h"
|
||||
|
||||
extern struct op_mips_model op_model_mipsxx __attribute__((weak));
|
||||
extern struct op_mips_model op_model_rm9000 __attribute__((weak));
|
||||
extern struct op_mips_model op_model_mipsxx_ops __attribute__((weak));
|
||||
extern struct op_mips_model op_model_rm9000_ops __attribute__((weak));
|
||||
|
||||
static struct op_mips_model *model;
|
||||
|
||||
@ -83,11 +83,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
|
||||
case CPU_74K:
|
||||
case CPU_SB1:
|
||||
case CPU_SB1A:
|
||||
lmodel = &op_model_mipsxx;
|
||||
lmodel = &op_model_mipsxx_ops;
|
||||
break;
|
||||
|
||||
case CPU_RM9000:
|
||||
lmodel = &op_model_rm9000;
|
||||
lmodel = &op_model_rm9000_ops;
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#define M_COUNTER_OVERFLOW (1UL << 31)
|
||||
|
||||
struct op_mips_model op_model_mipsxx;
|
||||
struct op_mips_model op_model_mipsxx_ops;
|
||||
|
||||
static struct mipsxx_register_config {
|
||||
unsigned int control[4];
|
||||
@ -34,7 +34,7 @@ static struct mipsxx_register_config {
|
||||
|
||||
static void mipsxx_reg_setup(struct op_counter_config *ctr)
|
||||
{
|
||||
unsigned int counters = op_model_mipsxx.num_counters;
|
||||
unsigned int counters = op_model_mipsxx_ops.num_counters;
|
||||
int i;
|
||||
|
||||
/* Compute the performance counter control word. */
|
||||
@ -62,7 +62,7 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
|
||||
|
||||
static void mipsxx_cpu_setup (void *args)
|
||||
{
|
||||
unsigned int counters = op_model_mipsxx.num_counters;
|
||||
unsigned int counters = op_model_mipsxx_ops.num_counters;
|
||||
|
||||
switch (counters) {
|
||||
case 4:
|
||||
@ -83,7 +83,7 @@ static void mipsxx_cpu_setup (void *args)
|
||||
/* Start all counters on current CPU */
|
||||
static void mipsxx_cpu_start(void *args)
|
||||
{
|
||||
unsigned int counters = op_model_mipsxx.num_counters;
|
||||
unsigned int counters = op_model_mipsxx_ops.num_counters;
|
||||
|
||||
switch (counters) {
|
||||
case 4:
|
||||
@ -100,7 +100,7 @@ static void mipsxx_cpu_start(void *args)
|
||||
/* Stop all counters on current CPU */
|
||||
static void mipsxx_cpu_stop(void *args)
|
||||
{
|
||||
unsigned int counters = op_model_mipsxx.num_counters;
|
||||
unsigned int counters = op_model_mipsxx_ops.num_counters;
|
||||
|
||||
switch (counters) {
|
||||
case 4:
|
||||
@ -116,7 +116,7 @@ static void mipsxx_cpu_stop(void *args)
|
||||
|
||||
static int mipsxx_perfcount_handler(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int counters = op_model_mipsxx.num_counters;
|
||||
unsigned int counters = op_model_mipsxx_ops.num_counters;
|
||||
unsigned int control;
|
||||
unsigned int counter;
|
||||
int handled = 0;
|
||||
@ -187,37 +187,37 @@ static int __init mipsxx_init(void)
|
||||
|
||||
reset_counters(counters);
|
||||
|
||||
op_model_mipsxx.num_counters = counters;
|
||||
op_model_mipsxx_ops.num_counters = counters;
|
||||
switch (current_cpu_data.cputype) {
|
||||
case CPU_20KC:
|
||||
op_model_mipsxx.cpu_type = "mips/20K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/20K";
|
||||
break;
|
||||
|
||||
case CPU_24K:
|
||||
op_model_mipsxx.cpu_type = "mips/24K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/24K";
|
||||
break;
|
||||
|
||||
case CPU_25KF:
|
||||
op_model_mipsxx.cpu_type = "mips/25K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/25K";
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
case CPU_34K:
|
||||
op_model_mipsxx.cpu_type = "mips/34K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/34K";
|
||||
break;
|
||||
|
||||
case CPU_74K:
|
||||
op_model_mipsxx.cpu_type = "mips/74K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/74K";
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CPU_5KC:
|
||||
op_model_mipsxx.cpu_type = "mips/5K";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/5K";
|
||||
break;
|
||||
|
||||
case CPU_SB1:
|
||||
case CPU_SB1A:
|
||||
op_model_mipsxx.cpu_type = "mips/sb1";
|
||||
op_model_mipsxx_ops.cpu_type = "mips/sb1";
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -233,12 +233,12 @@ static int __init mipsxx_init(void)
|
||||
|
||||
static void mipsxx_exit(void)
|
||||
{
|
||||
reset_counters(op_model_mipsxx.num_counters);
|
||||
reset_counters(op_model_mipsxx_ops.num_counters);
|
||||
|
||||
perf_irq = null_perf_irq;
|
||||
}
|
||||
|
||||
struct op_mips_model op_model_mipsxx = {
|
||||
struct op_mips_model op_model_mipsxx_ops = {
|
||||
.reg_setup = mipsxx_reg_setup,
|
||||
.cpu_setup = mipsxx_cpu_setup,
|
||||
.init = mipsxx_init,
|
||||
|
@ -126,7 +126,7 @@ static void rm9000_exit(void)
|
||||
free_irq(rm9000_perfcount_irq, NULL);
|
||||
}
|
||||
|
||||
struct op_mips_model op_model_rm9000 = {
|
||||
struct op_mips_model op_model_rm9000_ops = {
|
||||
.reg_setup = rm9000_reg_setup,
|
||||
.cpu_setup = rm9000_cpu_setup,
|
||||
.init = rm9000_init,
|
||||
|
@ -31,12 +31,12 @@
|
||||
/* issue a PIO read to make sure no PIO writes are pending */
|
||||
static void inline flush_crime_bus(void)
|
||||
{
|
||||
volatile unsigned long junk = crime->control;
|
||||
crime->control;
|
||||
}
|
||||
|
||||
static void inline flush_mace_bus(void)
|
||||
{
|
||||
volatile unsigned long junk = mace->perif.ctrl.misc;
|
||||
mace->perif.ctrl.misc;
|
||||
}
|
||||
|
||||
#undef DEBUG_IRQ
|
||||
|
@ -776,6 +776,7 @@ static void __init prom_send_capabilities(void)
|
||||
/* try calling the ibm,client-architecture-support method */
|
||||
if (call_prom_ret("call-method", 3, 2, &ret,
|
||||
ADDR("ibm,client-architecture-support"),
|
||||
root,
|
||||
ADDR(ibm_architecture_vec)) == 0) {
|
||||
/* the call exists... */
|
||||
if (ret)
|
||||
@ -1541,6 +1542,15 @@ static int __init prom_find_machine_type(void)
|
||||
if (strstr(p, RELOC("Power Macintosh")) ||
|
||||
strstr(p, RELOC("MacRISC")))
|
||||
return PLATFORM_POWERMAC;
|
||||
#ifdef CONFIG_PPC64
|
||||
/* We must make sure we don't detect the IBM Cell
|
||||
* blades as pSeries due to some firmware issues,
|
||||
* so we do it here.
|
||||
*/
|
||||
if (strstr(p, RELOC("IBM,CBEA")) ||
|
||||
strstr(p, RELOC("IBM,CPBW-1.0")))
|
||||
return PLATFORM_GENERIC;
|
||||
#endif /* CONFIG_PPC64 */
|
||||
i += sl + 1;
|
||||
}
|
||||
}
|
||||
|
@ -808,10 +808,13 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
|
||||
if (__get_user(cmcp, &ucp->uc_regs))
|
||||
return -EFAULT;
|
||||
mcp = (struct mcontext __user *)(u64)cmcp;
|
||||
/* no need to check access_ok(mcp), since mcp < 4GB */
|
||||
}
|
||||
#else
|
||||
if (__get_user(mcp, &ucp->uc_regs))
|
||||
return -EFAULT;
|
||||
if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
|
||||
return -EFAULT;
|
||||
#endif
|
||||
restore_sigmask(&set);
|
||||
if (restore_user_regs(regs, mcp, sig))
|
||||
@ -913,13 +916,14 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
|
||||
{
|
||||
struct sig_dbg_op op;
|
||||
int i;
|
||||
unsigned char tmp;
|
||||
unsigned long new_msr = regs->msr;
|
||||
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
|
||||
unsigned long new_dbcr0 = current->thread.dbcr0;
|
||||
#endif
|
||||
|
||||
for (i=0; i<ndbg; i++) {
|
||||
if (__copy_from_user(&op, dbg, sizeof(op)))
|
||||
if (copy_from_user(&op, dbg + i, sizeof(op)))
|
||||
return -EFAULT;
|
||||
switch (op.dbg_type) {
|
||||
case SIG_DBG_SINGLE_STEPPING:
|
||||
@ -964,6 +968,11 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
|
||||
current->thread.dbcr0 = new_dbcr0;
|
||||
#endif
|
||||
|
||||
if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
|
||||
|| __get_user(tmp, (u8 __user *) ctx)
|
||||
|| __get_user(tmp, (u8 __user *) (ctx + 1) - 1))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* If we get a fault copying the context into the kernel's
|
||||
* image of the user's registers, we can't just return -EFAULT
|
||||
|
@ -184,6 +184,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
|
||||
err |= __get_user(v_regs, &sc->v_regs);
|
||||
if (err)
|
||||
return err;
|
||||
if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
|
||||
return -EFAULT;
|
||||
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
|
||||
if (v_regs != 0 && (msr & MSR_VEC) != 0)
|
||||
err |= __copy_from_user(current->thread.vr, v_regs,
|
||||
|
@ -125,14 +125,13 @@ static void __init cell_init_early(void)
|
||||
|
||||
static int __init cell_probe(void)
|
||||
{
|
||||
/* XXX This is temporary, the Cell maintainer will come up with
|
||||
* more appropriate detection logic
|
||||
*/
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
|
||||
of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/prom.h>
|
||||
@ -546,6 +547,7 @@ struct pmf_device {
|
||||
|
||||
static LIST_HEAD(pmf_devices);
|
||||
static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
|
||||
static DEFINE_MUTEX(pmf_irq_mutex);
|
||||
|
||||
static void pmf_release_device(struct kref *kref)
|
||||
{
|
||||
@ -864,15 +866,17 @@ int pmf_register_irq_client(struct device_node *target,
|
||||
|
||||
spin_lock_irqsave(&pmf_lock, flags);
|
||||
func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
|
||||
if (func == NULL) {
|
||||
spin_unlock_irqrestore(&pmf_lock, flags);
|
||||
if (func)
|
||||
func = pmf_get_function(func);
|
||||
spin_unlock_irqrestore(&pmf_lock, flags);
|
||||
if (func == NULL)
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&pmf_irq_mutex);
|
||||
if (list_empty(&func->irq_clients))
|
||||
func->dev->handlers->irq_enable(func);
|
||||
list_add(&client->link, &func->irq_clients);
|
||||
client->func = func;
|
||||
spin_unlock_irqrestore(&pmf_lock, flags);
|
||||
mutex_unlock(&pmf_irq_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -881,16 +885,16 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client);
|
||||
void pmf_unregister_irq_client(struct pmf_irq_client *client)
|
||||
{
|
||||
struct pmf_function *func = client->func;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(func == NULL);
|
||||
|
||||
spin_lock_irqsave(&pmf_lock, flags);
|
||||
mutex_lock(&pmf_irq_mutex);
|
||||
client->func = NULL;
|
||||
list_del(&client->link);
|
||||
if (list_empty(&func->irq_clients))
|
||||
func->dev->handlers->irq_disable(func);
|
||||
spin_unlock_irqrestore(&pmf_lock, flags);
|
||||
mutex_unlock(&pmf_irq_mutex);
|
||||
pmf_put_function(func);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
|
||||
|
||||
|
@ -389,6 +389,7 @@ static int __init pSeries_probe_hypertas(unsigned long node,
|
||||
|
||||
static int __init pSeries_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"device_type", NULL);
|
||||
if (dtype == NULL)
|
||||
@ -396,6 +397,13 @@ static int __init pSeries_probe(void)
|
||||
if (strcmp(dtype, "chrp"))
|
||||
return 0;
|
||||
|
||||
/* Cell blades firmware claims to be chrp while it's not. Until this
|
||||
* is fixed, we need to avoid those here.
|
||||
*/
|
||||
if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
|
||||
of_flat_dt_is_compatible(root, "IBM,CBEA"))
|
||||
return 0;
|
||||
|
||||
DBG("pSeries detected, looking for LPAR capability...\n");
|
||||
|
||||
/* Now try to figure out if we are running on LPAR */
|
||||
|
@ -69,6 +69,17 @@ void __init smp_store_cpu_info(int id)
|
||||
"clock-frequency", 0);
|
||||
cpu_data(id).prom_node = cpu_node;
|
||||
cpu_data(id).mid = cpu_get_hwmid(cpu_node);
|
||||
|
||||
/* this is required to tune the scheduler correctly */
|
||||
/* is it possible to have CPUs with different cache sizes? */
|
||||
if (id == boot_cpu_id) {
|
||||
int cache_line,cache_nlines;
|
||||
cache_line = 0x20;
|
||||
cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
|
||||
cache_nlines = 0x8000;
|
||||
cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
|
||||
max_cache_size = cache_line * cache_nlines;
|
||||
}
|
||||
if (cpu_data(id).mid < 0)
|
||||
panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/threads.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/pstate.h>
|
||||
@ -493,6 +494,35 @@ tlb_fixup_done:
|
||||
call prom_init
|
||||
mov %l7, %o0 ! OpenPROM cif handler
|
||||
|
||||
/* Initialize current_thread_info()->cpu as early as possible.
|
||||
* In order to do that accurately we have to patch up the get_cpuid()
|
||||
* assembler sequences. And that, in turn, requires that we know
|
||||
* if we are on a Starfire box or not. While we're here, patch up
|
||||
* the sun4v sequences as well.
|
||||
*/
|
||||
call check_if_starfire
|
||||
nop
|
||||
call per_cpu_patch
|
||||
nop
|
||||
call sun4v_patch
|
||||
nop
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
call hard_smp_processor_id
|
||||
nop
|
||||
cmp %o0, NR_CPUS
|
||||
blu,pt %xcc, 1f
|
||||
nop
|
||||
call boot_cpu_id_too_large
|
||||
nop
|
||||
/* Not reached... */
|
||||
|
||||
1:
|
||||
#else
|
||||
mov 0, %o0
|
||||
#endif
|
||||
stb %o0, [%g6 + TI_CPU]
|
||||
|
||||
/* Off we go.... */
|
||||
call start_kernel
|
||||
nop
|
||||
|
@ -599,18 +599,128 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = {
|
||||
|
||||
/* SUN4V PCI configuration space accessors. */
|
||||
|
||||
static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
|
||||
struct pdev_entry {
|
||||
struct pdev_entry *next;
|
||||
u32 devhandle;
|
||||
unsigned int bus;
|
||||
unsigned int device;
|
||||
unsigned int func;
|
||||
};
|
||||
|
||||
#define PDEV_HTAB_SIZE 16
|
||||
#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1)
|
||||
static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE];
|
||||
|
||||
static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
|
||||
{
|
||||
if (bus == pbm->pci_first_busno) {
|
||||
if (device == 0 && func == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
unsigned int val;
|
||||
|
||||
val = (devhandle ^ (devhandle >> 4));
|
||||
val ^= bus;
|
||||
val ^= device;
|
||||
val ^= func;
|
||||
|
||||
return val & PDEV_HTAB_MASK;
|
||||
}
|
||||
|
||||
static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
|
||||
{
|
||||
struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL);
|
||||
struct pdev_entry **slot;
|
||||
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
|
||||
p->next = *slot;
|
||||
*slot = p;
|
||||
|
||||
p->devhandle = devhandle;
|
||||
p->bus = bus;
|
||||
p->device = device;
|
||||
p->func = func;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recursively descend into the OBP device tree, rooted at toplevel_node,
|
||||
* looking for a PCI device matching bus and devfn.
|
||||
*/
|
||||
static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
|
||||
{
|
||||
toplevel_node = prom_getchild(toplevel_node);
|
||||
|
||||
while (toplevel_node != 0) {
|
||||
int ret = obp_find(pregs, toplevel_node, bus, devfn);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
|
||||
sizeof(*pregs) * PROMREG_MAX);
|
||||
if (ret == 0 || ret == -1)
|
||||
goto next_sibling;
|
||||
|
||||
if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
|
||||
((pregs[0].phys_hi >> 8) & 0xff) == devfn)
|
||||
break;
|
||||
|
||||
next_sibling:
|
||||
toplevel_node = prom_getsibling(toplevel_node);
|
||||
}
|
||||
|
||||
return toplevel_node;
|
||||
}
|
||||
|
||||
static int pdev_htab_populate(struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct linux_prom_pci_registers pr[PROMREG_MAX];
|
||||
u32 devhandle = pbm->devhandle;
|
||||
unsigned int bus;
|
||||
|
||||
for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) {
|
||||
unsigned int devfn;
|
||||
|
||||
for (devfn = 0; devfn < 256; devfn++) {
|
||||
unsigned int device = PCI_SLOT(devfn);
|
||||
unsigned int func = PCI_FUNC(devfn);
|
||||
|
||||
if (obp_find(pr, pbm->prom_node, bus, devfn)) {
|
||||
int err = pdev_htab_add(devhandle, bus,
|
||||
device, func);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
|
||||
{
|
||||
struct pdev_entry *p;
|
||||
|
||||
p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
|
||||
while (p) {
|
||||
if (p->devhandle == devhandle &&
|
||||
p->bus == bus &&
|
||||
p->device == device &&
|
||||
p->func == func)
|
||||
break;
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
|
||||
{
|
||||
if (bus < pbm->pci_first_busno ||
|
||||
bus > pbm->pci_last_busno)
|
||||
return 1;
|
||||
return 0;
|
||||
return pdev_find(pbm->devhandle, bus, device, func) == NULL;
|
||||
}
|
||||
|
||||
static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||
@ -1063,6 +1173,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
|
||||
|
||||
pci_sun4v_get_bus_range(pbm);
|
||||
pci_sun4v_iommu_init(pbm);
|
||||
|
||||
pdev_htab_populate(pbm);
|
||||
}
|
||||
|
||||
void sun4v_pci_init(int node, char *model_name)
|
||||
|
@ -220,7 +220,7 @@ char reboot_command[COMMAND_LINE_SIZE];
|
||||
|
||||
static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
|
||||
|
||||
static void __init per_cpu_patch(void)
|
||||
void __init per_cpu_patch(void)
|
||||
{
|
||||
struct cpuid_patch_entry *p;
|
||||
unsigned long ver;
|
||||
@ -280,7 +280,7 @@ static void __init per_cpu_patch(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init sun4v_patch(void)
|
||||
void __init sun4v_patch(void)
|
||||
{
|
||||
struct sun4v_1insn_patch_entry *p1;
|
||||
struct sun4v_2insn_patch_entry *p2;
|
||||
@ -315,6 +315,15 @@ static void __init sun4v_patch(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void __init boot_cpu_id_too_large(int cpu)
|
||||
{
|
||||
prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
|
||||
cpu, NR_CPUS);
|
||||
prom_halt();
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/* Initialize PROM console and command line. */
|
||||
@ -332,16 +341,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
conswitchp = &prom_con;
|
||||
#endif
|
||||
|
||||
/* Work out if we are starfire early on */
|
||||
check_if_starfire();
|
||||
|
||||
/* Now we know enough to patch the get_cpuid sequences
|
||||
* used by trap code.
|
||||
*/
|
||||
per_cpu_patch();
|
||||
|
||||
sun4v_patch();
|
||||
|
||||
boot_flags_init(*cmdline_p);
|
||||
|
||||
idprom_init();
|
||||
|
@ -1264,7 +1264,6 @@ void __init smp_tick_init(void)
|
||||
boot_cpu_id = hard_smp_processor_id();
|
||||
current_tick_offset = timer_tick_offset;
|
||||
|
||||
cpu_set(boot_cpu_id, cpu_online_map);
|
||||
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
|
||||
}
|
||||
|
||||
@ -1288,6 +1287,40 @@ int setup_profiling_timer(unsigned int multiplier)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init smp_tune_scheduling(void)
|
||||
{
|
||||
int instance, node;
|
||||
unsigned int def, smallest = ~0U;
|
||||
|
||||
def = ((tlb_type == hypervisor) ?
|
||||
(3 * 1024 * 1024) :
|
||||
(4 * 1024 * 1024));
|
||||
|
||||
instance = 0;
|
||||
while (!cpu_find_by_instance(instance, &node, NULL)) {
|
||||
unsigned int val;
|
||||
|
||||
val = prom_getintdefault(node, "ecache-size", def);
|
||||
if (val < smallest)
|
||||
smallest = val;
|
||||
|
||||
instance++;
|
||||
}
|
||||
|
||||
/* Any value less than 256K is nonsense. */
|
||||
if (smallest < (256U * 1024U))
|
||||
smallest = 256 * 1024;
|
||||
|
||||
max_cache_size = smallest;
|
||||
|
||||
if (smallest < 1U * 1024U * 1024U)
|
||||
printk(KERN_INFO "Using max_cache_size of %uKB\n",
|
||||
smallest / 1024U);
|
||||
else
|
||||
printk(KERN_INFO "Using max_cache_size of %uMB\n",
|
||||
smallest / 1024U / 1024U);
|
||||
}
|
||||
|
||||
/* Constrain the number of cpus to max_cpus. */
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
@ -1323,6 +1356,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
}
|
||||
|
||||
smp_store_cpu_info(boot_cpu_id);
|
||||
smp_tune_scheduling();
|
||||
}
|
||||
|
||||
/* Set this up early so that things like the scheduler can init
|
||||
@ -1345,18 +1379,6 @@ void __init smp_setup_cpu_possible_map(void)
|
||||
|
||||
void __devinit smp_prepare_boot_cpu(void)
|
||||
{
|
||||
int cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu >= NR_CPUS) {
|
||||
prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
current_thread_info()->cpu = cpu;
|
||||
__local_per_cpu_offset = __per_cpu_offset(cpu);
|
||||
|
||||
cpu_set(smp_processor_id(), cpu_online_map);
|
||||
cpu_set(smp_processor_id(), phys_cpu_present_map);
|
||||
}
|
||||
|
||||
int __devinit __cpu_up(unsigned int cpu)
|
||||
@ -1433,4 +1455,7 @@ void __init setup_per_cpu_areas(void)
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++, ptr += size)
|
||||
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
||||
|
||||
/* Setup %g5 for the boot cpu. */
|
||||
__local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
|
||||
}
|
||||
|
@ -1797,7 +1797,9 @@ static const char *sun4v_err_type_to_str(u32 type)
|
||||
};
|
||||
}
|
||||
|
||||
static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
|
||||
extern void __show_regs(struct pt_regs * regs);
|
||||
|
||||
static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
@ -1830,6 +1832,8 @@ static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *
|
||||
pfx,
|
||||
ent->err_raddr, ent->err_size, ent->err_cpu);
|
||||
|
||||
__show_regs(regs);
|
||||
|
||||
if ((cnt = atomic_read(ocnt)) != 0) {
|
||||
atomic_set(ocnt, 0);
|
||||
wmb();
|
||||
@ -1862,7 +1866,7 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
|
||||
|
||||
put_cpu();
|
||||
|
||||
sun4v_log_error(&local_copy, cpu,
|
||||
sun4v_log_error(regs, &local_copy, cpu,
|
||||
KERN_ERR "RESUMABLE ERROR",
|
||||
&sun4v_resum_oflow_cnt);
|
||||
}
|
||||
@ -1910,7 +1914,7 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
|
||||
}
|
||||
#endif
|
||||
|
||||
sun4v_log_error(&local_copy, cpu,
|
||||
sun4v_log_error(regs, &local_copy, cpu,
|
||||
KERN_EMERG "NON-RESUMABLE ERROR",
|
||||
&sun4v_nonresum_oflow_cnt);
|
||||
|
||||
@ -2200,7 +2204,6 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
|
||||
void die_if_kernel(char *str, struct pt_regs *regs)
|
||||
{
|
||||
static int die_counter;
|
||||
extern void __show_regs(struct pt_regs * regs);
|
||||
extern void smp_report_regs(void);
|
||||
int count = 0;
|
||||
|
||||
|
@ -165,8 +165,9 @@ csum_partial_end_cruft:
|
||||
sll %g1, 8, %g1
|
||||
or %o5, %g1, %o4
|
||||
|
||||
1: add %o2, %o4, %o2
|
||||
1: addcc %o2, %o4, %o2
|
||||
addc %g0, %o2, %o2
|
||||
|
||||
csum_partial_finish:
|
||||
retl
|
||||
mov %o2, %o0
|
||||
srl %o2, 0, %o0
|
||||
|
@ -221,11 +221,12 @@ FUNC_NAME: /* %o0=src, %o1=dst, %o2=len, %o3=sum */
|
||||
sll %g1, 8, %g1
|
||||
or %o5, %g1, %o4
|
||||
|
||||
1: add %o3, %o4, %o3
|
||||
1: addcc %o3, %o4, %o3
|
||||
addc %g0, %o3, %o3
|
||||
|
||||
70:
|
||||
retl
|
||||
mov %o3, %o0
|
||||
srl %o3, 0, %o0
|
||||
|
||||
95: mov 0, GLOBAL_SPARE
|
||||
brlez,pn %o2, 4f
|
||||
|
@ -33,5 +33,9 @@ include $(srctree)/arch/i386/Makefile.cpu
|
||||
# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
|
||||
cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
|
||||
|
||||
# Prevent sprintf in nfsd from being converted to strcpy and resulting in
|
||||
# an unresolved reference.
|
||||
cflags-y += -ffreestanding
|
||||
|
||||
CFLAGS += $(cflags-y)
|
||||
USER_CFLAGS += $(cflags-y)
|
||||
|
@ -120,20 +120,11 @@ extern int is_syscall(unsigned long addr);
|
||||
extern void free_irq(unsigned int, void *);
|
||||
extern int cpu(void);
|
||||
|
||||
extern void time_init_kern(void);
|
||||
|
||||
/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
|
||||
extern int __cant_sleep(void);
|
||||
extern void segv_handler(int sig, union uml_pt_regs *regs);
|
||||
extern void sigio_handler(int sig, union uml_pt_regs *regs);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
|
@ -84,6 +84,16 @@ void timer_irq(union uml_pt_regs *regs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void time_init_kern(void)
|
||||
{
|
||||
unsigned long long nsecs;
|
||||
|
||||
nsecs = os_nsecs();
|
||||
set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
|
||||
-nsecs % BILLION);
|
||||
}
|
||||
|
||||
void do_boot_timer_handler(struct sigcontext * sc)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
@ -59,7 +59,7 @@ static __init void do_uml_initcalls(void)
|
||||
initcall_t *call;
|
||||
|
||||
call = &__uml_initcall_start;
|
||||
while (call < &__uml_initcall_end){;
|
||||
while (call < &__uml_initcall_end){
|
||||
(*call)();
|
||||
call++;
|
||||
}
|
||||
|
@ -81,20 +81,12 @@ void uml_idle_timer(void)
|
||||
set_interval(ITIMER_REAL);
|
||||
}
|
||||
|
||||
extern void ktime_get_ts(struct timespec *ts);
|
||||
#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
|
||||
|
||||
void time_init(void)
|
||||
{
|
||||
struct timespec now;
|
||||
|
||||
if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
|
||||
panic("Couldn't set SIGVTALRM handler");
|
||||
set_interval(ITIMER_VIRTUAL);
|
||||
|
||||
do_posix_clock_monotonic_gettime(&now);
|
||||
wall_to_monotonic.tv_sec = -now.tv_sec;
|
||||
wall_to_monotonic.tv_nsec = -now.tv_nsec;
|
||||
time_init_kern();
|
||||
}
|
||||
|
||||
unsigned long long os_nsecs(void)
|
||||
|
@ -99,11 +99,12 @@ long sys_ipc (uint call, int first, int second,
|
||||
|
||||
switch (call) {
|
||||
case SEMOP:
|
||||
return sys_semtimedop(first, (struct sembuf *) ptr, second,
|
||||
NULL);
|
||||
return sys_semtimedop(first, (struct sembuf __user *) ptr,
|
||||
second, NULL);
|
||||
case SEMTIMEDOP:
|
||||
return sys_semtimedop(first, (struct sembuf *) ptr, second,
|
||||
(const struct timespec *) fifth);
|
||||
return sys_semtimedop(first, (struct sembuf __user *) ptr,
|
||||
second,
|
||||
(const struct timespec __user *) fifth);
|
||||
case SEMGET:
|
||||
return sys_semget (first, second, third);
|
||||
case SEMCTL: {
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "skas.h"
|
||||
|
||||
static int copy_sc_from_user_skas(struct pt_regs *regs,
|
||||
struct sigcontext *from)
|
||||
struct sigcontext __user *from)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@ -54,7 +54,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
|
||||
return(err);
|
||||
}
|
||||
|
||||
int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
|
||||
int copy_sc_to_user_skas(struct sigcontext __user *to,
|
||||
struct _fpstate __user *to_fp,
|
||||
struct pt_regs *regs, unsigned long mask,
|
||||
unsigned long sp)
|
||||
{
|
||||
@ -106,10 +107,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MODE_TT
|
||||
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
|
||||
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
|
||||
int fpsize)
|
||||
{
|
||||
struct _fpstate *to_fp, *from_fp;
|
||||
struct _fpstate *to_fp;
|
||||
struct _fpstate __user *from_fp;
|
||||
unsigned long sigs;
|
||||
int err;
|
||||
|
||||
@ -124,13 +126,14 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
|
||||
return(err);
|
||||
}
|
||||
|
||||
int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
|
||||
int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
|
||||
struct sigcontext *from, int fpsize, unsigned long sp)
|
||||
{
|
||||
struct _fpstate *to_fp, *from_fp;
|
||||
struct _fpstate __user *to_fp;
|
||||
struct _fpstate *from_fp;
|
||||
int err;
|
||||
|
||||
to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
|
||||
to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
|
||||
from_fp = from->fpstate;
|
||||
err = copy_to_user(to, from, sizeof(*to));
|
||||
/* The SP in the sigcontext is the updated one for the signal
|
||||
@ -158,7 +161,8 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
|
||||
static int copy_sc_to_user(struct sigcontext __user *to,
|
||||
struct _fpstate __user *fp,
|
||||
struct pt_regs *from, unsigned long mask,
|
||||
unsigned long sp)
|
||||
{
|
||||
@ -169,7 +173,7 @@ static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
|
||||
|
||||
struct rt_sigframe
|
||||
{
|
||||
char *pretcode;
|
||||
char __user *pretcode;
|
||||
struct ucontext uc;
|
||||
struct siginfo info;
|
||||
};
|
||||
@ -188,7 +192,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
|
||||
frame = (struct rt_sigframe __user *)
|
||||
round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
|
||||
frame = (struct rt_sigframe *) ((unsigned long) frame - 128);
|
||||
frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
|
||||
goto out;
|
||||
|
@ -45,7 +45,7 @@ static long arch_prctl_tt(int code, unsigned long addr)
|
||||
case ARCH_GET_GS:
|
||||
ret = arch_prctl(code, (unsigned long) &tmp);
|
||||
if(!ret)
|
||||
ret = put_user(tmp, &addr);
|
||||
ret = put_user(tmp, (long __user *)addr);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -271,6 +271,18 @@ __setup("enable_8254_timer", setup_enable_8254_timer);
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
static int nvidia_hpet_detected __initdata;
|
||||
|
||||
static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
|
||||
{
|
||||
nvidia_hpet_detected = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
|
||||
off. Check for an Nvidia or VIA PCI bridge and turn it off.
|
||||
Use pci direct infrastructure because this runs before the PCI subsystem.
|
||||
@ -317,11 +329,19 @@ void __init check_ioapic(void)
|
||||
return;
|
||||
case PCI_VENDOR_ID_NVIDIA:
|
||||
#ifdef CONFIG_ACPI
|
||||
/* All timer overrides on Nvidia
|
||||
seem to be wrong. Skip them. */
|
||||
acpi_skip_timer_override = 1;
|
||||
printk(KERN_INFO
|
||||
"Nvidia board detected. Ignoring ACPI timer override.\n");
|
||||
/*
|
||||
* All timer overrides on Nvidia are
|
||||
* wrong unless HPET is enabled.
|
||||
*/
|
||||
nvidia_hpet_detected = 0;
|
||||
acpi_table_parse(ACPI_HPET,
|
||||
nvidia_hpet_check);
|
||||
if (nvidia_hpet_detected == 0) {
|
||||
acpi_skip_timer_override = 1;
|
||||
printk(KERN_INFO "Nvidia board "
|
||||
"detected. Ignoring ACPI "
|
||||
"timer override.\n");
|
||||
}
|
||||
#endif
|
||||
/* RED-PEN skip them on mptables too? */
|
||||
return;
|
||||
|
@ -1648,17 +1648,17 @@ static void as_exit_queue(elevator_t *e)
|
||||
* initialize elevator private data (as_data), and alloc a arq for
|
||||
* each request on the free lists
|
||||
*/
|
||||
static int as_init_queue(request_queue_t *q, elevator_t *e)
|
||||
static void *as_init_queue(request_queue_t *q, elevator_t *e)
|
||||
{
|
||||
struct as_data *ad;
|
||||
int i;
|
||||
|
||||
if (!arq_pool)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
|
||||
if (!ad)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
memset(ad, 0, sizeof(*ad));
|
||||
|
||||
ad->q = q; /* Identify what queue the data belongs to */
|
||||
@ -1667,7 +1667,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
|
||||
GFP_KERNEL, q->node);
|
||||
if (!ad->hash) {
|
||||
kfree(ad);
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
|
||||
@ -1675,7 +1675,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
|
||||
if (!ad->arq_pool) {
|
||||
kfree(ad->hash);
|
||||
kfree(ad);
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* anticipatory scheduling helpers */
|
||||
@ -1696,14 +1696,13 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
|
||||
ad->antic_expire = default_antic_expire;
|
||||
ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
|
||||
ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
|
||||
e->elevator_data = ad;
|
||||
|
||||
ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
|
||||
ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
|
||||
if (ad->write_batch_count < 2)
|
||||
ad->write_batch_count = 2;
|
||||
|
||||
return 0;
|
||||
return ad;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -133,6 +133,7 @@ struct cfq_data {
|
||||
mempool_t *crq_pool;
|
||||
|
||||
int rq_in_driver;
|
||||
int hw_tag;
|
||||
|
||||
/*
|
||||
* schedule slice state info
|
||||
@ -500,10 +501,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
|
||||
|
||||
/*
|
||||
* if queue was preempted, just add to front to be fair. busy_rr
|
||||
* isn't sorted.
|
||||
* isn't sorted, but insert at the back for fairness.
|
||||
*/
|
||||
if (preempted || list == &cfqd->busy_rr) {
|
||||
list_add(&cfqq->cfq_list, list);
|
||||
if (preempted)
|
||||
list = list->prev;
|
||||
|
||||
list_add_tail(&cfqq->cfq_list, list);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -664,6 +668,15 @@ static void cfq_activate_request(request_queue_t *q, struct request *rq)
|
||||
struct cfq_data *cfqd = q->elevator->elevator_data;
|
||||
|
||||
cfqd->rq_in_driver++;
|
||||
|
||||
/*
|
||||
* If the depth is larger 1, it really could be queueing. But lets
|
||||
* make the mark a little higher - idling could still be good for
|
||||
* low queueing, and a low queueing number could also just indicate
|
||||
* a SCSI mid layer like behaviour where limit+1 is often seen.
|
||||
*/
|
||||
if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
|
||||
cfqd->hw_tag = 1;
|
||||
}
|
||||
|
||||
static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
|
||||
@ -878,6 +891,13 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
|
||||
if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
|
||||
cfqq = list_entry_cfqq(cfqd->cur_rr.next);
|
||||
|
||||
/*
|
||||
* If no new queues are available, check if the busy list has some
|
||||
* before falling back to idle io.
|
||||
*/
|
||||
if (!cfqq && !list_empty(&cfqd->busy_rr))
|
||||
cfqq = list_entry_cfqq(cfqd->busy_rr.next);
|
||||
|
||||
/*
|
||||
* if we have idle queues and no rt or be queues had pending
|
||||
* requests, either allow immediate service if the grace period
|
||||
@ -1458,7 +1478,8 @@ retry:
|
||||
* set ->slice_left to allow preemption for a new process
|
||||
*/
|
||||
cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
|
||||
cfq_mark_cfqq_idle_window(cfqq);
|
||||
if (!cfqd->hw_tag)
|
||||
cfq_mark_cfqq_idle_window(cfqq);
|
||||
cfq_mark_cfqq_prio_changed(cfqq);
|
||||
cfq_init_prio_data(cfqq);
|
||||
}
|
||||
@ -1649,7 +1670,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
||||
{
|
||||
int enable_idle = cfq_cfqq_idle_window(cfqq);
|
||||
|
||||
if (!cic->ioc->task || !cfqd->cfq_slice_idle)
|
||||
if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag)
|
||||
enable_idle = 0;
|
||||
else if (sample_valid(cic->ttime_samples)) {
|
||||
if (cic->ttime_mean > cfqd->cfq_slice_idle)
|
||||
@ -1740,14 +1761,24 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
||||
|
||||
cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
|
||||
|
||||
cic = crq->io_context;
|
||||
|
||||
/*
|
||||
* we never wait for an async request and we don't allow preemption
|
||||
* of an async request. so just return early
|
||||
*/
|
||||
if (!cfq_crq_is_sync(crq))
|
||||
if (!cfq_crq_is_sync(crq)) {
|
||||
/*
|
||||
* sync process issued an async request, if it's waiting
|
||||
* then expire it and kick rq handling.
|
||||
*/
|
||||
if (cic == cfqd->active_cic &&
|
||||
del_timer(&cfqd->idle_slice_timer)) {
|
||||
cfq_slice_expired(cfqd, 0);
|
||||
cfq_start_queueing(cfqd, cfqq);
|
||||
}
|
||||
return;
|
||||
|
||||
cic = crq->io_context;
|
||||
}
|
||||
|
||||
cfq_update_io_thinktime(cfqd, cic);
|
||||
cfq_update_io_seektime(cfqd, cic, crq);
|
||||
@ -2165,10 +2196,9 @@ static void cfq_idle_class_timer(unsigned long data)
|
||||
* race with a non-idle queue, reset timer
|
||||
*/
|
||||
end = cfqd->last_end_request + CFQ_IDLE_GRACE;
|
||||
if (!time_after_eq(jiffies, end)) {
|
||||
cfqd->idle_class_timer.expires = end;
|
||||
add_timer(&cfqd->idle_class_timer);
|
||||
} else
|
||||
if (!time_after_eq(jiffies, end))
|
||||
mod_timer(&cfqd->idle_class_timer, end);
|
||||
else
|
||||
cfq_schedule_dispatch(cfqd);
|
||||
|
||||
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
|
||||
@ -2221,14 +2251,14 @@ static void cfq_exit_queue(elevator_t *e)
|
||||
kfree(cfqd);
|
||||
}
|
||||
|
||||
static int cfq_init_queue(request_queue_t *q, elevator_t *e)
|
||||
static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
|
||||
{
|
||||
struct cfq_data *cfqd;
|
||||
int i;
|
||||
|
||||
cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
|
||||
if (!cfqd)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
memset(cfqd, 0, sizeof(*cfqd));
|
||||
|
||||
@ -2258,8 +2288,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
|
||||
for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
|
||||
INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
|
||||
|
||||
e->elevator_data = cfqd;
|
||||
|
||||
cfqd->queue = q;
|
||||
|
||||
cfqd->max_queued = q->nr_requests / 4;
|
||||
@ -2286,14 +2314,14 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
|
||||
cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
|
||||
cfqd->cfq_slice_idle = cfq_slice_idle;
|
||||
|
||||
return 0;
|
||||
return cfqd;
|
||||
out_crqpool:
|
||||
kfree(cfqd->cfq_hash);
|
||||
out_cfqhash:
|
||||
kfree(cfqd->crq_hash);
|
||||
out_crqhash:
|
||||
kfree(cfqd);
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cfq_slab_kill(void)
|
||||
|
@ -613,24 +613,24 @@ static void deadline_exit_queue(elevator_t *e)
|
||||
* initialize elevator private data (deadline_data), and alloc a drq for
|
||||
* each request on the free lists
|
||||
*/
|
||||
static int deadline_init_queue(request_queue_t *q, elevator_t *e)
|
||||
static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
|
||||
{
|
||||
struct deadline_data *dd;
|
||||
int i;
|
||||
|
||||
if (!drq_pool)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
|
||||
if (!dd)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
memset(dd, 0, sizeof(*dd));
|
||||
|
||||
dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
|
||||
GFP_KERNEL, q->node);
|
||||
if (!dd->hash) {
|
||||
kfree(dd);
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
|
||||
@ -638,7 +638,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
|
||||
if (!dd->drq_pool) {
|
||||
kfree(dd->hash);
|
||||
kfree(dd);
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < DL_HASH_ENTRIES; i++)
|
||||
@ -653,8 +653,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
|
||||
dd->writes_starved = writes_starved;
|
||||
dd->front_merges = 1;
|
||||
dd->fifo_batch = fifo_batch;
|
||||
e->elevator_data = dd;
|
||||
return 0;
|
||||
return dd;
|
||||
}
|
||||
|
||||
static void deadline_put_request(request_queue_t *q, struct request *rq)
|
||||
|
@ -121,16 +121,16 @@ static struct elevator_type *elevator_get(const char *name)
|
||||
return e;
|
||||
}
|
||||
|
||||
static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
|
||||
static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
|
||||
{
|
||||
int ret = 0;
|
||||
return eq->ops->elevator_init_fn(q, eq);
|
||||
}
|
||||
|
||||
static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
|
||||
void *data)
|
||||
{
|
||||
q->elevator = eq;
|
||||
|
||||
if (eq->ops->elevator_init_fn)
|
||||
ret = eq->ops->elevator_init_fn(q, eq);
|
||||
|
||||
return ret;
|
||||
eq->elevator_data = data;
|
||||
}
|
||||
|
||||
static char chosen_elevator[16];
|
||||
@ -181,6 +181,7 @@ int elevator_init(request_queue_t *q, char *name)
|
||||
struct elevator_type *e = NULL;
|
||||
struct elevator_queue *eq;
|
||||
int ret = 0;
|
||||
void *data;
|
||||
|
||||
INIT_LIST_HEAD(&q->queue_head);
|
||||
q->last_merge = NULL;
|
||||
@ -202,10 +203,13 @@ int elevator_init(request_queue_t *q, char *name)
|
||||
if (!eq)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = elevator_attach(q, eq);
|
||||
if (ret)
|
||||
data = elevator_init_queue(q, eq);
|
||||
if (!data) {
|
||||
kobject_put(&eq->kobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
elevator_attach(q, eq, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -722,13 +726,16 @@ int elv_register_queue(struct request_queue *q)
|
||||
return error;
|
||||
}
|
||||
|
||||
static void __elv_unregister_queue(elevator_t *e)
|
||||
{
|
||||
kobject_uevent(&e->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&e->kobj);
|
||||
}
|
||||
|
||||
void elv_unregister_queue(struct request_queue *q)
|
||||
{
|
||||
if (q) {
|
||||
elevator_t *e = q->elevator;
|
||||
kobject_uevent(&e->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&e->kobj);
|
||||
}
|
||||
if (q)
|
||||
__elv_unregister_queue(q->elevator);
|
||||
}
|
||||
|
||||
int elv_register(struct elevator_type *e)
|
||||
@ -780,6 +787,7 @@ EXPORT_SYMBOL_GPL(elv_unregister);
|
||||
static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
|
||||
{
|
||||
elevator_t *old_elevator, *e;
|
||||
void *data;
|
||||
|
||||
/*
|
||||
* Allocate new elevator
|
||||
@ -788,6 +796,12 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
data = elevator_init_queue(q, e);
|
||||
if (!data) {
|
||||
kobject_put(&e->kobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on BYPASS and drain all requests w/ elevator private data
|
||||
*/
|
||||
@ -806,19 +820,19 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
|
||||
elv_drain_elevator(q);
|
||||
}
|
||||
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
/*
|
||||
* unregister old elevator data
|
||||
* Remember old elevator.
|
||||
*/
|
||||
elv_unregister_queue(q);
|
||||
old_elevator = q->elevator;
|
||||
|
||||
/*
|
||||
* attach and start new elevator
|
||||
*/
|
||||
if (elevator_attach(q, e))
|
||||
goto fail;
|
||||
elevator_attach(q, e, data);
|
||||
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
__elv_unregister_queue(old_elevator);
|
||||
|
||||
if (elv_register_queue(q))
|
||||
goto fail_register;
|
||||
@ -837,7 +851,6 @@ fail_register:
|
||||
*/
|
||||
elevator_exit(e);
|
||||
e = NULL;
|
||||
fail:
|
||||
q->elevator = old_elevator;
|
||||
elv_register_queue(q);
|
||||
clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
|
||||
|
@ -65,16 +65,15 @@ noop_latter_request(request_queue_t *q, struct request *rq)
|
||||
return list_entry(rq->queuelist.next, struct request, queuelist);
|
||||
}
|
||||
|
||||
static int noop_init_queue(request_queue_t *q, elevator_t *e)
|
||||
static void *noop_init_queue(request_queue_t *q, elevator_t *e)
|
||||
{
|
||||
struct noop_data *nd;
|
||||
|
||||
nd = kmalloc(sizeof(*nd), GFP_KERNEL);
|
||||
if (!nd)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
INIT_LIST_HEAD(&nd->queue);
|
||||
e->elevator_data = nd;
|
||||
return 0;
|
||||
return nd;
|
||||
}
|
||||
|
||||
static void noop_exit_queue(elevator_t *e)
|
||||
|
@ -577,6 +577,8 @@ acpi_processor_register_performance(struct acpi_processor_performance
|
||||
return_VALUE(-EBUSY);
|
||||
}
|
||||
|
||||
WARN_ON(!performance);
|
||||
|
||||
pr->performance = performance;
|
||||
|
||||
if (acpi_processor_get_performance_info(pr)) {
|
||||
@ -609,7 +611,8 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
kfree(pr->performance->states);
|
||||
if (pr->performance)
|
||||
kfree(pr->performance->states);
|
||||
pr->performance = NULL;
|
||||
|
||||
acpi_cpufreq_remove_file(pr);
|
||||
|
@ -41,9 +41,9 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
||||
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
|
||||
obj-$(CONFIG_SX) += sx.o generic_serial.o
|
||||
obj-$(CONFIG_RIO) += rio/ generic_serial.o
|
||||
obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
|
||||
obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
|
||||
obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
|
||||
obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
|
||||
obj-$(CONFIG_RAW_DRIVER) += raw.o
|
||||
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
|
||||
obj-$(CONFIG_MMTIMER) += mmtimer.o
|
||||
|
@ -1384,8 +1384,10 @@ do_it_again:
|
||||
* longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
|
||||
* we won't get any more characters.
|
||||
*/
|
||||
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
|
||||
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
|
||||
n_tty_set_room(tty);
|
||||
check_unthrottle(tty);
|
||||
}
|
||||
|
||||
if (b - buf >= minimum)
|
||||
break;
|
||||
|
@ -149,7 +149,7 @@ struct cm4000_dev {
|
||||
#define ZERO_DEV(dev) \
|
||||
memset(&dev->atr_csum,0, \
|
||||
sizeof(struct cm4000_dev) - \
|
||||
/*link*/ sizeof(struct pcmcia_device) - \
|
||||
/*link*/ sizeof(struct pcmcia_device *) - \
|
||||
/*node*/ sizeof(dev_node_t) - \
|
||||
/*atr*/ MAX_ATR*sizeof(char) - \
|
||||
/*rbuf*/ 512*sizeof(char) - \
|
||||
|
@ -845,7 +845,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
|
||||
&sbp2_highlevel, ud->ne->host, &sbp2_ops,
|
||||
sizeof(struct sbp2_status_block), sizeof(quadlet_t),
|
||||
0x010000000000ULL, CSR1212_ALL_SPACE_END);
|
||||
if (!scsi_id->status_fifo_addr) {
|
||||
if (scsi_id->status_fifo_addr == ~0ULL) {
|
||||
SBP2_ERR("failed to allocate status FIFO address range");
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
@ -275,6 +275,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
++priv->tx_tail;
|
||||
if (netif_queue_stopped(dev) &&
|
||||
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) &&
|
||||
priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
|
||||
netif_wake_queue(dev);
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
|
@ -1605,6 +1605,21 @@ mpt_resume(struct pci_dev *pdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
|
||||
{
|
||||
if ((MptDriverClass[index] == MPTSPI_DRIVER &&
|
||||
ioc->bus_type != SPI) ||
|
||||
(MptDriverClass[index] == MPTFC_DRIVER &&
|
||||
ioc->bus_type != FC) ||
|
||||
(MptDriverClass[index] == MPTSAS_DRIVER &&
|
||||
ioc->bus_type != SAS))
|
||||
/* make sure we only call the relevant reset handler
|
||||
* for the bus */
|
||||
return 0;
|
||||
return (MptResetHandlers[index])(ioc, reset_phase);
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* mpt_do_ioc_recovery - Initialize or recover MPT adapter.
|
||||
@ -1885,14 +1900,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
|
||||
if ((ret == 0) && MptResetHandlers[ii]) {
|
||||
dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
|
||||
ioc->name, ii));
|
||||
rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
|
||||
rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
|
||||
handlers++;
|
||||
}
|
||||
|
||||
if (alt_ioc_ready && MptResetHandlers[ii]) {
|
||||
drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
|
||||
ioc->name, ioc->alt_ioc->name, ii));
|
||||
rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
|
||||
rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
|
||||
handlers++;
|
||||
}
|
||||
}
|
||||
@ -3267,11 +3282,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
||||
if (MptResetHandlers[ii]) {
|
||||
dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
|
||||
ioc->name, ii));
|
||||
r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
|
||||
r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
|
||||
if (ioc->alt_ioc) {
|
||||
dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
|
||||
ioc->name, ioc->alt_ioc->name, ii));
|
||||
r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
|
||||
r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5706,11 +5721,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
|
||||
if (MptResetHandlers[ii]) {
|
||||
dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
|
||||
ioc->name, ii));
|
||||
r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
|
||||
r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
|
||||
if (ioc->alt_ioc) {
|
||||
dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
|
||||
ioc->name, ioc->alt_ioc->name, ii));
|
||||
r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
|
||||
r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -831,6 +831,7 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/*
|
||||
* spi module resume handler
|
||||
*/
|
||||
@ -846,6 +847,7 @@ mptspi_resume(struct pci_dev *pdev)
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
|
@ -55,6 +55,7 @@ struct i2o_exec_wait {
|
||||
u32 m; /* message id */
|
||||
struct i2o_message *msg; /* pointer to the reply message */
|
||||
struct list_head list; /* node in global wait list */
|
||||
spinlock_t lock; /* lock before modifying */
|
||||
};
|
||||
|
||||
/* Work struct needed to handle LCT NOTIFY replies */
|
||||
@ -87,6 +88,7 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&wait->list);
|
||||
spin_lock_init(&wait->lock);
|
||||
|
||||
return wait;
|
||||
};
|
||||
@ -125,6 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
|
||||
DECLARE_WAIT_QUEUE_HEAD(wq);
|
||||
struct i2o_exec_wait *wait;
|
||||
static u32 tcntxt = 0x80000000;
|
||||
long flags;
|
||||
int rc = 0;
|
||||
|
||||
wait = i2o_exec_wait_alloc();
|
||||
@ -146,33 +149,28 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
|
||||
wait->tcntxt = tcntxt++;
|
||||
msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
|
||||
|
||||
wait->wq = &wq;
|
||||
/*
|
||||
* we add elements to the head, because if a entry in the list will
|
||||
* never be removed, we have to iterate over it every time
|
||||
*/
|
||||
list_add(&wait->list, &i2o_exec_wait_list);
|
||||
|
||||
/*
|
||||
* Post the message to the controller. At some point later it will
|
||||
* return. If we time out before it returns then complete will be zero.
|
||||
*/
|
||||
i2o_msg_post(c, msg);
|
||||
|
||||
if (!wait->complete) {
|
||||
wait->wq = &wq;
|
||||
/*
|
||||
* we add elements add the head, because if a entry in the list
|
||||
* will never be removed, we have to iterate over it every time
|
||||
*/
|
||||
list_add(&wait->list, &i2o_exec_wait_list);
|
||||
wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
|
||||
|
||||
wait_event_interruptible_timeout(wq, wait->complete,
|
||||
timeout * HZ);
|
||||
spin_lock_irqsave(&wait->lock, flags);
|
||||
|
||||
wait->wq = NULL;
|
||||
}
|
||||
wait->wq = NULL;
|
||||
|
||||
barrier();
|
||||
|
||||
if (wait->complete) {
|
||||
if (wait->complete)
|
||||
rc = le32_to_cpu(wait->msg->body[0]) >> 24;
|
||||
i2o_flush_reply(c, wait->m);
|
||||
i2o_exec_wait_free(wait);
|
||||
} else {
|
||||
else {
|
||||
/*
|
||||
* We cannot remove it now. This is important. When it does
|
||||
* terminate (which it must do if the controller has not
|
||||
@ -186,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
|
||||
rc = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&wait->lock, flags);
|
||||
|
||||
if (rc != -ETIMEDOUT) {
|
||||
i2o_flush_reply(c, wait->m);
|
||||
i2o_exec_wait_free(wait);
|
||||
}
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
@ -213,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
|
||||
{
|
||||
struct i2o_exec_wait *wait, *tmp;
|
||||
unsigned long flags;
|
||||
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||
int rc = 1;
|
||||
|
||||
/*
|
||||
@ -223,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
|
||||
* already expired. Not much we can do about that except log it for
|
||||
* debug purposes, increase timeout, and recompile.
|
||||
*/
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
|
||||
if (wait->tcntxt == context) {
|
||||
list_del(&wait->list);
|
||||
spin_lock_irqsave(&wait->lock, flags);
|
||||
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
list_del(&wait->list);
|
||||
|
||||
wait->m = m;
|
||||
wait->msg = msg;
|
||||
wait->complete = 1;
|
||||
|
||||
barrier();
|
||||
|
||||
if (wait->wq) {
|
||||
wake_up_interruptible(wait->wq);
|
||||
if (wait->wq)
|
||||
rc = 0;
|
||||
} else {
|
||||
else
|
||||
rc = -1;
|
||||
|
||||
spin_unlock_irqrestore(&wait->lock, flags);
|
||||
|
||||
if (rc) {
|
||||
struct device *dev;
|
||||
|
||||
dev = &c->pdev->dev;
|
||||
@ -248,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
|
||||
c->name);
|
||||
i2o_dma_free(dev, &wait->dma);
|
||||
i2o_exec_wait_free(wait);
|
||||
rc = -1;
|
||||
}
|
||||
} else
|
||||
wake_up_interruptible(wait->wq);
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
|
||||
osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
|
||||
context);
|
||||
|
||||
@ -322,14 +325,9 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
|
||||
static int i2o_exec_probe(struct device *dev)
|
||||
{
|
||||
struct i2o_device *i2o_dev = to_i2o_device(dev);
|
||||
struct i2o_controller *c = i2o_dev->iop;
|
||||
|
||||
i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
|
||||
|
||||
c->exec = i2o_dev;
|
||||
|
||||
i2o_exec_lct_notify(c, c->lct->change_ind + 1);
|
||||
|
||||
device_create_file(dev, &dev_attr_vendor_id);
|
||||
device_create_file(dev, &dev_attr_product_id);
|
||||
|
||||
@ -523,6 +521,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
|
||||
struct device *dev;
|
||||
struct i2o_message *msg;
|
||||
|
||||
down(&c->lct_lock);
|
||||
|
||||
dev = &c->pdev->dev;
|
||||
|
||||
if (i2o_dma_realloc
|
||||
@ -545,6 +545,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
|
||||
|
||||
i2o_msg_post(c, msg);
|
||||
|
||||
up(&c->lct_lock);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controller *c)
|
||||
|
||||
/* Ask the IOP to switch to RESET state */
|
||||
i2o_iop_reset(c);
|
||||
|
||||
put_device(&c->device);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(void)
|
||||
|
||||
snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
|
||||
if (i2o_pool_alloc
|
||||
(&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
|
||||
(&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
|
||||
I2O_MSG_INPOOL_MIN)) {
|
||||
kfree(c);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -84,7 +84,7 @@ config MMC_WBSD
|
||||
|
||||
config MMC_AU1X
|
||||
tristate "Alchemy AU1XX0 MMC Card Interface support"
|
||||
depends on SOC_AU1X00 && MMC
|
||||
depends on MMC && SOC_AU1200
|
||||
help
|
||||
This selects the AMD Alchemy(R) Multimedia card interface.
|
||||
If you have a Alchemy platform with a MMC slot, say Y or M here.
|
||||
|
@ -870,13 +870,16 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
|
||||
*data = 0;
|
||||
|
||||
/* Hook up test interrupt handler just for this test */
|
||||
if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
|
||||
if (!request_irq(irq, &e1000_test_intr, SA_PROBEIRQ, netdev->name,
|
||||
netdev)) {
|
||||
shared_int = FALSE;
|
||||
} else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
|
||||
netdev->name, netdev)){
|
||||
*data = 1;
|
||||
return -1;
|
||||
}
|
||||
DPRINTK(PROBE,INFO, "testing %s interrupt\n",
|
||||
(shared_int ? "shared" : "unshared"));
|
||||
|
||||
/* Disable all the interrupts */
|
||||
E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
|
||||
|
@ -3519,7 +3519,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
|
||||
while (rx_desc->status & E1000_RXD_STAT_DD) {
|
||||
struct sk_buff *skb, *next_skb;
|
||||
struct sk_buff *skb;
|
||||
u8 status;
|
||||
#ifdef CONFIG_E1000_NAPI
|
||||
if (*work_done >= work_to_do)
|
||||
@ -3537,8 +3537,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
prefetch(next_rxd);
|
||||
|
||||
next_buffer = &rx_ring->buffer_info[i];
|
||||
next_skb = next_buffer->skb;
|
||||
prefetch(next_skb->data - NET_IP_ALIGN);
|
||||
|
||||
cleaned = TRUE;
|
||||
cleaned_count++;
|
||||
@ -3668,7 +3666,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
||||
struct e1000_buffer *buffer_info, *next_buffer;
|
||||
struct e1000_ps_page *ps_page;
|
||||
struct e1000_ps_page_dma *ps_page_dma;
|
||||
struct sk_buff *skb, *next_skb;
|
||||
struct sk_buff *skb;
|
||||
unsigned int i, j;
|
||||
uint32_t length, staterr;
|
||||
int cleaned_count = 0;
|
||||
@ -3697,8 +3695,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
||||
prefetch(next_rxd);
|
||||
|
||||
next_buffer = &rx_ring->buffer_info[i];
|
||||
next_skb = next_buffer->skb;
|
||||
prefetch(next_skb->data - NET_IP_ALIGN);
|
||||
|
||||
cleaned = TRUE;
|
||||
cleaned_count++;
|
||||
|
@ -2615,6 +2615,18 @@ static int nv_nway_reset(struct net_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef NETIF_F_TSO
|
||||
static int nv_set_tso(struct net_device *dev, u32 value)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
if ((np->driver_data & DEV_HAS_CHECKSUM))
|
||||
return ethtool_op_set_tso(dev, value);
|
||||
else
|
||||
return value ? -EOPNOTSUPP : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct ethtool_ops ops = {
|
||||
.get_drvinfo = nv_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
@ -2626,6 +2638,10 @@ static struct ethtool_ops ops = {
|
||||
.get_regs = nv_get_regs,
|
||||
.nway_reset = nv_nway_reset,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
#ifdef NETIF_F_TSO
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = nv_set_tso
|
||||
#endif
|
||||
};
|
||||
|
||||
static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
|
||||
|
@ -107,7 +107,7 @@ static int init_netconsole(void)
|
||||
|
||||
if(!configured) {
|
||||
printk("netconsole: not configured, aborting\n");
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(netpoll_setup(&np))
|
||||
|
@ -1204,7 +1204,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
lp->linux_stats.rx_packets++;
|
||||
lp->linux_stats.rx_bytes += skb->len;
|
||||
lp->linux_stats.rx_bytes += pkt_len;
|
||||
outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
|
||||
continue;
|
||||
} else {
|
||||
|
@ -861,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
|
||||
* give dev_queue_xmit something it can free.
|
||||
*/
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (skb2 == NULL)
|
||||
goto abort;
|
||||
}
|
||||
|
||||
ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
|
||||
|
@ -69,8 +69,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.58"
|
||||
#define DRV_MODULE_RELDATE "May 22, 2006"
|
||||
#define DRV_MODULE_VERSION "3.59"
|
||||
#define DRV_MODULE_RELDATE "June 8, 2006"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -4485,9 +4485,8 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
|
||||
/* tp->lock is held. */
|
||||
static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
|
||||
{
|
||||
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
|
||||
tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
|
||||
NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
|
||||
tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
|
||||
NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
|
||||
switch (kind) {
|
||||
@ -4568,13 +4567,12 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
void (*write_op)(struct tg3 *, u32, u32);
|
||||
int i;
|
||||
|
||||
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
|
||||
tg3_nvram_lock(tp);
|
||||
/* No matching tg3_nvram_unlock() after this because
|
||||
* chip reset below will undo the nvram lock.
|
||||
*/
|
||||
tp->nvram_lock_cnt = 0;
|
||||
}
|
||||
tg3_nvram_lock(tp);
|
||||
|
||||
/* No matching tg3_nvram_unlock() after this because
|
||||
* chip reset below will undo the nvram lock.
|
||||
*/
|
||||
tp->nvram_lock_cnt = 0;
|
||||
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
|
||||
@ -4727,20 +4725,25 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
tw32_f(MAC_MODE, 0);
|
||||
udelay(40);
|
||||
|
||||
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
|
||||
/* Wait for firmware initialization to complete. */
|
||||
for (i = 0; i < 100000; i++) {
|
||||
tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
|
||||
if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
if (i >= 100000) {
|
||||
printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
|
||||
"firmware will not restart magic=%08x\n",
|
||||
tp->dev->name, val);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Wait for firmware initialization to complete. */
|
||||
for (i = 0; i < 100000; i++) {
|
||||
tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
|
||||
if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/* Chip might not be fitted with firmare. Some Sun onboard
|
||||
* parts are configured like that. So don't signal the timeout
|
||||
* of the above loop as an error, but do report the lack of
|
||||
* running firmware once.
|
||||
*/
|
||||
if (i >= 100000 &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
|
||||
tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
|
||||
|
||||
printk(KERN_INFO PFX "%s: No firmware running.\n",
|
||||
tp->dev->name);
|
||||
}
|
||||
|
||||
if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
|
||||
@ -9075,9 +9078,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
|
||||
return;
|
||||
|
||||
tw32_f(GRC_EEPROM_ADDR,
|
||||
(EEPROM_ADDR_FSM_RESET |
|
||||
(EEPROM_DEFAULT_CLOCK_PERIOD <<
|
||||
@ -9210,11 +9210,6 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
|
||||
printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
|
||||
return tg3_nvram_read_using_eeprom(tp, offset, val);
|
||||
|
||||
@ -9447,11 +9442,6 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
|
||||
printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
|
||||
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
|
||||
~GRC_LCLCTRL_GPIO_OUTPUT1);
|
||||
@ -9578,15 +9568,19 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
|
||||
pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
|
||||
tp->misc_host_ctrl);
|
||||
|
||||
/* The memory arbiter has to be enabled in order for SRAM accesses
|
||||
* to succeed. Normally on powerup the tg3 chip firmware will make
|
||||
* sure it is enabled, but other entities such as system netboot
|
||||
* code might disable it.
|
||||
*/
|
||||
val = tr32(MEMARB_MODE);
|
||||
tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
|
||||
|
||||
tp->phy_id = PHY_ID_INVALID;
|
||||
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
|
||||
|
||||
/* Do not even try poking around in here on Sun parts. */
|
||||
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
|
||||
/* All SUN chips are built-in LOMs. */
|
||||
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
|
||||
return;
|
||||
}
|
||||
/* Assume an onboard device by default. */
|
||||
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
|
||||
|
||||
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
|
||||
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
|
||||
@ -9686,6 +9680,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
|
||||
|
||||
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
|
||||
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
|
||||
else
|
||||
tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
|
||||
|
||||
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
|
||||
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
|
||||
@ -9834,16 +9830,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
|
||||
int i;
|
||||
u32 magic;
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
|
||||
/* Sun decided not to put the necessary bits in the
|
||||
* NVRAM of their onboard tg3 parts :(
|
||||
*/
|
||||
strcpy(tp->board_part_number, "Sun 570X");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tg3_nvram_read_swab(tp, 0x0, &magic))
|
||||
return;
|
||||
goto out_not_found;
|
||||
|
||||
if (magic == TG3_EEPROM_MAGIC) {
|
||||
for (i = 0; i < 256; i += 4) {
|
||||
@ -9874,6 +9862,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
if (!(tmp16 & 0x8000))
|
||||
goto out_not_found;
|
||||
|
||||
pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
|
||||
&tmp);
|
||||
tmp = cpu_to_le32(tmp);
|
||||
@ -9965,37 +9956,6 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
static int __devinit tg3_is_sun_570X(struct tg3 *tp)
|
||||
{
|
||||
struct pci_dev *pdev = tp->pdev;
|
||||
struct pcidev_cookie *pcp = pdev->sysdata;
|
||||
|
||||
if (pcp != NULL) {
|
||||
int node = pcp->prom_node;
|
||||
u32 venid;
|
||||
int err;
|
||||
|
||||
err = prom_getproperty(node, "subsystem-vendor-id",
|
||||
(char *) &venid, sizeof(venid));
|
||||
if (err == 0 || err == -1)
|
||||
return 0;
|
||||
if (venid == PCI_VENDOR_ID_SUN)
|
||||
return 1;
|
||||
|
||||
/* TG3 chips onboard the SunBlade-2500 don't have the
|
||||
* subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they
|
||||
* are distinguishable from non-Sun variants by being
|
||||
* named "network" by the firmware. Non-Sun cards will
|
||||
* show up as being named "ethernet".
|
||||
*/
|
||||
if (!strcmp(pcp->prom_name, "network"))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
{
|
||||
static struct pci_device_id write_reorder_chipsets[] = {
|
||||
@ -10012,11 +9972,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
u16 pci_cmd;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
if (tg3_is_sun_570X(tp))
|
||||
tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
|
||||
#endif
|
||||
|
||||
/* Force memory write invalidate off. If we leave it on,
|
||||
* then on 5700_BX chips we have to enable a workaround.
|
||||
* The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
|
||||
@ -10312,8 +10267,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
if (tp->write32 == tg3_write_indirect_reg32 ||
|
||||
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
|
||||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
|
||||
(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
|
||||
tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
|
||||
|
||||
/* Get eeprom hw config before calling tg3_set_power_state().
|
||||
@ -10594,8 +10548,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
|
||||
#endif
|
||||
|
||||
mac_offset = 0x7c;
|
||||
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
|
||||
!(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
|
||||
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
|
||||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
|
||||
if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
|
||||
mac_offset = 0xcc;
|
||||
@ -10622,8 +10575,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
|
||||
}
|
||||
if (!addr_ok) {
|
||||
/* Next, try NVRAM. */
|
||||
if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
|
||||
!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
|
||||
if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
|
||||
!tg3_nvram_read(tp, mac_offset + 4, &lo)) {
|
||||
dev->dev_addr[0] = ((hi >> 16) & 0xff);
|
||||
dev->dev_addr[1] = ((hi >> 24) & 0xff);
|
||||
|
@ -2184,7 +2184,7 @@ struct tg3 {
|
||||
#define TG3_FLAG_INIT_COMPLETE 0x80000000
|
||||
u32 tg3_flags2;
|
||||
#define TG3_FLG2_RESTART_TIMER 0x00000001
|
||||
#define TG3_FLG2_SUN_570X 0x00000002
|
||||
/* 0x00000002 available */
|
||||
#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004
|
||||
#define TG3_FLG2_IS_5788 0x00000008
|
||||
#define TG3_FLG2_MAX_RXPEND_64 0x00000010
|
||||
@ -2216,6 +2216,7 @@ struct tg3 {
|
||||
#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
|
||||
#define TG3_FLG2_1SHOT_MSI 0x10000000
|
||||
#define TG3_FLG2_PHY_JITTER_BUG 0x20000000
|
||||
#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000
|
||||
|
||||
u32 split_mode_max_reqs;
|
||||
#define SPLIT_MODE_5704_MAX_REQ 3
|
||||
|
@ -624,25 +624,28 @@ err_destroy_tx0:
|
||||
static u16 generate_cookie(struct bcm43xx_dmaring *ring,
|
||||
int slot)
|
||||
{
|
||||
u16 cookie = 0x0000;
|
||||
u16 cookie = 0xF000;
|
||||
|
||||
/* Use the upper 4 bits of the cookie as
|
||||
* DMA controller ID and store the slot number
|
||||
* in the lower 12 bits
|
||||
* in the lower 12 bits.
|
||||
* Note that the cookie must never be 0, as this
|
||||
* is a special value used in RX path.
|
||||
*/
|
||||
switch (ring->mmio_base) {
|
||||
default:
|
||||
assert(0);
|
||||
case BCM43xx_MMIO_DMA1_BASE:
|
||||
cookie = 0xA000;
|
||||
break;
|
||||
case BCM43xx_MMIO_DMA2_BASE:
|
||||
cookie = 0x1000;
|
||||
cookie = 0xB000;
|
||||
break;
|
||||
case BCM43xx_MMIO_DMA3_BASE:
|
||||
cookie = 0x2000;
|
||||
cookie = 0xC000;
|
||||
break;
|
||||
case BCM43xx_MMIO_DMA4_BASE:
|
||||
cookie = 0x3000;
|
||||
cookie = 0xD000;
|
||||
break;
|
||||
}
|
||||
assert(((u16)slot & 0xF000) == 0x0000);
|
||||
@ -660,16 +663,16 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
|
||||
struct bcm43xx_dmaring *ring = NULL;
|
||||
|
||||
switch (cookie & 0xF000) {
|
||||
case 0x0000:
|
||||
case 0xA000:
|
||||
ring = dma->tx_ring0;
|
||||
break;
|
||||
case 0x1000:
|
||||
case 0xB000:
|
||||
ring = dma->tx_ring1;
|
||||
break;
|
||||
case 0x2000:
|
||||
case 0xC000:
|
||||
ring = dma->tx_ring2;
|
||||
break;
|
||||
case 0x3000:
|
||||
case 0xD000:
|
||||
ring = dma->tx_ring3;
|
||||
break;
|
||||
default:
|
||||
@ -839,8 +842,18 @@ static void dma_rx(struct bcm43xx_dmaring *ring,
|
||||
/* We received an xmit status. */
|
||||
struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
|
||||
struct bcm43xx_xmitstatus stat;
|
||||
int i = 0;
|
||||
|
||||
stat.cookie = le16_to_cpu(hw->cookie);
|
||||
while (stat.cookie == 0) {
|
||||
if (unlikely(++i >= 10000)) {
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
udelay(2);
|
||||
barrier();
|
||||
stat.cookie = le16_to_cpu(hw->cookie);
|
||||
}
|
||||
stat.flags = hw->flags;
|
||||
stat.cnt1 = hw->cnt1;
|
||||
stat.cnt2 = hw->cnt2;
|
||||
|
@ -285,9 +285,9 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
|
||||
* Default resume method for devices that have no driver provided resume,
|
||||
* or not even a driver at all.
|
||||
*/
|
||||
static void pci_default_resume(struct pci_dev *pci_dev)
|
||||
static int pci_default_resume(struct pci_dev *pci_dev)
|
||||
{
|
||||
int retval;
|
||||
int retval = 0;
|
||||
|
||||
/* restore the PCI config space */
|
||||
pci_restore_state(pci_dev);
|
||||
@ -297,18 +297,21 @@ static void pci_default_resume(struct pci_dev *pci_dev)
|
||||
/* if the device was busmaster before the suspend, make it busmaster again */
|
||||
if (pci_dev->is_busmaster)
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int pci_device_resume(struct device * dev)
|
||||
{
|
||||
int error;
|
||||
struct pci_dev * pci_dev = to_pci_dev(dev);
|
||||
struct pci_driver * drv = pci_dev->driver;
|
||||
|
||||
if (drv && drv->resume)
|
||||
drv->resume(pci_dev);
|
||||
error = drv->resume(pci_dev);
|
||||
else
|
||||
pci_default_resume(pci_dev);
|
||||
return 0;
|
||||
error = pci_default_resume(pci_dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void pci_device_shutdown(struct device *dev)
|
||||
|
@ -461,9 +461,23 @@ int
|
||||
pci_restore_state(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
int val;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
|
||||
/*
|
||||
* The Base Address register should be programmed before the command
|
||||
* register(s)
|
||||
*/
|
||||
for (i = 15; i >= 0; i--) {
|
||||
pci_read_config_dword(dev, i * 4, &val);
|
||||
if (val != dev->saved_config_space[i]) {
|
||||
printk(KERN_DEBUG "PM: Writing back config space on "
|
||||
"device %s at offset %x (was %x, writing %x)\n",
|
||||
pci_name(dev), i,
|
||||
val, (int)dev->saved_config_space[i]);
|
||||
pci_write_config_dword(dev,i * 4,
|
||||
dev->saved_config_space[i]);
|
||||
}
|
||||
}
|
||||
pci_restore_msi_state(dev);
|
||||
pci_restore_msix_state(dev);
|
||||
return 0;
|
||||
|
@ -1143,6 +1143,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
|
||||
{
|
||||
struct pcmcia_socket *s = pcmcia_get_socket(skt);
|
||||
|
||||
if (!s) {
|
||||
printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
|
||||
"failed, event 0x%x lost!\n", skt, event);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
|
||||
event, priority, skt);
|
||||
|
||||
|
@ -48,33 +48,33 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct m48t86_ops *ops = pdev->dev.platform_data;
|
||||
|
||||
reg = ops->readb(M48T86_REG_B);
|
||||
reg = ops->readbyte(M48T86_REG_B);
|
||||
|
||||
if (reg & M48T86_REG_B_DM) {
|
||||
/* data (binary) mode */
|
||||
tm->tm_sec = ops->readb(M48T86_REG_SEC);
|
||||
tm->tm_min = ops->readb(M48T86_REG_MIN);
|
||||
tm->tm_hour = ops->readb(M48T86_REG_HOUR) & 0x3F;
|
||||
tm->tm_mday = ops->readb(M48T86_REG_DOM);
|
||||
tm->tm_sec = ops->readbyte(M48T86_REG_SEC);
|
||||
tm->tm_min = ops->readbyte(M48T86_REG_MIN);
|
||||
tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
|
||||
tm->tm_mday = ops->readbyte(M48T86_REG_DOM);
|
||||
/* tm_mon is 0-11 */
|
||||
tm->tm_mon = ops->readb(M48T86_REG_MONTH) - 1;
|
||||
tm->tm_year = ops->readb(M48T86_REG_YEAR) + 100;
|
||||
tm->tm_wday = ops->readb(M48T86_REG_DOW);
|
||||
tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1;
|
||||
tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100;
|
||||
tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
|
||||
} else {
|
||||
/* bcd mode */
|
||||
tm->tm_sec = BCD2BIN(ops->readb(M48T86_REG_SEC));
|
||||
tm->tm_min = BCD2BIN(ops->readb(M48T86_REG_MIN));
|
||||
tm->tm_hour = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F);
|
||||
tm->tm_mday = BCD2BIN(ops->readb(M48T86_REG_DOM));
|
||||
tm->tm_sec = BCD2BIN(ops->readbyte(M48T86_REG_SEC));
|
||||
tm->tm_min = BCD2BIN(ops->readbyte(M48T86_REG_MIN));
|
||||
tm->tm_hour = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
|
||||
tm->tm_mday = BCD2BIN(ops->readbyte(M48T86_REG_DOM));
|
||||
/* tm_mon is 0-11 */
|
||||
tm->tm_mon = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1;
|
||||
tm->tm_year = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100;
|
||||
tm->tm_wday = BCD2BIN(ops->readb(M48T86_REG_DOW));
|
||||
tm->tm_mon = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1;
|
||||
tm->tm_year = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100;
|
||||
tm->tm_wday = BCD2BIN(ops->readbyte(M48T86_REG_DOW));
|
||||
}
|
||||
|
||||
/* correct the hour if the clock is in 12h mode */
|
||||
if (!(reg & M48T86_REG_B_H24))
|
||||
if (ops->readb(M48T86_REG_HOUR) & 0x80)
|
||||
if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
|
||||
tm->tm_hour += 12;
|
||||
|
||||
return 0;
|
||||
@ -86,35 +86,35 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct m48t86_ops *ops = pdev->dev.platform_data;
|
||||
|
||||
reg = ops->readb(M48T86_REG_B);
|
||||
reg = ops->readbyte(M48T86_REG_B);
|
||||
|
||||
/* update flag and 24h mode */
|
||||
reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
|
||||
ops->writeb(reg, M48T86_REG_B);
|
||||
ops->writebyte(reg, M48T86_REG_B);
|
||||
|
||||
if (reg & M48T86_REG_B_DM) {
|
||||
/* data (binary) mode */
|
||||
ops->writeb(tm->tm_sec, M48T86_REG_SEC);
|
||||
ops->writeb(tm->tm_min, M48T86_REG_MIN);
|
||||
ops->writeb(tm->tm_hour, M48T86_REG_HOUR);
|
||||
ops->writeb(tm->tm_mday, M48T86_REG_DOM);
|
||||
ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH);
|
||||
ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR);
|
||||
ops->writeb(tm->tm_wday, M48T86_REG_DOW);
|
||||
ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
|
||||
ops->writebyte(tm->tm_min, M48T86_REG_MIN);
|
||||
ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
|
||||
ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
|
||||
ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
|
||||
ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
|
||||
ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
|
||||
} else {
|
||||
/* bcd mode */
|
||||
ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
|
||||
ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
|
||||
ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
|
||||
ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
|
||||
ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
|
||||
ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
|
||||
ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
|
||||
ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
|
||||
ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
|
||||
ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
|
||||
ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
|
||||
ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
|
||||
ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
|
||||
ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
|
||||
}
|
||||
|
||||
/* update ended */
|
||||
reg &= ~M48T86_REG_B_SET;
|
||||
ops->writeb(reg, M48T86_REG_B);
|
||||
ops->writebyte(reg, M48T86_REG_B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -125,12 +125,12 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct m48t86_ops *ops = pdev->dev.platform_data;
|
||||
|
||||
reg = ops->readb(M48T86_REG_B);
|
||||
reg = ops->readbyte(M48T86_REG_B);
|
||||
|
||||
seq_printf(seq, "mode\t\t: %s\n",
|
||||
(reg & M48T86_REG_B_DM) ? "binary" : "bcd");
|
||||
|
||||
reg = ops->readb(M48T86_REG_D);
|
||||
reg = ops->readbyte(M48T86_REG_D);
|
||||
|
||||
seq_printf(seq, "battery\t\t: %s\n",
|
||||
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
|
||||
@ -157,7 +157,7 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev)
|
||||
platform_set_drvdata(dev, rtc);
|
||||
|
||||
/* read battery status */
|
||||
reg = ops->readb(M48T86_REG_D);
|
||||
reg = ops->readbyte(M48T86_REG_D);
|
||||
dev_info(&dev->dev, "battery %s\n",
|
||||
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
|
||||
|
||||
|
@ -45,11 +45,11 @@ struct pgid {
|
||||
union {
|
||||
__u8 fc; /* SPID function code */
|
||||
struct path_state ps; /* SNID path state */
|
||||
} inf;
|
||||
} __attribute__ ((packed)) inf;
|
||||
union {
|
||||
__u32 cpu_addr : 16; /* CPU address */
|
||||
struct extended_cssid ext_cssid;
|
||||
} pgid_high;
|
||||
} __attribute__ ((packed)) pgid_high;
|
||||
__u32 cpu_id : 24; /* CPU identification */
|
||||
__u32 cpu_model : 16; /* CPU model */
|
||||
__u32 tod_high; /* high word TOD clock */
|
||||
|
@ -749,7 +749,7 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
|
||||
/* Unit check but no sense data. Need basic sense. */
|
||||
if (ccw_device_do_sense(cdev, irb) != 0)
|
||||
goto call_handler_unsol;
|
||||
memcpy(irb, &cdev->private->irb, sizeof(struct irb));
|
||||
memcpy(&cdev->private->irb, irb, sizeof(struct irb));
|
||||
cdev->private->state = DEV_STATE_W4SENSE;
|
||||
cdev->private->intparm = 0;
|
||||
return;
|
||||
|
@ -982,6 +982,12 @@ static int device_check(ppa_struct *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int ppa_adjust_queue(struct scsi_device *device)
|
||||
{
|
||||
blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scsi_host_template ppa_template = {
|
||||
.module = THIS_MODULE,
|
||||
.proc_name = "ppa",
|
||||
@ -997,6 +1003,7 @@ static struct scsi_host_template ppa_template = {
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.can_queue = 1,
|
||||
.slave_alloc = ppa_adjust_queue,
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -454,7 +454,7 @@ static int sil24_softreset(struct ata_port *ap, int verbose,
|
||||
*/
|
||||
msleep(10);
|
||||
|
||||
prb->ctrl = PRB_CTRL_SRST;
|
||||
prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
|
||||
prb->fis[1] = 0; /* no PM yet */
|
||||
|
||||
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
|
||||
@ -551,9 +551,9 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
|
||||
|
||||
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
|
||||
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
||||
prb->ctrl = PRB_CTRL_PACKET_WRITE;
|
||||
prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE);
|
||||
else
|
||||
prb->ctrl = PRB_CTRL_PACKET_READ;
|
||||
prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ);
|
||||
} else
|
||||
prb->ctrl = 0;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user