提交 ab11d1ea 编写于 作者: P Paul Mackerras

Merge by hand from Linus' tree.

Signed-off-by: NPaul Mackerras <paulus@samba.org>
...@@ -237,6 +237,12 @@ udev ...@@ -237,6 +237,12 @@ udev
udev is a userspace application for populating /dev dynamically with udev is a userspace application for populating /dev dynamically with
only entries for devices actually present. udev replaces devfs. only entries for devices actually present. udev replaces devfs.
FUSE
----
Needs libfuse 2.4.0 or later. Absolute minimum is 2.3.0 but mount
options 'direct_io' and 'kernel_cache' won't work.
Networking Networking
========== ==========
...@@ -390,6 +396,10 @@ udev ...@@ -390,6 +396,10 @@ udev
---- ----
o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html> o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
FUSE
----
o <http://sourceforge.net/projects/fuse>
Networking Networking
********** **********
......
...@@ -195,8 +195,8 @@ KEY ACCESS PERMISSIONS ...@@ -195,8 +195,8 @@ KEY ACCESS PERMISSIONS
====================== ======================
Keys have an owner user ID, a group access ID, and a permissions mask. The mask Keys have an owner user ID, a group access ID, and a permissions mask. The mask
has up to eight bits each for user, group and other access. Only five of each has up to eight bits each for possessor, user, group and other access. Only
set of eight bits are defined. These permissions granted are: five of each set of eight bits are defined. These permissions granted are:
(*) View (*) View
...@@ -241,16 +241,16 @@ about the status of the key service: ...@@ -241,16 +241,16 @@ about the status of the key service:
type, description and permissions. The payload of the key is not available type, description and permissions. The payload of the key is not available
this way: this way:
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4
00000002 I----- 2 perm 1f0000 0 0 keyring _uid.0: empty 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty
00000007 I----- 1 perm 1f0000 0 0 keyring _pid.1: empty 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty
0000018d I----- 1 perm 1f0000 0 0 keyring _pid.412: empty 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty
000004d2 I--Q-- 1 perm 1f0000 32 -1 keyring _uid.32: 1/4 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4
000004d3 I--Q-- 3 perm 1f0000 32 -1 keyring _uid_ses.32: empty 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty
00000892 I--QU- 1 perm 1f0000 0 0 user metal:copper: 0 00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0
00000893 I--Q-N 1 35s 1f0000 0 0 user metal:silver: 0 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0
00000894 I--Q-- 1 10h 1f0000 0 0 user metal:gold: 0 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0
The flags are: The flags are:
...@@ -637,6 +637,34 @@ call, and the key released upon close. How to deal with conflicting keys due to ...@@ -637,6 +637,34 @@ call, and the key released upon close. How to deal with conflicting keys due to
two different users opening the same file is left to the filesystem author to two different users opening the same file is left to the filesystem author to
solve. solve.
Note that there are two different types of pointers to keys that may be
encountered:
(*) struct key *
This simply points to the key structure itself. Key structures will be at
least four-byte aligned.
(*) key_ref_t
This is equivalent to a struct key *, but the least significant bit is set
if the caller "possesses" the key. By "possession" it is meant that the
calling processes has a searchable link to the key from one of its
keyrings. There are three functions for dealing with these:
key_ref_t make_key_ref(const struct key *key,
unsigned long possession);
struct key *key_ref_to_ptr(const key_ref_t key_ref);
unsigned long is_key_possessed(const key_ref_t key_ref);
The first function constructs a key reference from a key pointer and
possession information (which must be 0 or 1 and not any other value).
The second function retrieves the key pointer from a reference and the
third retrieves the possession flag.
When accessing a key's payload contents, certain precautions must be taken to When accessing a key's payload contents, certain precautions must be taken to
prevent access vs modification races. See the section "Notes on accessing prevent access vs modification races. See the section "Notes on accessing
payload contents" for more information. payload contents" for more information.
...@@ -665,7 +693,11 @@ payload contents" for more information. ...@@ -665,7 +693,11 @@ payload contents" for more information.
void key_put(struct key *key); void key_put(struct key *key);
This can be called from interrupt context. If CONFIG_KEYS is not set then Or:
void key_ref_put(key_ref_t key_ref);
These can be called from interrupt context. If CONFIG_KEYS is not set then
the argument will not be parsed. the argument will not be parsed.
...@@ -689,13 +721,17 @@ payload contents" for more information. ...@@ -689,13 +721,17 @@ payload contents" for more information.
(*) If a keyring was found in the search, this can be further searched by: (*) If a keyring was found in the search, this can be further searched by:
struct key *keyring_search(struct key *keyring, key_ref_t keyring_search(key_ref_t keyring_ref,
const struct key_type *type, const struct key_type *type,
const char *description) const char *description)
This searches the keyring tree specified for a matching key. Error ENOKEY This searches the keyring tree specified for a matching key. Error ENOKEY
is returned upon failure. If successful, the returned key will need to be is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful,
released. the returned key will need to be released.
The possession attribute from the keyring reference is used to control
access through the permissions mask and is propagated to the returned key
reference pointer if successful.
(*) To check the validity of a key, this function can be called: (*) To check the validity of a key, this function can be called:
...@@ -732,7 +768,7 @@ More complex payload contents must be allocated and a pointer to them set in ...@@ -732,7 +768,7 @@ More complex payload contents must be allocated and a pointer to them set in
key->payload.data. One of the following ways must be selected to access the key->payload.data. One of the following ways must be selected to access the
data: data:
(1) Unmodifyable key type. (1) Unmodifiable key type.
If the key type does not have a modify method, then the key's payload can If the key type does not have a modify method, then the key's payload can
be accessed without any form of locking, provided that it's known to be be accessed without any form of locking, provided that it's known to be
......
...@@ -604,6 +604,15 @@ P: H. Peter Anvin ...@@ -604,6 +604,15 @@ P: H. Peter Anvin
M: hpa@zytor.com M: hpa@zytor.com
S: Maintained S: Maintained
CPUSETS
P: Paul Jackson
P: Simon Derr
M: pj@sgi.com
M: simon.derr@bull.net
L: linux-kernel@vger.kernel.org
W: http://www.bullopensource.org/cpuset/
S: Supported
CRAMFS FILESYSTEM CRAMFS FILESYSTEM
W: http://sourceforge.net/projects/cramfs/ W: http://sourceforge.net/projects/cramfs/
S: Orphan S: Orphan
...@@ -1906,6 +1915,13 @@ M: joern@wh.fh-wedel.de ...@@ -1906,6 +1915,13 @@ M: joern@wh.fh-wedel.de
L: linux-mtd@lists.infradead.org L: linux-mtd@lists.infradead.org
S: Maintained S: Maintained
PKTCDVD DRIVER
P: Peter Osterlund
M: petero2@telia.com
L: linux-kernel@vger.kernel.org
L: packet-writing@suse.com
S: Maintained
POSIX CLOCKS and TIMERS POSIX CLOCKS and TIMERS
P: George Anzinger P: George Anzinger
M: george@mvista.com M: george@mvista.com
......
...@@ -175,10 +175,10 @@ else ...@@ -175,10 +175,10 @@ else
endif endif
@touch $@ @touch $@
archprepare: maketools include/asm-arm/.arch archprepare: maketools
.PHONY: maketools FORCE .PHONY: maketools FORCE
maketools: include/linux/version.h FORCE maketools: include/linux/version.h include/asm-arm/.arch FORCE
$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
# Convert bzImage to zImage # Convert bzImage to zImage
......
此差异已折叠。
...@@ -125,7 +125,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) ...@@ -125,7 +125,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
} else if (type & IRQT_LOW) { } else if (type & IRQT_LOW) {
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
irq_type = IXP4XX_IRQ_LEVEL; irq_type = IXP4XX_IRQ_LEVEL;
} } else
return -EINVAL;
ixp4xx_config_irq(irq, irq_type); ixp4xx_config_irq(irq, irq_type);
...@@ -142,6 +143,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) ...@@ -142,6 +143,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
/* Set the new style */ /* Set the new style */
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
return 0;
} }
static void ixp4xx_irq_mask(unsigned int irq) static void ixp4xx_irq_mask(unsigned int irq)
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/irq.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/dmi.h> #include <linux/dmi.h>
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/irq.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -11,10 +11,8 @@ ...@@ -11,10 +11,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/irq.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/elfcore.h> #include <linux/elfcore.h>
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/delay.h> #include <asm/delay.h>
...@@ -25,8 +24,6 @@ ...@@ -25,8 +24,6 @@
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <asm/i8259.h> #include <asm/i8259.h>
#include <linux/irq.h>
#include <io_ports.h> #include <io_ports.h>
/* /*
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
*/ */
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
*/ */
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/delay.h> #include <linux/delay.h>
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
......
...@@ -47,13 +47,11 @@ ...@@ -47,13 +47,11 @@
#include <asm/ldt.h> #include <asm/ldt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/irq.h>
#include <asm/desc.h> #include <asm/desc.h>
#ifdef CONFIG_MATH_EMULATION #ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h> #include <asm/math_emu.h>
#endif #endif
#include <linux/irq.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/irq.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/cpu.h> #include <linux/cpu.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/irq.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <asm/delay.h> #include <asm/delay.h>
......
...@@ -52,7 +52,6 @@ ...@@ -52,7 +52,6 @@
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <linux/irq.h>
#include <linux/module.h> #include <linux/module.h>
#include "mach_traps.h" #include "mach_traps.h"
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <asm/voyager.h> #include <asm/voyager.h>
#include <asm/vic.h> #include <asm/vic.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/irq.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <asm/i8253.h> #include <asm/i8253.h>
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <linux/irq.h>
/* TLB state -- visible externally, indexed physically */ /* TLB state -- visible externally, indexed physically */
DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#include <asm/mtrr.h> #include <asm/mtrr.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <linux/irq.h>
#define THREAD_NAME "kvoyagerd" #define THREAD_NAME "kvoyagerd"
/* external variables */ /* external variables */
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/irq.h> #include <linux/errno.h>
#include <linux/oprofile.h> #include <linux/oprofile.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
......
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/numa.h> #include <asm/numa.h>
#include "pci.h" #include "pci.h"
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/smp.h> #include <asm/smp.h>
......
...@@ -8,25 +8,8 @@ ...@@ -8,25 +8,8 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <linux/sysrq.h>
#include <linux/proc_fs.h>
#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/acpi.h>
#include <asm/uaccess.h>
#include <asm/acpi.h>
#include <asm/tlbflush.h>
#include <asm/processor.h>
static struct saved_context saved_context; static struct saved_context saved_context;
......
...@@ -24,7 +24,7 @@ aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -Wa,-no-bitinst ...@@ -24,7 +24,7 @@ aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -Wa,-no-bitinst
CFLAGS += $(cflags-y) CFLAGS += $(cflags-y)
AFLAGS += $(aflags-y) AFLAGS += $(aflags-y)
CHECKFLAGS := $(CHECK) -D__m32r__ CHECKFLAGS += -D__m32r__ -D__BIG_ENDIAN__=1
head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
unsigned long unsigned long
__generic_copy_to_user(void *to, const void *from, unsigned long n) __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{ {
prefetch(from); prefetch(from);
if (access_ok(VERIFY_WRITE, to, n)) if (access_ok(VERIFY_WRITE, to, n))
...@@ -22,7 +22,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) ...@@ -22,7 +22,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n)
} }
unsigned long unsigned long
__generic_copy_from_user(void *to, const void *from, unsigned long n) __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
prefetchw(to); prefetchw(to);
if (access_ok(VERIFY_READ, from, n)) if (access_ok(VERIFY_READ, from, n))
...@@ -111,7 +111,7 @@ do { \ ...@@ -111,7 +111,7 @@ do { \
#endif /* CONFIG_ISA_DUAL_ISSUE */ #endif /* CONFIG_ISA_DUAL_ISSUE */
long long
__strncpy_from_user(char *dst, const char *src, long count) __strncpy_from_user(char *dst, const char __user *src, long count)
{ {
long res; long res;
__do_strncpy_from_user(dst, src, count, res); __do_strncpy_from_user(dst, src, count, res);
...@@ -119,7 +119,7 @@ __strncpy_from_user(char *dst, const char *src, long count) ...@@ -119,7 +119,7 @@ __strncpy_from_user(char *dst, const char *src, long count)
} }
long long
strncpy_from_user(char *dst, const char *src, long count) strncpy_from_user(char *dst, const char __user *src, long count)
{ {
long res = -EFAULT; long res = -EFAULT;
if (access_ok(VERIFY_READ, src, 1)) if (access_ok(VERIFY_READ, src, 1))
...@@ -222,7 +222,7 @@ do { \ ...@@ -222,7 +222,7 @@ do { \
#endif /* not CONFIG_ISA_DUAL_ISSUE */ #endif /* not CONFIG_ISA_DUAL_ISSUE */
unsigned long unsigned long
clear_user(void *to, unsigned long n) clear_user(void __user *to, unsigned long n)
{ {
if (access_ok(VERIFY_WRITE, to, n)) if (access_ok(VERIFY_WRITE, to, n))
__do_clear_user(to, n); __do_clear_user(to, n);
...@@ -230,7 +230,7 @@ clear_user(void *to, unsigned long n) ...@@ -230,7 +230,7 @@ clear_user(void *to, unsigned long n)
} }
unsigned long unsigned long
__clear_user(void *to, unsigned long n) __clear_user(void __user *to, unsigned long n)
{ {
__do_clear_user(to, n); __do_clear_user(to, n);
return n; return n;
...@@ -244,7 +244,7 @@ __clear_user(void *to, unsigned long n) ...@@ -244,7 +244,7 @@ __clear_user(void *to, unsigned long n)
#ifdef CONFIG_ISA_DUAL_ISSUE #ifdef CONFIG_ISA_DUAL_ISSUE
long strnlen_user(const char *s, long n) long strnlen_user(const char __user *s, long n)
{ {
unsigned long mask = -__addr_ok(s); unsigned long mask = -__addr_ok(s);
unsigned long res; unsigned long res;
...@@ -313,7 +313,7 @@ long strnlen_user(const char *s, long n) ...@@ -313,7 +313,7 @@ long strnlen_user(const char *s, long n)
#else /* not CONFIG_ISA_DUAL_ISSUE */ #else /* not CONFIG_ISA_DUAL_ISSUE */
long strnlen_user(const char *s, long n) long strnlen_user(const char __user *s, long n)
{ {
unsigned long mask = -__addr_ok(s); unsigned long mask = -__addr_ok(s);
unsigned long res; unsigned long res;
......
...@@ -45,9 +45,8 @@ static void dummy_perf(struct pt_regs *regs) ...@@ -45,9 +45,8 @@ static void dummy_perf(struct pt_regs *regs)
mtpmr(PMRN_PMGC0, pmgc0); mtpmr(PMRN_PMGC0, pmgc0);
} }
#elif CONFIG_6xx #elif defined(CONFIG_6xx)
/* Ensure exceptions are disabled */ /* Ensure exceptions are disabled */
static void dummy_perf(struct pt_regs *regs) static void dummy_perf(struct pt_regs *regs)
{ {
unsigned int mmcr0 = mfspr(SPRN_MMCR0); unsigned int mmcr0 = mfspr(SPRN_MMCR0);
......
...@@ -205,6 +205,7 @@ static void kexec_prepare_cpus(void) ...@@ -205,6 +205,7 @@ static void kexec_prepare_cpus(void)
continue; continue;
while (paca[i].hw_cpu_id != -1) { while (paca[i].hw_cpu_id != -1) {
barrier();
if (!cpu_possible(i)) { if (!cpu_possible(i)) {
printk("kexec: cpu %d hw_cpu_id %d is not" printk("kexec: cpu %d hw_cpu_id %d is not"
" possible, ignoring\n", " possible, ignoring\n",
......
...@@ -342,14 +342,13 @@ static void native_flush_hash_range(unsigned long number, int local) ...@@ -342,14 +342,13 @@ static void native_flush_hash_range(unsigned long number, int local)
hpte_t *hptep; hpte_t *hptep;
unsigned long hpte_v; unsigned long hpte_v;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
unsigned long large; unsigned long large = batch->large;
local_irq_save(flags); local_irq_save(flags);
j = 0; j = 0;
for (i = 0; i < number; i++) { for (i = 0; i < number; i++) {
va = batch->vaddr[j]; va = batch->vaddr[j];
large = pte_huge(batch->pte[i]);
if (large) if (large)
vpn = va >> HPAGE_SHIFT; vpn = va >> HPAGE_SHIFT;
else else
...@@ -399,7 +398,7 @@ static void native_flush_hash_range(unsigned long number, int local) ...@@ -399,7 +398,7 @@ static void native_flush_hash_range(unsigned long number, int local)
asm volatile("ptesync":::"memory"); asm volatile("ptesync":::"memory");
for (i = 0; i < j; i++) for (i = 0; i < j; i++)
__tlbie(batch->vaddr[i], 0); __tlbie(batch->vaddr[i], large);
asm volatile("eieio; tlbsync; ptesync":::"memory"); asm volatile("eieio; tlbsync; ptesync":::"memory");
......
...@@ -141,12 +141,14 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, ...@@ -141,12 +141,14 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
* up scanning and resetting referenced bits then our batch context * up scanning and resetting referenced bits then our batch context
* will change mid stream. * will change mid stream.
*/ */
if (unlikely(i != 0 && mm != batch->mm)) { if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) {
flush_tlb_pending(); flush_tlb_pending();
i = 0; i = 0;
} }
if (i == 0) if (i == 0) {
batch->mm = mm; batch->mm = mm;
batch->large = pte_huge(pte);
}
if (addr < KERNELBASE) { if (addr < KERNELBASE) {
vsid = get_vsid(mm->context.id, addr); vsid = get_vsid(mm->context.id, addr);
WARN_ON(vsid == 0); WARN_ON(vsid == 0);
......
...@@ -33,6 +33,14 @@ config DEBUG_BOOTMEM ...@@ -33,6 +33,14 @@ config DEBUG_BOOTMEM
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
bool "Debug BOOTMEM initialization" bool "Debug BOOTMEM initialization"
config DEBUG_PAGEALLOC
bool "Page alloc debugging"
depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
of memory corruptions.
config MCOUNT config MCOUNT
bool bool
depends on STACK_DEBUG depends on STACK_DEBUG
......
...@@ -135,6 +135,28 @@ void __init device_scan(void) ...@@ -135,6 +135,28 @@ void __init device_scan(void)
cpu_data(0).clock_tick = prom_getintdefault(cpu_node, cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
"clock-frequency", "clock-frequency",
0); 0);
cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
"dcache-size",
16 * 1024);
cpu_data(0).dcache_line_size =
prom_getintdefault(cpu_node, "dcache-line-size", 32);
cpu_data(0).icache_size = prom_getintdefault(cpu_node,
"icache-size",
16 * 1024);
cpu_data(0).icache_line_size =
prom_getintdefault(cpu_node, "icache-line-size", 32);
cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
"ecache-size",
4 * 1024 * 1024);
cpu_data(0).ecache_line_size =
prom_getintdefault(cpu_node, "ecache-line-size", 64);
printk("CPU[0]: Caches "
"D[sz(%d):line_sz(%d)] "
"I[sz(%d):line_sz(%d)] "
"E[sz(%d):line_sz(%d)]\n",
cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
cpu_data(0).icache_size, cpu_data(0).icache_line_size,
cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
} }
#endif #endif
......
...@@ -9,17 +9,7 @@ ...@@ -9,17 +9,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#if PAGE_SHIFT == 13 #define VALID_SZ_BITS (_PAGE_VALID | _PAGE_SZBITS)
#define SZ_BITS _PAGE_SZ8K
#elif PAGE_SHIFT == 16
#define SZ_BITS _PAGE_SZ64K
#elif PAGE_SHIFT == 19
#define SZ_BITS _PAGE_SZ512K
#elif PAGE_SHIFT == 22
#define SZ_BITS _PAGE_SZ4MB
#endif
#define VALID_SZ_BITS (_PAGE_VALID | SZ_BITS)
#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P ) #define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P )
#define VPTE_SHIFT (PAGE_SHIFT - 3) #define VPTE_SHIFT (PAGE_SHIFT - 3)
...@@ -163,7 +153,6 @@ sparc64_vpte_continue: ...@@ -163,7 +153,6 @@ sparc64_vpte_continue:
stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS
retry ! Load PTE once again retry ! Load PTE once again
#undef SZ_BITS
#undef VALID_SZ_BITS #undef VALID_SZ_BITS
#undef VPTE_SHIFT #undef VPTE_SHIFT
#undef VPTE_BITS #undef VPTE_BITS
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
from_tl1_trap: from_tl1_trap:
rdpr %tl, %g5 ! For TL==3 test rdpr %tl, %g5 ! For TL==3 test
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
be,pn %xcc, 3f ! Yep, special processing be,pn %xcc, kvmap ! Yep, special processing
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
cmp %g5, 4 ! Last trap level? cmp %g5, 4 ! Last trap level?
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
...@@ -83,9 +83,9 @@ from_tl1_trap: ...@@ -83,9 +83,9 @@ from_tl1_trap:
nop ! Delay-slot nop ! Delay-slot
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
retry ! Trap return retry ! Trap return
3: brlz,pt %g4, 9b ! Kernel virtual map? nop
xor %g2, %g4, %g5 ! Finish bit twiddles nop
ba,a,pt %xcc, kvmap ! Yep, go check for obp/vmalloc nop
/* DTLB ** ICACHE line 3: winfixups+real_faults */ /* DTLB ** ICACHE line 3: winfixups+real_faults */
longpath: longpath:
......
...@@ -30,159 +30,6 @@ ...@@ -30,159 +30,6 @@
.text .text
.align 32 .align 32
.globl sparc64_vpte_patchme1
.globl sparc64_vpte_patchme2
/*
* On a second level vpte miss, check whether the original fault is to the OBP
* range (note that this is only possible for instruction miss, data misses to
* obp range do not use vpte). If so, go back directly to the faulting address.
* This is because we want to read the tpc, otherwise we have no way of knowing
* the 8k aligned faulting address if we are using >8k kernel pagesize. This
* also ensures no vpte range addresses are dropped into tlb while obp is
* executing (see inherit_locked_prom_mappings() rant).
*/
sparc64_vpte_nucleus:
/* Note that kvmap below has verified that the address is
* in the range MODULES_VADDR --> VMALLOC_END already. So
* here we need only check if it is an OBP address or not.
*/
sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5
blu,pn %xcc, sparc64_vpte_patchme1
mov 0x1, %g5
sllx %g5, 32, %g5
cmp %g4, %g5
blu,pn %xcc, obp_iaddr_patch
nop
/* These two instructions are patched by paginig_init(). */
sparc64_vpte_patchme1:
sethi %hi(0), %g5
sparc64_vpte_patchme2:
or %g5, %lo(0), %g5
/* With kernel PGD in %g5, branch back into dtlb_backend. */
ba,pt %xcc, sparc64_kpte_continue
andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */
vpte_noent:
/* Restore previous TAG_ACCESS, %g5 is zero, and we will
* skip over the trap instruction so that the top level
* TLB miss handler will thing this %g5 value is just an
* invalid PTE, thus branching to full fault processing.
*/
mov TLB_SFSR, %g1
stxa %g4, [%g1 + %g1] ASI_DMMU
done
.globl obp_iaddr_patch
obp_iaddr_patch:
/* These two instructions patched by inherit_prom_mappings(). */
sethi %hi(0), %g5
or %g5, %lo(0), %g5
/* Behave as if we are at TL0. */
wrpr %g0, 1, %tl
rdpr %tpc, %g4 /* Find original faulting iaddr */
srlx %g4, 13, %g4 /* Throw out context bits */
sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */
/* Restore previous TAG_ACCESS. */
mov TLB_SFSR, %g1
stxa %g4, [%g1 + %g1] ASI_IMMU
/* Get PMD offset. */
srlx %g4, 23, %g6
and %g6, 0x7ff, %g6
sllx %g6, 2, %g6
/* Load PMD, is it valid? */
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
sllx %g5, 11, %g5
/* Get PTE offset. */
srlx %g4, 13, %g6
and %g6, 0x3ff, %g6
sllx %g6, 3, %g6
/* Load PTE. */
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brgez,pn %g5, longpath
nop
/* TLB load and return from trap. */
stxa %g5, [%g0] ASI_ITLB_DATA_IN
retry
.globl obp_daddr_patch
obp_daddr_patch:
/* These two instructions patched by inherit_prom_mappings(). */
sethi %hi(0), %g5
or %g5, %lo(0), %g5
/* Get PMD offset. */
srlx %g4, 23, %g6
and %g6, 0x7ff, %g6
sllx %g6, 2, %g6
/* Load PMD, is it valid? */
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
sllx %g5, 11, %g5
/* Get PTE offset. */
srlx %g4, 13, %g6
and %g6, 0x3ff, %g6
sllx %g6, 3, %g6
/* Load PTE. */
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brgez,pn %g5, longpath
nop
/* TLB load and return from trap. */
stxa %g5, [%g0] ASI_DTLB_DATA_IN
retry
/*
* On a first level data miss, check whether this is to the OBP range (note
* that such accesses can be made by prom, as well as by kernel using
* prom_getproperty on "address"), and if so, do not use vpte access ...
* rather, use information saved during inherit_prom_mappings() using 8k
* pagesize.
*/
.align 32
kvmap:
sethi %hi(MODULES_VADDR), %g5
cmp %g4, %g5
blu,pn %xcc, longpath
mov (VMALLOC_END >> 24), %g5
sllx %g5, 24, %g5
cmp %g4, %g5
bgeu,pn %xcc, longpath
nop
kvmap_check_obp:
sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5
blu,pn %xcc, kvmap_vmalloc_addr
mov 0x1, %g5
sllx %g5, 32, %g5
cmp %g4, %g5
blu,pn %xcc, obp_daddr_patch
nop
kvmap_vmalloc_addr:
/* If we get here, a vmalloc addr was accessed, load kernel VPTE. */
ldxa [%g3 + %g6] ASI_N, %g5
brgez,pn %g5, longpath
nop
/* PTE is valid, load into TLB and return from trap. */
stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
retry
/* This is trivial with the new code... */ /* This is trivial with the new code... */
.globl do_fpdis .globl do_fpdis
do_fpdis: do_fpdis:
...@@ -525,14 +372,13 @@ cheetah_plus_patch_fpdis: ...@@ -525,14 +372,13 @@ cheetah_plus_patch_fpdis:
* *
* DATA 0: [low 32-bits] Address of function to call, jmp to this * DATA 0: [low 32-bits] Address of function to call, jmp to this
* [high 32-bits] MMU Context Argument 0, place in %g5 * [high 32-bits] MMU Context Argument 0, place in %g5
* DATA 1: Address Argument 1, place in %g6 * DATA 1: Address Argument 1, place in %g1
* DATA 2: Address Argument 2, place in %g7 * DATA 2: Address Argument 2, place in %g7
* *
* With this method we can do most of the cross-call tlb/cache * With this method we can do most of the cross-call tlb/cache
* flushing very quickly. * flushing very quickly.
* *
* Current CPU's IRQ worklist table is locked into %g1, * Current CPU's IRQ worklist table is locked into %g6, don't touch.
* don't touch.
*/ */
.text .text
.align 32 .align 32
...@@ -1006,13 +852,14 @@ cheetah_plus_dcpe_trap_vector: ...@@ -1006,13 +852,14 @@ cheetah_plus_dcpe_trap_vector:
nop nop
do_cheetah_plus_data_parity: do_cheetah_plus_data_parity:
ba,pt %xcc, etrap rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7 rd %pc, %g7
mov 0x0, %o0 mov 0x0, %o0
call cheetah_plus_parity_error call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1 add %sp, PTREGS_OFF, %o1
ba,pt %xcc, rtrap ba,a,pt %xcc, rtrap_irq
clr %l6
cheetah_plus_dcpe_trap_vector_tl1: cheetah_plus_dcpe_trap_vector_tl1:
membar #Sync membar #Sync
...@@ -1036,13 +883,14 @@ cheetah_plus_icpe_trap_vector: ...@@ -1036,13 +883,14 @@ cheetah_plus_icpe_trap_vector:
nop nop
do_cheetah_plus_insn_parity: do_cheetah_plus_insn_parity:
ba,pt %xcc, etrap rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7 rd %pc, %g7
mov 0x1, %o0 mov 0x1, %o0
call cheetah_plus_parity_error call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1 add %sp, PTREGS_OFF, %o1
ba,pt %xcc, rtrap ba,a,pt %xcc, rtrap_irq
clr %l6
cheetah_plus_icpe_trap_vector_tl1: cheetah_plus_icpe_trap_vector_tl1:
membar #Sync membar #Sync
...@@ -1075,6 +923,10 @@ do_dcpe_tl1: ...@@ -1075,6 +923,10 @@ do_dcpe_tl1:
nop nop
wrpr %g1, %tl ! Restore original trap level wrpr %g1, %tl ! Restore original trap level
do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
sethi %hi(dcache_parity_tl1_occurred), %g2
lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
add %g1, 1, %g1
stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
/* Reset D-cache parity */ /* Reset D-cache parity */
sethi %hi(1 << 16), %g1 ! D-cache size sethi %hi(1 << 16), %g1 ! D-cache size
mov (1 << 5), %g2 ! D-cache line size mov (1 << 5), %g2 ! D-cache line size
...@@ -1121,6 +973,10 @@ do_icpe_tl1: ...@@ -1121,6 +973,10 @@ do_icpe_tl1:
nop nop
wrpr %g1, %tl ! Restore original trap level wrpr %g1, %tl ! Restore original trap level
do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
sethi %hi(icache_parity_tl1_occurred), %g2
lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1
add %g1, 1, %g1
stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
/* Flush I-cache */ /* Flush I-cache */
sethi %hi(1 << 15), %g1 ! I-cache size sethi %hi(1 << 15), %g1 ! I-cache size
mov (1 << 5), %g2 ! I-cache line size mov (1 << 5), %g2 ! I-cache line size
......
...@@ -80,15 +80,165 @@ sparc_ramdisk_image64: ...@@ -80,15 +80,165 @@ sparc_ramdisk_image64:
.xword 0 .xword 0
.word _end .word _end
/* We must be careful, 32-bit OpenBOOT will get confused if it /* PROM cif handler code address is in %o4. */
* tries to save away a register window to a 64-bit kernel sparc64_boot:
* stack address. Flush all windows, disable interrupts, 1: rd %pc, %g7
* remap if necessary, jump onto kernel trap table, then kernel set 1b, %g1
* stack, or else we die. cmp %g1, %g7
be,pn %xcc, sparc64_boot_after_remap
mov %o4, %l7
/* We need to remap the kernel. Use position independant
* code to remap us to KERNBASE.
* *
* PROM entry point is on %o4 * SILO can invoke us with 32-bit address masking enabled,
* so make sure that's clear.
*/ */
sparc64_boot: rdpr %pstate, %g1
andn %g1, PSTATE_AM, %g1
wrpr %g1, 0x0, %pstate
ba,a,pt %xcc, 1f
.globl prom_finddev_name, prom_chosen_path
.globl prom_getprop_name, prom_mmu_name
.globl prom_callmethod_name, prom_translate_name
.globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
.globl prom_boot_mapped_pc, prom_boot_mapping_mode
.globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
prom_finddev_name:
.asciz "finddevice"
prom_chosen_path:
.asciz "/chosen"
prom_getprop_name:
.asciz "getprop"
prom_mmu_name:
.asciz "mmu"
prom_callmethod_name:
.asciz "call-method"
prom_translate_name:
.asciz "translate"
prom_map_name:
.asciz "map"
prom_unmap_name:
.asciz "unmap"
.align 4
prom_mmu_ihandle_cache:
.word 0
prom_boot_mapped_pc:
.word 0
prom_boot_mapping_mode:
.word 0
.align 8
prom_boot_mapping_phys_high:
.xword 0
prom_boot_mapping_phys_low:
.xword 0
1:
rd %pc, %l0
mov (1b - prom_finddev_name), %l1
mov (1b - prom_chosen_path), %l2
mov (1b - prom_boot_mapped_pc), %l3
sub %l0, %l1, %l1
sub %l0, %l2, %l2
sub %l0, %l3, %l3
stw %l0, [%l3]
sub %sp, (192 + 128), %sp
/* chosen_node = prom_finddevice("/chosen") */
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice"
mov 1, %l3
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen"
stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
call %l7
add %sp, (2047 + 128), %o0 ! argument array
ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node
mov (1b - prom_getprop_name), %l1
mov (1b - prom_mmu_name), %l2
mov (1b - prom_mmu_ihandle_cache), %l5
sub %l0, %l1, %l1
sub %l0, %l2, %l2
sub %l0, %l5, %l5
/* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
mov 4, %l3
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
mov 1, %l3
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node
stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu"
stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache
mov 4, %l3
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3)
stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
call %l7
add %sp, (2047 + 128), %o0 ! argument array
mov (1b - prom_callmethod_name), %l1
mov (1b - prom_translate_name), %l2
sub %l0, %l1, %l1
sub %l0, %l2, %l2
lduw [%l5], %l5 ! prom_mmu_ihandle_cache
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method"
mov 3, %l3
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3
mov 5, %l3
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
srlx %l0, 22, %l3
sllx %l3, 22, %l3
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
stx %g0, [%sp + 2047 + 128 + 0x40] ! res3
stx %g0, [%sp + 2047 + 128 + 0x48] ! res4
stx %g0, [%sp + 2047 + 128 + 0x50] ! res5
call %l7
add %sp, (2047 + 128), %o0 ! argument array
ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode
mov (1b - prom_boot_mapping_mode), %l4
sub %l0, %l4, %l4
stw %l1, [%l4]
mov (1b - prom_boot_mapping_phys_high), %l4
sub %l0, %l4, %l4
ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
stx %l2, [%l4 + 0x0]
ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
stx %l3, [%l4 + 0x8]
/* Leave service as-is, "call-method" */
mov 7, %l3
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7
mov 1, %l3
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
mov (1b - prom_map_name), %l3
sub %l0, %l3, %l3
stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map"
/* Leave arg2 as-is, prom_mmu_ihandle_cache */
mov -1, %l3
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default)
sethi %hi(8 * 1024 * 1024), %l3
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: size (8MB)
sethi %hi(KERNBASE), %l3
stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE)
stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty
mov (1b - prom_boot_mapping_phys_low), %l3
sub %l0, %l3, %l3
ldx [%l3], %l3
stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr
call %l7
add %sp, (2047 + 128), %o0 ! argument array
add %sp, (192 + 128), %sp
sparc64_boot_after_remap:
BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
ba,pt %xcc, spitfire_boot ba,pt %xcc, spitfire_boot
...@@ -125,185 +275,7 @@ cheetah_generic_boot: ...@@ -125,185 +275,7 @@ cheetah_generic_boot:
stxa %g0, [%g3] ASI_IMMU stxa %g0, [%g3] ASI_IMMU
membar #Sync membar #Sync
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate ba,a,pt %xcc, jump_to_sun4u_init
wr %g0, 0, %fprs
/* Just like for Spitfire, we probe itlb-2 for a mapping which
* matches our current %pc. We take the physical address in
* that mapping and use it to make our own.
*/
/* %g5 holds the tlb data */
sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
sllx %g5, 32, %g5
or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
/* Put PADDR tlb data mask into %g3. */
sethi %uhi(_PAGE_PADDR), %g3
or %g3, %ulo(_PAGE_PADDR), %g3
sllx %g3, 32, %g3
sethi %hi(_PAGE_PADDR), %g7
or %g7, %lo(_PAGE_PADDR), %g7
or %g3, %g7, %g3
set 2 << 16, %l0 /* TLB entry walker. */
set 0x1fff, %l2 /* Page mask. */
rd %pc, %l3
andn %l3, %l2, %g2 /* vaddr comparator */
1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g2
be,pn %xcc, cheetah_got_tlbentry
nop
and %l0, (127 << 3), %g1
cmp %g1, (127 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
/* Search the small TLB. OBP never maps us like that but
* newer SILO can.
*/
clr %l0
1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g2
be,pn %xcc, cheetah_got_tlbentry
nop
cmp %l0, (15 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
/* BUG() if we get here... */
ta 0x5
cheetah_got_tlbentry:
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
membar #Sync
and %g1, %g3, %g1
set 0x5fff, %l0
andn %g1, %l0, %g1
or %g5, %g1, %g5
/* Clear out any KERNBASE area entries. */
set 2 << 16, %l0
sethi %hi(KERNBASE), %g3
sethi %hi(KERNBASE<<1), %g7
mov TLB_TAG_ACCESS, %l7
/* First, check ITLB */
1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_IMMU
membar #Sync
stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
membar #Sync
2: and %l0, (127 << 3), %g1
cmp %g1, (127 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
/* Next, check DTLB */
set 2 << 16, %l0
1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_DMMU
membar #Sync
stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
membar #Sync
2: and %l0, (511 << 3), %g1
cmp %g1, (511 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
/* On Cheetah+, have to check second DTLB. */
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,l0,2f)
ba,pt %xcc, 9f
nop
2: set 3 << 16, %l0
1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_DMMU
membar #Sync
stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
membar #Sync
2: and %l0, (511 << 3), %g1
cmp %g1, (511 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
9:
/* Now lock the TTE we created into ITLB-0 and DTLB-0,
* entry 15 (and maybe 14 too).
*/
sethi %hi(KERNBASE), %g3
set (0 << 16) | (15 << 3), %g7
stxa %g3, [%l7] ASI_DMMU
membar #Sync
stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
membar #Sync
stxa %g3, [%l7] ASI_IMMU
membar #Sync
stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync
flush %g3
membar #Sync
sethi %hi(_end), %g3 /* Check for bigkernel case */
or %g3, %lo(_end), %g3
srl %g3, 23, %g3 /* Check if _end > 8M */
brz,pt %g3, 1f
sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
sethi %hi(0x400000), %g3
or %g3, %lo(0x400000), %g3
add %g5, %g3, %g5 /* New tte data */
andn %g5, (_PAGE_G), %g5
sethi %hi(KERNBASE+0x400000), %g3
or %g3, %lo(KERNBASE+0x400000), %g3
set (0 << 16) | (14 << 3), %g7
stxa %g3, [%l7] ASI_DMMU
membar #Sync
stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
membar #Sync
stxa %g3, [%l7] ASI_IMMU
membar #Sync
stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync
flush %g3
membar #Sync
sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
ba,pt %xcc, 1f
nop
1: set sun4u_init, %g2
jmpl %g2 + %g0, %g0
nop
spitfire_boot: spitfire_boot:
/* Typically PROM has already enabled both MMU's and both on-chip /* Typically PROM has already enabled both MMU's and both on-chip
...@@ -313,6 +285,7 @@ spitfire_boot: ...@@ -313,6 +285,7 @@ spitfire_boot:
stxa %g1, [%g0] ASI_LSU_CONTROL stxa %g1, [%g0] ASI_LSU_CONTROL
membar #Sync membar #Sync
jump_to_sun4u_init:
/* /*
* Make sure we are in privileged mode, have address masking, * Make sure we are in privileged mode, have address masking,
* using the ordinary globals and have enabled floating * using the ordinary globals and have enabled floating
...@@ -324,151 +297,6 @@ spitfire_boot: ...@@ -324,151 +297,6 @@ spitfire_boot:
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
wr %g0, 0, %fprs wr %g0, 0, %fprs
spitfire_create_mappings:
/* %g5 holds the tlb data */
sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
sllx %g5, 32, %g5
or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
/* Base of physical memory cannot reliably be assumed to be
* at 0x0! Figure out where it happens to be. -DaveM
*/
/* Put PADDR tlb data mask into %g3. */
sethi %uhi(_PAGE_PADDR_SF), %g3
or %g3, %ulo(_PAGE_PADDR_SF), %g3
sllx %g3, 32, %g3
sethi %hi(_PAGE_PADDR_SF), %g7
or %g7, %lo(_PAGE_PADDR_SF), %g7
or %g3, %g7, %g3
/* Walk through entire ITLB, looking for entry which maps
* our %pc currently, stick PADDR from there into %g5 tlb data.
*/
clr %l0 /* TLB entry walker. */
set 0x1fff, %l2 /* Page mask. */
rd %pc, %l3
andn %l3, %l2, %g2 /* vaddr comparator */
1:
/* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
ldxa [%l0] ASI_ITLB_TAG_READ, %g1
nop
nop
nop
andn %g1, %l2, %g1 /* Get vaddr */
cmp %g1, %g2
be,a,pn %xcc, spitfire_got_tlbentry
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
cmp %l0, (63 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
/* BUG() if we get here... */
ta 0x5
spitfire_got_tlbentry:
/* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
nop
nop
nop
and %g1, %g3, %g1 /* Mask to just get paddr bits. */
set 0x5fff, %l3 /* Mask offset to get phys base. */
andn %g1, %l3, %g1
/* NOTE: We hold on to %g1 paddr base as we need it below to lock
* NOTE: the PROM cif code into the TLB.
*/
or %g5, %g1, %g5 /* Or it into TAG being built. */
clr %l0 /* TLB entry walker. */
sethi %hi(KERNBASE), %g3 /* 4M lower limit */
sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */
mov TLB_TAG_ACCESS, %l7
1:
/* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
ldxa [%l0] ASI_ITLB_TAG_READ, %g1
nop
nop
nop
andn %g1, %l2, %g1 /* Get vaddr */
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_IMMU
stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
membar #Sync
2:
cmp %l0, (63 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
nop; nop; nop
clr %l0 /* TLB entry walker. */
1:
/* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
ldxa [%l0] ASI_DTLB_TAG_READ, %g1
nop
nop
nop
andn %g1, %l2, %g1 /* Get vaddr */
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_DMMU
stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
membar #Sync
2:
cmp %l0, (63 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
nop; nop; nop
/* PROM never puts any TLB entries into the MMU with the lock bit
* set. So we gladly use tlb entry 63 for KERNBASE. And maybe 62 too.
*/
sethi %hi(KERNBASE), %g3
mov (63 << 3), %g7
stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */
stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
membar #Sync
stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */
stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
membar #Sync
flush %g3
membar #Sync
sethi %hi(_end), %g3 /* Check for bigkernel case */
or %g3, %lo(_end), %g3
srl %g3, 23, %g3 /* Check if _end > 8M */
brz,pt %g3, 2f
sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
sethi %hi(0x400000), %g3
or %g3, %lo(0x400000), %g3
add %g5, %g3, %g5 /* New tte data */
andn %g5, (_PAGE_G), %g5
sethi %hi(KERNBASE+0x400000), %g3
or %g3, %lo(KERNBASE+0x400000), %g3
mov (62 << 3), %g7
stxa %g3, [%l7] ASI_DMMU
stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
membar #Sync
stxa %g3, [%l7] ASI_IMMU
stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync
flush %g3
membar #Sync
sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
2: ba,pt %xcc, 1f
nop
1:
set sun4u_init, %g2 set sun4u_init, %g2
jmpl %g2 + %g0, %g0 jmpl %g2 + %g0, %g0
nop nop
...@@ -483,38 +311,12 @@ sun4u_init: ...@@ -483,38 +311,12 @@ sun4u_init:
stxa %g0, [%g7] ASI_DMMU stxa %g0, [%g7] ASI_DMMU
membar #Sync membar #Sync
/* We are now safely (we hope) in Nucleus context (0), rewrite
* the KERNBASE TTE's so they no longer have the global bit set.
* Don't forget to setup TAG_ACCESS first 8-)
*/
mov TLB_TAG_ACCESS, %g2
stxa %g3, [%g2] ASI_IMMU
stxa %g3, [%g2] ASI_DMMU
membar #Sync
BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup) BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
ba,pt %xcc, spitfire_tlb_fixup ba,pt %xcc, spitfire_tlb_fixup
nop nop
cheetah_tlb_fixup: cheetah_tlb_fixup:
set (0 << 16) | (15 << 3), %g7
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g0
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync
ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g0
ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
membar #Sync
/* Kill instruction prefetch queues. */
flush %g3
membar #Sync
mov 2, %g2 /* Set TLB type to cheetah+. */ mov 2, %g2 /* Set TLB type to cheetah+. */
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
...@@ -551,21 +353,6 @@ cheetah_tlb_fixup: ...@@ -551,21 +353,6 @@ cheetah_tlb_fixup:
nop nop
spitfire_tlb_fixup: spitfire_tlb_fixup:
mov (63 << 3), %g7
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync
ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
membar #Sync
/* Kill instruction prefetch queues. */
flush %g3
membar #Sync
/* Set TLB type to spitfire. */ /* Set TLB type to spitfire. */
mov 0, %g2 mov 0, %g2
sethi %hi(tlb_type), %g1 sethi %hi(tlb_type), %g1
...@@ -578,24 +365,6 @@ tlb_fixup_done: ...@@ -578,24 +365,6 @@ tlb_fixup_done:
mov %sp, %l6 mov %sp, %l6
mov %o4, %l7 mov %o4, %l7
#if 0 /* We don't do it like this anymore, but for historical hack value
* I leave this snippet here to show how crazy we can be sometimes. 8-)
*/
/* Setup "Linux Current Register", thanks Sun 8-) */
wr %g0, 0x1, %pcr
/* Blackbird errata workaround. See commentary in
* smp.c:smp_percpu_timer_interrupt() for more
* information.
*/
ba,pt %xcc, 99f
nop
.align 64
99: wr %g6, %g0, %pic
rd %pic, %g0
#endif
wr %g0, ASI_P, %asi wr %g0, ASI_P, %asi
mov 1, %g1 mov 1, %g1
sllx %g1, THREAD_SHIFT, %g1 sllx %g1, THREAD_SHIFT, %g1
...@@ -756,12 +525,7 @@ bootup_user_stack_end: ...@@ -756,12 +525,7 @@ bootup_user_stack_end:
#include "ttable.S" #include "ttable.S"
#include "systbls.S" #include "systbls.S"
#include "ktlb.S"
.align 1024
.globl swapper_pg_dir
swapper_pg_dir:
.word 0
#include "etrap.S" #include "etrap.S"
#include "rtrap.S" #include "rtrap.S"
#include "winfixup.S" #include "winfixup.S"
......
/* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling.
*
* Copyright (C) 1995, 1997, 2005 David S. Miller <davem@davemloft.net>
* Copyright (C) 1996 Eddie C. Dost (ecd@brainaid.de)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/config.h>
#include <asm/head.h>
#include <asm/asi.h>
#include <asm/page.h>
#include <asm/pgtable.h>
.text
.align 32
/*
* On a second level vpte miss, check whether the original fault is to the OBP
* range (note that this is only possible for instruction miss, data misses to
* obp range do not use vpte). If so, go back directly to the faulting address.
* This is because we want to read the tpc, otherwise we have no way of knowing
* the 8k aligned faulting address if we are using >8k kernel pagesize. This
* also ensures no vpte range addresses are dropped into tlb while obp is
* executing (see inherit_locked_prom_mappings() rant).
*/
sparc64_vpte_nucleus:
/* Note that kvmap below has verified that the address is
* in the range MODULES_VADDR --> VMALLOC_END already. So
* here we need only check if it is an OBP address or not.
*/
sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5
blu,pn %xcc, kern_vpte
mov 0x1, %g5
sllx %g5, 32, %g5
cmp %g4, %g5
blu,pn %xcc, vpte_insn_obp
nop
/* These two instructions are patched by paginig_init(). */
kern_vpte:
sethi %hi(swapper_pgd_zero), %g5
lduw [%g5 + %lo(swapper_pgd_zero)], %g5
/* With kernel PGD in %g5, branch back into dtlb_backend. */
ba,pt %xcc, sparc64_kpte_continue
andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */
vpte_noent:
/* Restore previous TAG_ACCESS, %g5 is zero, and we will
* skip over the trap instruction so that the top level
* TLB miss handler will thing this %g5 value is just an
* invalid PTE, thus branching to full fault processing.
*/
mov TLB_SFSR, %g1
stxa %g4, [%g1 + %g1] ASI_DMMU
done
vpte_insn_obp:
sethi %hi(prom_pmd_phys), %g5
ldx [%g5 + %lo(prom_pmd_phys)], %g5
/* Behave as if we are at TL0. */
wrpr %g0, 1, %tl
rdpr %tpc, %g4 /* Find original faulting iaddr */
srlx %g4, 13, %g4 /* Throw out context bits */
sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */
/* Restore previous TAG_ACCESS. */
mov TLB_SFSR, %g1
stxa %g4, [%g1 + %g1] ASI_IMMU
/* Get PMD offset. */
srlx %g4, 23, %g6
and %g6, 0x7ff, %g6
sllx %g6, 2, %g6
/* Load PMD, is it valid? */
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
sllx %g5, 11, %g5
/* Get PTE offset. */
srlx %g4, 13, %g6
and %g6, 0x3ff, %g6
sllx %g6, 3, %g6
/* Load PTE. */
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brgez,pn %g5, longpath
nop
/* TLB load and return from trap. */
stxa %g5, [%g0] ASI_ITLB_DATA_IN
retry
kvmap_do_obp:
sethi %hi(prom_pmd_phys), %g5
ldx [%g5 + %lo(prom_pmd_phys)], %g5
/* Get PMD offset. */
srlx %g4, 23, %g6
and %g6, 0x7ff, %g6
sllx %g6, 2, %g6
/* Load PMD, is it valid? */
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
sllx %g5, 11, %g5
/* Get PTE offset. */
srlx %g4, 13, %g6
and %g6, 0x3ff, %g6
sllx %g6, 3, %g6
/* Load PTE. */
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brgez,pn %g5, longpath
nop
/* TLB load and return from trap. */
stxa %g5, [%g0] ASI_DTLB_DATA_IN
retry
/*
* On a first level data miss, check whether this is to the OBP range (note
* that such accesses can be made by prom, as well as by kernel using
* prom_getproperty on "address"), and if so, do not use vpte access ...
* rather, use information saved during inherit_prom_mappings() using 8k
* pagesize.
*/
.align 32
kvmap:
brgez,pn %g4, kvmap_nonlinear
nop
#ifdef CONFIG_DEBUG_PAGEALLOC
.globl kvmap_linear_patch
kvmap_linear_patch:
#endif
ba,pt %xcc, kvmap_load
xor %g2, %g4, %g5
#ifdef CONFIG_DEBUG_PAGEALLOC
sethi %hi(swapper_pg_dir), %g5
or %g5, %lo(swapper_pg_dir), %g5
sllx %g4, 64 - (PGDIR_SHIFT + PGDIR_BITS), %g6
srlx %g6, 64 - PAGE_SHIFT, %g6
andn %g6, 0x3, %g6
lduw [%g5 + %g6], %g5
brz,pn %g5, longpath
sllx %g4, 64 - (PMD_SHIFT + PMD_BITS), %g6
srlx %g6, 64 - PAGE_SHIFT, %g6
sllx %g5, 11, %g5
andn %g6, 0x3, %g6
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
sllx %g4, 64 - PMD_SHIFT, %g6
srlx %g6, 64 - PAGE_SHIFT, %g6
sllx %g5, 11, %g5
andn %g6, 0x7, %g6
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
brz,pn %g5, longpath
nop
ba,a,pt %xcc, kvmap_load
#endif
kvmap_nonlinear:
sethi %hi(MODULES_VADDR), %g5
cmp %g4, %g5
blu,pn %xcc, longpath
mov (VMALLOC_END >> 24), %g5
sllx %g5, 24, %g5
cmp %g4, %g5
bgeu,pn %xcc, longpath
nop
kvmap_check_obp:
sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5
blu,pn %xcc, kvmap_vmalloc_addr
mov 0x1, %g5
sllx %g5, 32, %g5
cmp %g4, %g5
blu,pn %xcc, kvmap_do_obp
nop
kvmap_vmalloc_addr:
/* If we get here, a vmalloc addr was accessed, load kernel VPTE. */
ldxa [%g3 + %g6] ASI_N, %g5
brgez,pn %g5, longpath
nop
kvmap_load:
/* PTE is valid, load into TLB and return from trap. */
stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
retry
...@@ -330,7 +330,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -330,7 +330,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
{ {
unsigned long sync_reg = (unsigned long) _arg2; unsigned long sync_reg = (unsigned long) _arg2;
u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO); u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO);
u64 val; u64 val;
int limit; int limit;
......
...@@ -496,7 +496,6 @@ extern void paging_init(void); ...@@ -496,7 +496,6 @@ extern void paging_init(void);
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
unsigned long highest_paddr;
int i; int i;
/* Initialize PROM console and command line. */ /* Initialize PROM console and command line. */
...@@ -519,11 +518,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -519,11 +518,7 @@ void __init setup_arch(char **cmdline_p)
idprom_init(); idprom_init();
(void) prom_probe_memory(); (void) prom_probe_memory();
/* In paging_init() we tip off this value to see if we need
* to change init_mm.pgd to point to the real alias mapping.
*/
phys_base = 0xffffffffffffffffUL; phys_base = 0xffffffffffffffffUL;
highest_paddr = 0UL;
for (i = 0; sp_banks[i].num_bytes != 0; i++) { for (i = 0; sp_banks[i].num_bytes != 0; i++) {
unsigned long top; unsigned long top;
...@@ -531,25 +526,10 @@ void __init setup_arch(char **cmdline_p) ...@@ -531,25 +526,10 @@ void __init setup_arch(char **cmdline_p)
phys_base = sp_banks[i].base_addr; phys_base = sp_banks[i].base_addr;
top = sp_banks[i].base_addr + top = sp_banks[i].base_addr +
sp_banks[i].num_bytes; sp_banks[i].num_bytes;
if (highest_paddr < top)
highest_paddr = top;
} }
pfn_base = phys_base >> PAGE_SHIFT; pfn_base = phys_base >> PAGE_SHIFT;
switch (tlb_type) { kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
default:
case spitfire:
kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent());
kern_base &= _PAGE_PADDR_SF;
break;
case cheetah:
case cheetah_plus:
kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
kern_base &= _PAGE_PADDR;
break;
};
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
if (!root_flags) if (!root_flags)
...@@ -625,6 +605,9 @@ extern void smp_info(struct seq_file *); ...@@ -625,6 +605,9 @@ extern void smp_info(struct seq_file *);
extern void smp_bogo(struct seq_file *); extern void smp_bogo(struct seq_file *);
extern void mmu_info(struct seq_file *); extern void mmu_info(struct seq_file *);
unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;
static int show_cpuinfo(struct seq_file *m, void *__unused) static int show_cpuinfo(struct seq_file *m, void *__unused)
{ {
seq_printf(m, seq_printf(m,
...@@ -635,6 +618,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) ...@@ -635,6 +618,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
"type\t\t: sun4u\n" "type\t\t: sun4u\n"
"ncpus probed\t: %ld\n" "ncpus probed\t: %ld\n"
"ncpus active\t: %ld\n" "ncpus active\t: %ld\n"
"D$ parity tl1\t: %u\n"
"I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
"Cpu0Bogo\t: %lu.%02lu\n" "Cpu0Bogo\t: %lu.%02lu\n"
"Cpu0ClkTck\t: %016lx\n" "Cpu0ClkTck\t: %016lx\n"
...@@ -647,7 +632,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) ...@@ -647,7 +632,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
(prom_prev >> 8) & 0xff, (prom_prev >> 8) & 0xff,
prom_prev & 0xff, prom_prev & 0xff,
(long)num_possible_cpus(), (long)num_possible_cpus(),
(long)num_online_cpus() (long)num_online_cpus(),
dcache_parity_tl1_occurred,
icache_parity_tl1_occurred
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
, cpu_data(0).udelay_val/(500000/HZ), , cpu_data(0).udelay_val/(500000/HZ),
(cpu_data(0).udelay_val/(5000/HZ)) % 100, (cpu_data(0).udelay_val/(5000/HZ)) % 100,
......
...@@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id) ...@@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id)
cpu_data(id).pte_cache[1] = NULL; cpu_data(id).pte_cache[1] = NULL;
cpu_data(id).pgd_cache = NULL; cpu_data(id).pgd_cache = NULL;
cpu_data(id).idle_volume = 1; cpu_data(id).idle_volume = 1;
cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
16 * 1024);
cpu_data(id).dcache_line_size =
prom_getintdefault(cpu_node, "dcache-line-size", 32);
cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
16 * 1024);
cpu_data(id).icache_line_size =
prom_getintdefault(cpu_node, "icache-line-size", 32);
cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
4 * 1024 * 1024);
cpu_data(id).ecache_line_size =
prom_getintdefault(cpu_node, "ecache-line-size", 64);
printk("CPU[%d]: Caches "
"D[sz(%d):line_sz(%d)] "
"I[sz(%d):line_sz(%d)] "
"E[sz(%d):line_sz(%d)]\n",
id,
cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
cpu_data(id).icache_size, cpu_data(id).icache_line_size,
cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
} }
static void smp_setup_percpu_timer(void); static void smp_setup_percpu_timer(void);
......
...@@ -119,8 +119,8 @@ startup_continue: ...@@ -119,8 +119,8 @@ startup_continue:
sethi %hi(itlb_load), %g2 sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2 or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18] stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2 sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20] stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2 sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28] stx %g2, [%sp + 2047 + 128 + 0x28]
...@@ -156,8 +156,8 @@ startup_continue: ...@@ -156,8 +156,8 @@ startup_continue:
sethi %hi(itlb_load), %g2 sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2 or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18] stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2 sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20] stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2 sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28] stx %g2, [%sp + 2047 + 128 + 0x28]
...@@ -190,8 +190,8 @@ do_dtlb: ...@@ -190,8 +190,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2 sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2 or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18] stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2 sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20] stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2 sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28] stx %g2, [%sp + 2047 + 128 + 0x28]
...@@ -228,8 +228,8 @@ do_dtlb: ...@@ -228,8 +228,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2 sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2 or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18] stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2 sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20] stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2 sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28] stx %g2, [%sp + 2047 + 128 + 0x28]
......
...@@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr) ...@@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr)
*/ */
static void __cheetah_flush_icache(void) static void __cheetah_flush_icache(void)
{ {
unsigned long i; unsigned int icache_size, icache_line_size;
unsigned long addr;
icache_size = local_cpu_data().icache_size;
icache_line_size = local_cpu_data().icache_line_size;
/* Clear the valid bits in all the tags. */ /* Clear the valid bits in all the tags. */
for (i = 0; i < (1 << 15); i += (1 << 5)) { for (addr = 0; addr < icache_size; addr += icache_line_size) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t" __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); : "r" (addr | (2 << 3)),
"i" (ASI_IC_TAG));
} }
} }
...@@ -904,13 +909,17 @@ static void cheetah_flush_icache(void) ...@@ -904,13 +909,17 @@ static void cheetah_flush_icache(void)
static void cheetah_flush_dcache(void) static void cheetah_flush_dcache(void)
{ {
unsigned long i; unsigned int dcache_size, dcache_line_size;
unsigned long addr;
dcache_size = local_cpu_data().dcache_size;
dcache_line_size = local_cpu_data().dcache_line_size;
for (i = 0; i < (1 << 16); i += (1 << 5)) { for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t" __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (i), "i" (ASI_DCACHE_TAG)); : "r" (addr), "i" (ASI_DCACHE_TAG));
} }
} }
...@@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void) ...@@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void)
*/ */
static void cheetah_plus_zap_dcache_parity(void) static void cheetah_plus_zap_dcache_parity(void)
{ {
unsigned long i; unsigned int dcache_size, dcache_line_size;
unsigned long addr;
dcache_size = local_cpu_data().dcache_size;
dcache_line_size = local_cpu_data().dcache_line_size;
for (i = 0; i < (1 << 16); i += (1 << 5)) { for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
unsigned long tag = (i >> 14); unsigned long tag = (addr >> 14);
unsigned long j; unsigned long line;
__asm__ __volatile__("membar #Sync\n\t" __asm__ __volatile__("membar #Sync\n\t"
"stxa %0, [%1] %2\n\t" "stxa %0, [%1] %2\n\t"
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (tag), "r" (i), : "r" (tag), "r" (addr),
"i" (ASI_DCACHE_UTAG)); "i" (ASI_DCACHE_UTAG));
for (j = i; j < i + (1 << 5); j += (1 << 3)) for (line = addr; line < addr + dcache_line_size; line += 8)
__asm__ __volatile__("membar #Sync\n\t" __asm__ __volatile__("membar #Sync\n\t"
"stxa %%g0, [%0] %1\n\t" "stxa %%g0, [%0] %1\n\t"
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (j), "i" (ASI_DCACHE_DATA)); : "r" (line),
"i" (ASI_DCACHE_DATA));
} }
} }
......
...@@ -9,8 +9,7 @@ ENTRY(_start) ...@@ -9,8 +9,7 @@ ENTRY(_start)
jiffies = jiffies_64; jiffies = jiffies_64;
SECTIONS SECTIONS
{ {
swapper_pmd_dir = 0x0000000000402000; swapper_low_pmd_dir = 0x0000000000402000;
empty_pg_dir = 0x0000000000403000;
. = 0x4000; . = 0x4000;
.text 0x0000000000404000 : .text 0x0000000000404000 :
{ {
......
此差异已折叠。
...@@ -144,42 +144,29 @@ __flush_icache_page: /* %o0 = phys_page */ ...@@ -144,42 +144,29 @@ __flush_icache_page: /* %o0 = phys_page */
#define DTAG_MASK 0x3 #define DTAG_MASK 0x3
/* This routine is Spitfire specific so the hardcoded
* D-cache size and line-size are OK.
*/
.align 64 .align 64
.globl __flush_dcache_page .globl __flush_dcache_page
__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
sethi %uhi(PAGE_OFFSET), %g1 sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1 sllx %g1, 32, %g1
sub %o0, %g1, %o0 sub %o0, %g1, %o0 ! physical address
clr %o4 srlx %o0, 11, %o0 ! make D-cache TAG
srlx %o0, 11, %o0 sethi %hi(1 << 14), %o2 ! D-cache size
sethi %hi(1 << 14), %o2 sub %o2, (1 << 5), %o2 ! D-cache line size
1: ldxa [%o4] ASI_DCACHE_TAG, %o3 ! LSU Group 1: ldxa [%o2] ASI_DCACHE_TAG, %o3 ! load D-cache TAG
add %o4, (1 << 5), %o4 ! IEU0 andcc %o3, DTAG_MASK, %g0 ! Valid?
ldxa [%o4] ASI_DCACHE_TAG, %g1 ! LSU Group be,pn %xcc, 2f ! Nope, branch
add %o4, (1 << 5), %o4 ! IEU0 andn %o3, DTAG_MASK, %o3 ! Clear valid bits
ldxa [%o4] ASI_DCACHE_TAG, %g2 ! LSU Group o3 available cmp %o3, %o0 ! TAG match?
add %o4, (1 << 5), %o4 ! IEU0 bne,pt %xcc, 2f ! Nope, branch
andn %o3, DTAG_MASK, %o3 ! IEU1 nop
ldxa [%o4] ASI_DCACHE_TAG, %g3 ! LSU Group stxa %g0, [%o2] ASI_DCACHE_TAG ! Invalidate TAG
add %o4, (1 << 5), %o4 ! IEU0 membar #Sync
andn %g1, DTAG_MASK, %g1 ! IEU1 2: brnz,pt %o2, 1b
cmp %o0, %o3 ! IEU1 Group sub %o2, (1 << 5), %o2 ! D-cache line size
be,a,pn %xcc, dflush1 ! CTI
sub %o4, (4 << 5), %o4 ! IEU0 (Group)
cmp %o0, %g1 ! IEU1 Group
andn %g2, DTAG_MASK, %g2 ! IEU0
be,a,pn %xcc, dflush2 ! CTI
sub %o4, (3 << 5), %o4 ! IEU0 (Group)
cmp %o0, %g2 ! IEU1 Group
andn %g3, DTAG_MASK, %g3 ! IEU0
be,a,pn %xcc, dflush3 ! CTI
sub %o4, (2 << 5), %o4 ! IEU0 (Group)
cmp %o0, %g3 ! IEU1 Group
be,a,pn %xcc, dflush4 ! CTI
sub %o4, (1 << 5), %o4 ! IEU0
2: cmp %o4, %o2 ! IEU1 Group
bne,pt %xcc, 1b ! CTI
nop ! IEU0
/* The I-cache does not snoop local stores so we /* The I-cache does not snoop local stores so we
* better flush that too when necessary. * better flush that too when necessary.
...@@ -189,48 +176,9 @@ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ ...@@ -189,48 +176,9 @@ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
retl retl
nop nop
dflush1:stxa %g0, [%o4] ASI_DCACHE_TAG
add %o4, (1 << 5), %o4
dflush2:stxa %g0, [%o4] ASI_DCACHE_TAG
add %o4, (1 << 5), %o4
dflush3:stxa %g0, [%o4] ASI_DCACHE_TAG
add %o4, (1 << 5), %o4
dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG
add %o4, (1 << 5), %o4
membar #Sync
ba,pt %xcc, 2b
nop
#endif /* DCACHE_ALIASING_POSSIBLE */ #endif /* DCACHE_ALIASING_POSSIBLE */
.previous .text .previous
.align 32
__prefill_dtlb:
rdpr %pstate, %g7
wrpr %g7, PSTATE_IE, %pstate
mov TLB_TAG_ACCESS, %g1
stxa %o5, [%g1] ASI_DMMU
stxa %o2, [%g0] ASI_DTLB_DATA_IN
flush %g6
retl
wrpr %g7, %pstate
__prefill_itlb:
rdpr %pstate, %g7
wrpr %g7, PSTATE_IE, %pstate
mov TLB_TAG_ACCESS, %g1
stxa %o5, [%g1] ASI_IMMU
stxa %o2, [%g0] ASI_ITLB_DATA_IN
flush %g6
retl
wrpr %g7, %pstate
.globl __update_mmu_cache
__update_mmu_cache: /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
srlx %o1, PAGE_SHIFT, %o1
andcc %o3, FAULT_CODE_DTLB, %g0
sllx %o1, PAGE_SHIFT, %o5
bne,pt %xcc, __prefill_dtlb
or %o5, %o0, %o5
ba,a,pt %xcc, __prefill_itlb
/* Cheetah specific versions, patched at boot time. */ /* Cheetah specific versions, patched at boot time. */
__cheetah_flush_tlb_mm: /* 18 insns */ __cheetah_flush_tlb_mm: /* 18 insns */
...@@ -283,7 +231,7 @@ __cheetah_flush_tlb_pending: /* 26 insns */ ...@@ -283,7 +231,7 @@ __cheetah_flush_tlb_pending: /* 26 insns */
wrpr %g7, 0x0, %pstate wrpr %g7, 0x0, %pstate
#ifdef DCACHE_ALIASING_POSSIBLE #ifdef DCACHE_ALIASING_POSSIBLE
flush_dcpage_cheetah: /* 11 insns */ __cheetah_flush_dcache_page: /* 11 insns */
sethi %uhi(PAGE_OFFSET), %g1 sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1 sllx %g1, 32, %g1
sub %o0, %g1, %o0 sub %o0, %g1, %o0
...@@ -329,8 +277,8 @@ cheetah_patch_cachetlbops: ...@@ -329,8 +277,8 @@ cheetah_patch_cachetlbops:
#ifdef DCACHE_ALIASING_POSSIBLE #ifdef DCACHE_ALIASING_POSSIBLE
sethi %hi(__flush_dcache_page), %o0 sethi %hi(__flush_dcache_page), %o0
or %o0, %lo(__flush_dcache_page), %o0 or %o0, %lo(__flush_dcache_page), %o0
sethi %hi(flush_dcpage_cheetah), %o1 sethi %hi(__cheetah_flush_dcache_page), %o1
or %o1, %lo(flush_dcpage_cheetah), %o1 or %o1, %lo(__cheetah_flush_dcache_page), %o1
call cheetah_patch_one call cheetah_patch_one
mov 11, %o2 mov 11, %o2
#endif /* DCACHE_ALIASING_POSSIBLE */ #endif /* DCACHE_ALIASING_POSSIBLE */
......
...@@ -7,4 +7,4 @@ EXTRA_AFLAGS := -ansi ...@@ -7,4 +7,4 @@ EXTRA_AFLAGS := -ansi
EXTRA_CFLAGS := -Werror EXTRA_CFLAGS := -Werror
lib-y := bootstr.o devops.o init.o memory.o misc.o \ lib-y := bootstr.o devops.o init.o memory.o misc.o \
tree.o console.o printf.o p1275.o map.o cif.o tree.o console.o printf.o p1275.o cif.o
...@@ -67,7 +67,7 @@ prom_putchar(char c) ...@@ -67,7 +67,7 @@ prom_putchar(char c)
} }
void void
prom_puts(char *s, int len) prom_puts(const char *s, int len)
{ {
p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
P1275_INOUT(3,1), P1275_INOUT(3,1),
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Returns 0 on failure. * Returns 0 on failure.
*/ */
int int
prom_devopen(char *dstr) prom_devopen(const char *dstr)
{ {
return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)| return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
P1275_INOUT(1,1), P1275_INOUT(1,1),
......
...@@ -46,7 +46,7 @@ void __init prom_init(void *cif_handler, void *cif_stack) ...@@ -46,7 +46,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
if((prom_root_node == 0) || (prom_root_node == -1)) if((prom_root_node == 0) || (prom_root_node == -1))
prom_halt(); prom_halt();
prom_chosen_node = prom_finddevice("/chosen"); prom_chosen_node = prom_finddevice(prom_chosen_path);
if (!prom_chosen_node || prom_chosen_node == -1) if (!prom_chosen_node || prom_chosen_node == -1)
prom_halt(); prom_halt();
......
/* $Id: map.S,v 1.2 1999/11/19 05:53:02 davem Exp $
* map.S: Tricky coding required to fixup the kernel OBP maps
* properly.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
.text
.align 8192
.globl prom_boot_page
prom_boot_page:
call_method:
.asciz "call-method"
.align 8
map:
.asciz "map"
.align 8
/* When we are invoked, our caller has remapped us to
* page zero, therefore we must use PC relative addressing
* for everything after we begin performing the unmap/map
* calls.
*/
.globl prom_remap
prom_remap: /* %o0 = physpage, %o1 = virtpage, %o2 = mmu_ihandle */
rd %pc, %g1
srl %o2, 0, %o2 ! kill sign extension
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
ldx [%g2 + 0x10], %g3 ! prom_cif_stack
save %g3, -(192 + 128), %sp
ldx [%g2 + 0x08], %l0 ! prom_cif_handler
mov %g6, %i3
mov %g4, %i4
mov %g5, %i5
flushw
sethi %hi(prom_remap - call_method), %g7
or %g7, %lo(prom_remap - call_method), %g7
sub %g1, %g7, %l2 ! call-method string
sethi %hi(prom_remap - map), %g7
or %g7, %lo(prom_remap - map), %g7
sub %g1, %g7, %l4 ! map string
/* OK, map the 4MB region we really live at. */
stx %l2, [%sp + 2047 + 128 + 0x00] ! call-method
mov 7, %l5
stx %l5, [%sp + 2047 + 128 + 0x08] ! num_args
mov 1, %l5
stx %l5, [%sp + 2047 + 128 + 0x10] ! num_rets
stx %l4, [%sp + 2047 + 128 + 0x18] ! map
stx %i2, [%sp + 2047 + 128 + 0x20] ! mmu_ihandle
mov -1, %l5
stx %l5, [%sp + 2047 + 128 + 0x28] ! mode == default
sethi %hi(4 * 1024 * 1024), %l5
stx %l5, [%sp + 2047 + 128 + 0x30] ! size
stx %i1, [%sp + 2047 + 128 + 0x38] ! vaddr
stx %g0, [%sp + 2047 + 128 + 0x40] ! filler
stx %i0, [%sp + 2047 + 128 + 0x48] ! paddr
call %l0
add %sp, (2047 + 128), %o0 ! argument array
/* Restore hard-coded globals. */
mov %i3, %g6
mov %i4, %g4
mov %i5, %g5
/* Wheee.... we are done. */
ret
restore
.align 8192
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
#include <asm/system.h> #include <asm/system.h>
/* Reset and reboot the machine with the command 'bcommand'. */ /* Reset and reboot the machine with the command 'bcommand'. */
void prom_reboot(char *bcommand) void prom_reboot(const char *bcommand)
{ {
p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) | p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_INOUT(1, 0), bcommand); P1275_INOUT(1, 0), bcommand);
} }
/* Forth evaluate the expression contained in 'fstring'. */ /* Forth evaluate the expression contained in 'fstring'. */
void prom_feval(char *fstring) void prom_feval(const char *fstring)
{ {
if (!fstring || fstring[0] == 0) if (!fstring || fstring[0] == 0)
return; return;
...@@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba) ...@@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba)
p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba); p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
} }
int mmu_ihandle_cache = 0;
int prom_get_mmu_ihandle(void) int prom_get_mmu_ihandle(void)
{ {
int node, ret; int node, ret;
if (mmu_ihandle_cache != 0) if (prom_mmu_ihandle_cache != 0)
return mmu_ihandle_cache; return prom_mmu_ihandle_cache;
node = prom_finddevice("/chosen"); node = prom_finddevice(prom_chosen_path);
ret = prom_getint(node, "mmu"); ret = prom_getint(node, prom_mmu_name);
if (ret == -1 || ret == 0) if (ret == -1 || ret == 0)
mmu_ihandle_cache = -1; prom_mmu_ihandle_cache = -1;
else else
mmu_ihandle_cache = ret; prom_mmu_ihandle_cache = ret;
return ret; return ret;
} }
...@@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index, ...@@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index,
unsigned long tte_data, unsigned long tte_data,
unsigned long vaddr) unsigned long vaddr)
{ {
return p1275_cmd("call-method", return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) | (P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) |
...@@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index, ...@@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index,
unsigned long tte_data, unsigned long tte_data,
unsigned long vaddr) unsigned long vaddr)
{ {
return p1275_cmd("call-method", return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) | (P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) |
...@@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index, ...@@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index,
int prom_map(int mode, unsigned long size, int prom_map(int mode, unsigned long size,
unsigned long vaddr, unsigned long paddr) unsigned long vaddr, unsigned long paddr)
{ {
int ret = p1275_cmd("call-method", int ret = p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) | (P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(3, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) |
P1275_ARG(4, P1275_ARG_IN_64B) | P1275_ARG(4, P1275_ARG_IN_64B) |
P1275_ARG(6, P1275_ARG_IN_64B) | P1275_ARG(6, P1275_ARG_IN_64B) |
P1275_INOUT(7, 1)), P1275_INOUT(7, 1)),
"map", prom_map_name,
prom_get_mmu_ihandle(), prom_get_mmu_ihandle(),
mode, mode,
size, size,
...@@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size, ...@@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size,
void prom_unmap(unsigned long size, unsigned long vaddr) void prom_unmap(unsigned long size, unsigned long vaddr)
{ {
p1275_cmd("call-method", p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) | (P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) |
P1275_INOUT(4, 0)), P1275_INOUT(4, 0)),
"unmap", prom_unmap_name,
prom_get_mmu_ihandle(), prom_get_mmu_ihandle(),
size, size,
vaddr); vaddr);
...@@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr) ...@@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr)
/* Set aside physical memory which is not touched or modified /* Set aside physical memory which is not touched or modified
* across soft resets. * across soft resets.
*/ */
unsigned long prom_retain(char *name, unsigned long prom_retain(const char *name,
unsigned long pa_low, unsigned long pa_high, unsigned long pa_low, unsigned long pa_high,
long size, long align) long size, long align)
{ {
...@@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code, ...@@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code,
unsigned long phys_addr, unsigned long phys_addr,
char *buf, int buflen) char *buf, int buflen)
{ {
return p1275_cmd("call-method", return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) | (P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(3, P1275_ARG_OUT_BUF) | P1275_ARG(3, P1275_ARG_OUT_BUF) |
P1275_ARG(6, P1275_ARG_IN_64B) | P1275_ARG(6, P1275_ARG_IN_64B) |
......
...@@ -46,7 +46,7 @@ static inline unsigned long spitfire_get_primary_context(void) ...@@ -46,7 +46,7 @@ static inline unsigned long spitfire_get_primary_context(void)
*/ */
DEFINE_SPINLOCK(prom_entry_lock); DEFINE_SPINLOCK(prom_entry_lock);
long p1275_cmd (char *service, long fmt, ...) long p1275_cmd(const char *service, long fmt, ...)
{ {
char *p, *q; char *p, *q;
unsigned long flags; unsigned long flags;
......
...@@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n) ...@@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n)
} }
void void
prom_printf(char *fmt, ...) prom_printf(const char *fmt, ...)
{ {
va_list args; va_list args;
int i; int i;
......
...@@ -69,7 +69,7 @@ prom_getsibling(int node) ...@@ -69,7 +69,7 @@ prom_getsibling(int node)
* Return -1 on error. * Return -1 on error.
*/ */
__inline__ int __inline__ int
prom_getproplen(int node, char *prop) prom_getproplen(int node, const char *prop)
{ {
if((!node) || (!prop)) return -1; if((!node) || (!prop)) return -1;
return p1275_cmd ("getproplen", return p1275_cmd ("getproplen",
...@@ -83,20 +83,20 @@ prom_getproplen(int node, char *prop) ...@@ -83,20 +83,20 @@ prom_getproplen(int node, char *prop)
* was successful the length will be returned, else -1 is returned. * was successful the length will be returned, else -1 is returned.
*/ */
__inline__ int __inline__ int
prom_getproperty(int node, char *prop, char *buffer, int bufsize) prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
{ {
int plen; int plen;
plen = prom_getproplen(node, prop); plen = prom_getproplen(node, prop);
if((plen > bufsize) || (plen == 0) || (plen == -1)) if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
return -1; return -1;
else { } else {
/* Ok, things seem all right. */ /* Ok, things seem all right. */
return p1275_cmd ("getprop", return p1275_cmd(prom_getprop_name,
P1275_ARG(1,P1275_ARG_IN_STRING)| P1275_ARG(1,P1275_ARG_IN_STRING)|
P1275_ARG(2,P1275_ARG_OUT_BUF)| P1275_ARG(2,P1275_ARG_OUT_BUF)|
P1275_INOUT(4, 1), P1275_INOUT(4, 1),
node, prop, buffer, P1275_SIZE(plen)); node, prop, buffer, P1275_SIZE(plen));
} }
} }
...@@ -104,7 +104,7 @@ prom_getproperty(int node, char *prop, char *buffer, int bufsize) ...@@ -104,7 +104,7 @@ prom_getproperty(int node, char *prop, char *buffer, int bufsize)
* on failure. * on failure.
*/ */
__inline__ int __inline__ int
prom_getint(int node, char *prop) prom_getint(int node, const char *prop)
{ {
int intprop; int intprop;
...@@ -119,7 +119,7 @@ prom_getint(int node, char *prop) ...@@ -119,7 +119,7 @@ prom_getint(int node, char *prop)
*/ */
int int
prom_getintdefault(int node, char *property, int deflt) prom_getintdefault(int node, const char *property, int deflt)
{ {
int retval; int retval;
...@@ -131,7 +131,7 @@ prom_getintdefault(int node, char *property, int deflt) ...@@ -131,7 +131,7 @@ prom_getintdefault(int node, char *property, int deflt)
/* Acquire a boolean property, 1=TRUE 0=FALSE. */ /* Acquire a boolean property, 1=TRUE 0=FALSE. */
int int
prom_getbool(int node, char *prop) prom_getbool(int node, const char *prop)
{ {
int retval; int retval;
...@@ -145,7 +145,7 @@ prom_getbool(int node, char *prop) ...@@ -145,7 +145,7 @@ prom_getbool(int node, char *prop)
* buffer. * buffer.
*/ */
void void
prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
{ {
int len; int len;
...@@ -160,7 +160,7 @@ prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) ...@@ -160,7 +160,7 @@ prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
* YES = 1 NO = 0 * YES = 1 NO = 0
*/ */
int int
prom_nodematch(int node, char *name) prom_nodematch(int node, const char *name)
{ {
char namebuf[128]; char namebuf[128];
prom_getproperty(node, "name", namebuf, sizeof(namebuf)); prom_getproperty(node, "name", namebuf, sizeof(namebuf));
...@@ -172,7 +172,7 @@ prom_nodematch(int node, char *name) ...@@ -172,7 +172,7 @@ prom_nodematch(int node, char *name)
* 'nodename'. Return node if successful, zero if not. * 'nodename'. Return node if successful, zero if not.
*/ */
int int
prom_searchsiblings(int node_start, char *nodename) prom_searchsiblings(int node_start, const char *nodename)
{ {
int thisnode, error; int thisnode, error;
...@@ -294,7 +294,7 @@ prom_firstprop(int node, char *buffer) ...@@ -294,7 +294,7 @@ prom_firstprop(int node, char *buffer)
* property types for this node. * property types for this node.
*/ */
__inline__ char * __inline__ char *
prom_nextprop(int node, char *oprop, char *buffer) prom_nextprop(int node, const char *oprop, char *buffer)
{ {
char buf[32]; char buf[32];
...@@ -314,15 +314,17 @@ prom_nextprop(int node, char *oprop, char *buffer) ...@@ -314,15 +314,17 @@ prom_nextprop(int node, char *oprop, char *buffer)
} }
int int
prom_finddevice(char *name) prom_finddevice(const char *name)
{ {
if(!name) return 0; if (!name)
return p1275_cmd ("finddevice", P1275_ARG(0,P1275_ARG_IN_STRING)| return 0;
P1275_INOUT(1, 1), return p1275_cmd(prom_finddev_name,
name); P1275_ARG(0,P1275_ARG_IN_STRING)|
P1275_INOUT(1, 1),
name);
} }
int prom_node_has_property(int node, char *prop) int prom_node_has_property(int node, const char *prop)
{ {
char buf [32]; char buf [32];
...@@ -339,7 +341,7 @@ int prom_node_has_property(int node, char *prop) ...@@ -339,7 +341,7 @@ int prom_node_has_property(int node, char *prop)
* of 'size' bytes. Return the number of bytes the prom accepted. * of 'size' bytes. Return the number of bytes the prom accepted.
*/ */
int int
prom_setprop(int node, char *pname, char *value, int size) prom_setprop(int node, const char *pname, char *value, int size)
{ {
if(size == 0) return 0; if(size == 0) return 0;
if((pname == 0) || (value == 0)) return 0; if((pname == 0) || (value == 0)) return 0;
...@@ -364,7 +366,7 @@ prom_inst2pkg(int inst) ...@@ -364,7 +366,7 @@ prom_inst2pkg(int inst)
* FIXME: Should work for v0 as well * FIXME: Should work for v0 as well
*/ */
int int
prom_pathtoinode(char *path) prom_pathtoinode(const char *path)
{ {
int node, inst; int node, inst;
......
...@@ -959,9 +959,6 @@ static __init int unsynchronized_tsc(void) ...@@ -959,9 +959,6 @@ static __init int unsynchronized_tsc(void)
are handled in the OEM check above. */ are handled in the OEM check above. */
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
return 0; return 0;
/* All in a single socket - should be synchronized */
if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
return 0;
#endif #endif
/* Assume multi socket systems are not synchronized */ /* Assume multi socket systems are not synchronized */
return num_online_cpus() > 1; return num_online_cpus() > 1;
......
...@@ -55,7 +55,7 @@ extern void (*pm_power_off)(void); ...@@ -55,7 +55,7 @@ extern void (*pm_power_off)(void);
static int poweroff_powercycle; static int poweroff_powercycle;
/* parameter definition to allow user to flag power cycle */ /* parameter definition to allow user to flag power cycle */
module_param(poweroff_powercycle, int, 0); module_param(poweroff_powercycle, int, 0644);
MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
/* Stuff from the get device id command. */ /* Stuff from the get device id command. */
......
...@@ -31,16 +31,19 @@ ...@@ -31,16 +31,19 @@
#include <linux/connector.h> #include <linux/connector.h>
#include <linux/delay.h> #include <linux/delay.h>
static void cn_queue_wrapper(void *data) void cn_queue_wrapper(void *data)
{ {
struct cn_callback_entry *cbq = data; struct cn_callback_data *d = data;
cbq->cb->callback(cbq->cb->priv); d->callback(d->callback_priv);
cbq->destruct_data(cbq->ddata);
cbq->ddata = NULL; d->destruct_data(d->ddata);
d->ddata = NULL;
kfree(d->free);
} }
static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb) static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
{ {
struct cn_callback_entry *cbq; struct cn_callback_entry *cbq;
...@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac ...@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac
return NULL; return NULL;
} }
cbq->cb = cb; snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq); memcpy(&cbq->id.id, id, sizeof(struct cb_id));
cbq->data.callback = callback;
INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
return cbq; return cbq;
} }
...@@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2) ...@@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
return ((i1->idx == i2->idx) && (i1->val == i2->val)); return ((i1->idx == i2->idx) && (i1->val == i2->val));
} }
int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
{ {
struct cn_callback_entry *cbq, *__cbq; struct cn_callback_entry *cbq, *__cbq;
int found = 0; int found = 0;
cbq = cn_queue_alloc_callback_entry(cb); cbq = cn_queue_alloc_callback_entry(name, id, callback);
if (!cbq) if (!cbq)
return -ENOMEM; return -ENOMEM;
...@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) ...@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
list_for_each_entry(__cbq, &dev->queue_list, callback_entry) { list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &cb->id)) { if (cn_cb_equal(&__cbq->id.id, id)) {
found = 1; found = 1;
break; break;
} }
...@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) ...@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
cbq->nls = dev->nls; cbq->nls = dev->nls;
cbq->seq = 0; cbq->seq = 0;
cbq->group = cbq->cb->id.idx; cbq->group = cbq->id.id.idx;
return 0; return 0;
} }
...@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id) ...@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) { list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&cbq->cb->id, id)) { if (cn_cb_equal(&cbq->id.id, id)) {
list_del(&cbq->callback_entry); list_del(&cbq->callback_entry);
found = 1; found = 1;
break; break;
......
...@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask) ...@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
spin_lock_bh(&dev->cbdev->queue_lock); spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, list_for_each_entry(__cbq, &dev->cbdev->queue_list,
callback_entry) { callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
found = 1; found = 1;
group = __cbq->group; group = __cbq->group;
} }
...@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v ...@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
{ {
struct cn_callback_entry *__cbq; struct cn_callback_entry *__cbq;
struct cn_dev *dev = &cdev; struct cn_dev *dev = &cdev;
int found = 0; int err = -ENODEV;
spin_lock_bh(&dev->cbdev->queue_lock); spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
/*
* Let's scream if there is some magic and the
* data will arrive asynchronously here.
* [i.e. netlink messages will be queued].
* After the first warning I will fix it
* quickly, but now I think it is
* impossible. --zbr (2004_04_27).
*/
if (likely(!test_bit(0, &__cbq->work.pending) && if (likely(!test_bit(0, &__cbq->work.pending) &&
__cbq->ddata == NULL)) { __cbq->data.ddata == NULL)) {
__cbq->cb->priv = msg; __cbq->data.callback_priv = msg;
__cbq->ddata = data; __cbq->data.ddata = data;
__cbq->destruct_data = destruct_data; __cbq->data.destruct_data = destruct_data;
if (queue_work(dev->cbdev->cn_queue, if (queue_work(dev->cbdev->cn_queue,
&__cbq->work)) &__cbq->work))
found = 1; err = 0;
} else { } else {
printk("%s: cbq->data=%p, " struct work_struct *w;
"work->pending=%08lx.\n", struct cn_callback_data *d;
__func__, __cbq->ddata,
__cbq->work.pending); w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
WARN_ON(1); if (w) {
d = (struct cn_callback_data *)(w+1);
d->callback_priv = msg;
d->callback = __cbq->data.callback;
d->ddata = data;
d->destruct_data = destruct_data;
d->free = w;
INIT_LIST_HEAD(&w->entry);
w->pending = 0;
w->func = &cn_queue_wrapper;
w->data = d;
init_timer(&w->timer);
if (queue_work(dev->cbdev->cn_queue, w))
err = 0;
else {
kfree(w);
err = -EINVAL;
}
} else
err = -ENOMEM;
} }
break; break;
} }
} }
spin_unlock_bh(&dev->cbdev->queue_lock); spin_unlock_bh(&dev->cbdev->queue_lock);
return found ? 0 : -ENODEV; return err;
} }
/* /*
...@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *)) ...@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
{ {
int err; int err;
struct cn_dev *dev = &cdev; struct cn_dev *dev = &cdev;
struct cn_callback *cb;
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
return -ENOMEM;
scnprintf(cb->name, sizeof(cb->name), "%s", name);
memcpy(&cb->id, id, sizeof(cb->id)); err = cn_queue_add_callback(dev->cbdev, name, id, callback);
cb->callback = callback; if (err)
err = cn_queue_add_callback(dev->cbdev, cb);
if (err) {
kfree(cb);
return err; return err;
}
cn_notify(id, 0); cn_notify(id, 0);
......
...@@ -477,7 +477,7 @@ static struct pcmcia_device_id ide_ids[] = { ...@@ -477,7 +477,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b),
PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79), PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
......
...@@ -69,6 +69,7 @@ struct ib_uverbs_event_file { ...@@ -69,6 +69,7 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file { struct ib_uverbs_file {
struct kref ref; struct kref ref;
struct semaphore mutex;
struct ib_uverbs_device *device; struct ib_uverbs_device *device;
struct ib_ucontext *ucontext; struct ib_ucontext *ucontext;
struct ib_event_handler event_handler; struct ib_event_handler event_handler;
......
...@@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, ...@@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
struct ib_uverbs_get_context_resp resp; struct ib_uverbs_get_context_resp resp;
struct ib_udata udata; struct ib_udata udata;
struct ib_device *ibdev = file->device->ib_dev; struct ib_device *ibdev = file->device->ib_dev;
struct ib_ucontext *ucontext;
int i; int i;
int ret = in_len; int ret;
if (out_len < sizeof resp) if (out_len < sizeof resp)
return -ENOSPC; return -ENOSPC;
...@@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, ...@@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd)) if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT; return -EFAULT;
down(&file->mutex);
if (file->ucontext) {
ret = -EINVAL;
goto err;
}
INIT_UDATA(&udata, buf + sizeof cmd, INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp, (unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp); in_len - sizeof cmd, out_len - sizeof resp);
file->ucontext = ibdev->alloc_ucontext(ibdev, &udata); ucontext = ibdev->alloc_ucontext(ibdev, &udata);
if (IS_ERR(file->ucontext)) { if (IS_ERR(ucontext))
ret = PTR_ERR(file->ucontext); return PTR_ERR(file->ucontext);
file->ucontext = NULL;
return ret;
}
file->ucontext->device = ibdev; ucontext->device = ibdev;
INIT_LIST_HEAD(&file->ucontext->pd_list); INIT_LIST_HEAD(&ucontext->pd_list);
INIT_LIST_HEAD(&file->ucontext->mr_list); INIT_LIST_HEAD(&ucontext->mr_list);
INIT_LIST_HEAD(&file->ucontext->mw_list); INIT_LIST_HEAD(&ucontext->mw_list);
INIT_LIST_HEAD(&file->ucontext->cq_list); INIT_LIST_HEAD(&ucontext->cq_list);
INIT_LIST_HEAD(&file->ucontext->qp_list); INIT_LIST_HEAD(&ucontext->qp_list);
INIT_LIST_HEAD(&file->ucontext->srq_list); INIT_LIST_HEAD(&ucontext->srq_list);
INIT_LIST_HEAD(&file->ucontext->ah_list); INIT_LIST_HEAD(&ucontext->ah_list);
spin_lock_init(&file->ucontext->lock);
resp.async_fd = file->async_file.fd; resp.async_fd = file->async_file.fd;
for (i = 0; i < file->device->num_comp; ++i) for (i = 0; i < file->device->num_comp; ++i)
if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab + if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
i * sizeof (__u32), i * sizeof (__u32),
&file->comp_file[i].fd, sizeof (__u32))) &file->comp_file[i].fd, sizeof (__u32))) {
goto err; ret = -EFAULT;
goto err_free;
}
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) &resp, sizeof resp)) {
goto err; ret = -EFAULT;
goto err_free;
}
file->ucontext = ucontext;
up(&file->mutex);
return in_len; return in_len;
err: err_free:
ibdev->dealloc_ucontext(file->ucontext); ibdev->dealloc_ucontext(ucontext);
file->ucontext = NULL;
return -EFAULT; err:
up(&file->mutex);
return ret;
} }
ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
...@@ -352,9 +364,9 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, ...@@ -352,9 +364,9 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
if (ret) if (ret)
goto err_pd; goto err_pd;
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list); list_add_tail(&uobj->list, &file->ucontext->pd_list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
memset(&resp, 0, sizeof resp); memset(&resp, 0, sizeof resp);
resp.pd_handle = uobj->id; resp.pd_handle = uobj->id;
...@@ -368,9 +380,9 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, ...@@ -368,9 +380,9 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
return in_len; return in_len;
err_list: err_list:
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->list); list_del(&uobj->list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
down(&ib_uverbs_idr_mutex); down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_pd_idr, uobj->id); idr_remove(&ib_uverbs_pd_idr, uobj->id);
...@@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, ...@@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->list); list_del(&uobj->list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
kfree(uobj); kfree(uobj);
...@@ -512,9 +524,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, ...@@ -512,9 +524,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
resp.mr_handle = obj->uobject.id; resp.mr_handle = obj->uobject.id;
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
...@@ -527,9 +539,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, ...@@ -527,9 +539,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
return in_len; return in_len;
err_list: err_list:
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&obj->uobject.list); list_del(&obj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
err_unreg: err_unreg:
ib_dereg_mr(mr); ib_dereg_mr(mr);
...@@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, ...@@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&memobj->uobject.list); list_del(&memobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem); ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj); kfree(memobj);
...@@ -647,9 +659,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, ...@@ -647,9 +659,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (ret) if (ret)
goto err_cq; goto err_cq;
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
memset(&resp, 0, sizeof resp); memset(&resp, 0, sizeof resp);
resp.cq_handle = uobj->uobject.id; resp.cq_handle = uobj->uobject.id;
...@@ -664,9 +676,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, ...@@ -664,9 +676,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
return in_len; return in_len;
err_list: err_list:
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
down(&ib_uverbs_idr_mutex); down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
...@@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, ...@@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
spin_lock_irq(&file->comp_file[0].lock); spin_lock_irq(&file->comp_file[0].lock);
list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) { list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
...@@ -847,9 +859,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, ...@@ -847,9 +859,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
resp.qp_handle = uobj->uobject.id; resp.qp_handle = uobj->uobject.id;
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
...@@ -862,9 +874,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, ...@@ -862,9 +874,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
return in_len; return in_len;
err_list: err_list:
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
err_destroy: err_destroy:
ib_destroy_qp(qp); ib_destroy_qp(qp);
...@@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, ...@@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
spin_lock_irq(&file->async_file.lock); spin_lock_irq(&file->async_file.lock);
list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
...@@ -1136,9 +1148,9 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, ...@@ -1136,9 +1148,9 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
resp.srq_handle = uobj->uobject.id; resp.srq_handle = uobj->uobject.id;
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
...@@ -1151,9 +1163,9 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, ...@@ -1151,9 +1163,9 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
return in_len; return in_len;
err_list: err_list:
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
err_destroy: err_destroy:
ib_destroy_srq(srq); ib_destroy_srq(srq);
...@@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, ...@@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
spin_lock_irq(&file->ucontext->lock); down(&file->mutex);
list_del(&uobj->uobject.list); list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock); up(&file->mutex);
spin_lock_irq(&file->async_file.lock); spin_lock_irq(&file->async_file.lock);
list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
......
...@@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ...@@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count) if (hdr.in_words * 4 != count)
return -EINVAL; return -EINVAL;
if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table)) if (hdr.command < 0 ||
hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
!uverbs_cmd_table[hdr.command])
return -EINVAL; return -EINVAL;
if (!file->ucontext && if (!file->ucontext &&
...@@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file = kmalloc(sizeof *file + file = kmalloc(sizeof *file +
(dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file), (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
GFP_KERNEL); GFP_KERNEL);
if (!file) if (!file) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
file->device = dev; file->device = dev;
kref_init(&file->ref); kref_init(&file->ref);
init_MUTEX(&file->mutex);
file->ucontext = NULL; file->ucontext = NULL;
kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->async_file, file); ret = ib_uverbs_event_init(&file->async_file, file);
if (ret) if (ret)
goto err; goto err_kref;
file->async_file.is_async = 1; file->async_file.is_async = 1;
kref_get(&file->ref);
for (i = 0; i < dev->num_comp; ++i) { for (i = 0; i < dev->num_comp; ++i) {
kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->comp_file[i], file); ret = ib_uverbs_event_init(&file->comp_file[i], file);
if (ret) if (ret)
goto err_async; goto err_async;
kref_get(&file->ref);
file->comp_file[i].is_async = 0; file->comp_file[i].is_async = 0;
} }
...@@ -524,9 +528,16 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -524,9 +528,16 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
ib_uverbs_event_release(&file->async_file); ib_uverbs_event_release(&file->async_file);
err: err_kref:
/*
* One extra kref_put() because we took a reference before the
* event file creation that failed and got us here.
*/
kref_put(&file->ref, ib_uverbs_release_file);
kref_put(&file->ref, ib_uverbs_release_file); kref_put(&file->ref, ib_uverbs_release_file);
err:
module_put(dev->ib_dev->owner);
return ret; return ret;
} }
......
...@@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, ...@@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) { for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) {
if (virt != -1) { if (virt != -1) {
pages[nent * 2] = cpu_to_be64(virt); pages[nent * 2] = cpu_to_be64(virt);
virt += 1 << lg; virt += 1 << lg;
...@@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, ...@@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
ts += 1 << (lg - 10); ts += 1 << (lg - 10);
++tc; ++tc;
if (nent == MTHCA_MAILBOX_SIZE / 16) { if (++nent == MTHCA_MAILBOX_SIZE / 16) {
err = mthca_cmd(dev, mailbox->dma, nent, 0, op, err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
CMD_TIME_CLASS_B, status); CMD_TIME_CLASS_B, status);
if (err || *status) if (err || *status)
......
...@@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) ...@@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
dev->eq_table.clr_mask = dev->eq_table.clr_mask =
swab32(1 << (dev->eq_table.inta_pin & 31)); swab32(1 << (dev->eq_table.inta_pin & 31));
dev->eq_table.clr_int = dev->clr_base + dev->eq_table.clr_int = dev->clr_base +
(dev->eq_table.inta_pin < 31 ? 4 : 0); (dev->eq_table.inta_pin < 32 ? 4 : 0);
} }
dev->eq_table.arm_mask = 0; dev->eq_table.arm_mask = 0;
......
...@@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, ...@@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
int i; int i;
u8 status; u8 status;
num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE; num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL); table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
if (!table) if (!table)
...@@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) ...@@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
goto found; goto found;
} }
for (i = start; i != end; i += dir)
if (!dev->db_tab->page[i].db_rec) {
page = dev->db_tab->page + i;
goto alloc;
}
if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) { if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
if (group == 0)
++dev->db_tab->max_group1;
else
--dev->db_tab->min_group2;
page = dev->db_tab->page + end; page = dev->db_tab->page + end;
alloc:
page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096, page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
&page->mapping, GFP_KERNEL); &page->mapping, GFP_KERNEL);
if (!page->db_rec) { if (!page->db_rec) {
...@@ -554,10 +567,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) ...@@ -554,10 +567,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
} }
bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE); bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
if (group == 0)
++dev->db_tab->max_group1;
else
--dev->db_tab->min_group2;
found: found:
j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE); j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
......
...@@ -84,7 +84,7 @@ static int mthca_query_device(struct ib_device *ibdev, ...@@ -84,7 +84,7 @@ static int mthca_query_device(struct ib_device *ibdev,
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff; 0xffffff;
props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30));
props->hw_ver = be16_to_cpup((__be16 *) (out_mad->data + 32)); props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32));
memcpy(&props->sys_image_guid, out_mad->data + 4, 8); memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
memcpy(&props->node_guid, out_mad->data + 12, 8); memcpy(&props->node_guid, out_mad->data + 12, 8);
......
...@@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi ...@@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi
static void __hash_remove(struct hash_cell *hc) static void __hash_remove(struct hash_cell *hc)
{ {
struct dm_table *table;
/* remove from the dev hash */ /* remove from the dev hash */
list_del(&hc->uuid_list); list_del(&hc->uuid_list);
list_del(&hc->name_list); list_del(&hc->name_list);
unregister_with_devfs(hc); unregister_with_devfs(hc);
dm_set_mdptr(hc->md, NULL); dm_set_mdptr(hc->md, NULL);
table = dm_get_table(hc->md);
if (table) {
dm_table_event(table);
dm_table_put(table);
}
dm_put(hc->md); dm_put(hc->md);
if (hc->new_map) if (hc->new_map)
dm_table_put(hc->new_map); dm_table_put(hc->new_map);
......
...@@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, ...@@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
/* /*
* If we run out of usable paths, should we queue I/O or error it? * If we run out of usable paths, should we queue I/O or error it?
*/ */
static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path) static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
unsigned save_old_value)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&m->lock, flags); spin_lock_irqsave(&m->lock, flags);
m->saved_queue_if_no_path = m->queue_if_no_path; if (save_old_value)
m->saved_queue_if_no_path = m->queue_if_no_path;
else
m->saved_queue_if_no_path = queue_if_no_path;
m->queue_if_no_path = queue_if_no_path; m->queue_if_no_path = queue_if_no_path;
if (!m->queue_if_no_path && m->queue_size) if (!m->queue_if_no_path && m->queue_size)
queue_work(kmultipathd, &m->process_queued_ios); queue_work(kmultipathd, &m->process_queued_ios);
...@@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m, ...@@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m,
return 0; return 0;
if (!strnicmp(shift(as), MESG_STR("queue_if_no_path"))) if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
return queue_if_no_path(m, 1); return queue_if_no_path(m, 1, 0);
else { else {
ti->error = "Unrecognised multipath feature request"; ti->error = "Unrecognised multipath feature request";
return -EINVAL; return -EINVAL;
...@@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti) ...@@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti)
{ {
struct multipath *m = (struct multipath *) ti->private; struct multipath *m = (struct multipath *) ti->private;
queue_if_no_path(m, 0); queue_if_no_path(m, 0, 1);
} }
/* /*
...@@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) ...@@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
if (argc == 1) { if (argc == 1) {
if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
return queue_if_no_path(m, 1); return queue_if_no_path(m, 1, 0);
else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
return queue_if_no_path(m, 0); return queue_if_no_path(m, 0, 0);
} }
if (argc != 2) if (argc != 2)
......
...@@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) ...@@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
ret = i2c_transfer (state->i2c, msg, 2); ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2) if (ret != 2)
printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n", printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
state->frontend.dvb->num, __FUNCTION__, ret); __FUNCTION__, ret);
return b1[0]; return b1[0];
} }
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#if ALLOW_DMA #if ALLOW_DMA
#include <asm/dma.h> #include <asm/dma.h>
#endif #endif
......
...@@ -67,8 +67,8 @@ ...@@ -67,8 +67,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.40" #define DRV_MODULE_VERSION "3.41"
#define DRV_MODULE_RELDATE "September 15, 2005" #define DRV_MODULE_RELDATE "September 27, 2005"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, ...@@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
struct tg3 *tp = netdev_priv(dev); struct tg3 *tp = netdev_priv(dev);
struct tg3_hw_status *sblk = tp->hw_status; struct tg3_hw_status *sblk = tp->hw_status;
if (sblk->status & SD_STATUS_UPDATED) { if ((sblk->status & SD_STATUS_UPDATED) ||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001); 0x00000001);
return IRQ_RETVAL(1); return IRQ_RETVAL(1);
...@@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) ...@@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
struct tg3 *tp = netdev_priv(dev); struct tg3 *tp = netdev_priv(dev);
struct sockaddr *addr = p; struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_bh(&tp->lock); spin_lock_bh(&tp->lock);
...@@ -5806,6 +5810,13 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5806,6 +5810,13 @@ static int tg3_reset_hw(struct tg3 *tp)
} }
memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
/* reset to prevent losing 1st rx packet intermittently */
tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10);
}
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
...@@ -5937,7 +5948,7 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5937,7 +5948,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_LED_CTRL, tp->led_ctrl);
tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
tw32_f(MAC_RX_MODE, RX_MODE_RESET); tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10); udelay(10);
} }
...@@ -7360,12 +7371,17 @@ static int tg3_nway_reset(struct net_device *dev) ...@@ -7360,12 +7371,17 @@ static int tg3_nway_reset(struct net_device *dev)
if (!netif_running(dev)) if (!netif_running(dev))
return -EAGAIN; return -EAGAIN;
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
return -EINVAL;
spin_lock_bh(&tp->lock); spin_lock_bh(&tp->lock);
r = -EINVAL; r = -EINVAL;
tg3_readphy(tp, MII_BMCR, &bmcr); tg3_readphy(tp, MII_BMCR, &bmcr);
if (!tg3_readphy(tp, MII_BMCR, &bmcr) && if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
(bmcr & BMCR_ANENABLE)) { ((bmcr & BMCR_ANENABLE) ||
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE);
r = 0; r = 0;
} }
spin_unlock_bh(&tp->lock); spin_unlock_bh(&tp->lock);
...@@ -7927,19 +7943,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) ...@@ -7927,19 +7943,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
struct tg3_rx_buffer_desc *desc; struct tg3_rx_buffer_desc *desc;
if (loopback_mode == TG3_MAC_LOOPBACK) { if (loopback_mode == TG3_MAC_LOOPBACK) {
/* HW errata - mac loopback fails in some cases on 5780.
* Normal traffic and PHY loopback are not affected by
* errata.
*/
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
return 0;
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
MAC_MODE_PORT_MODE_GMII; MAC_MODE_PORT_MODE_GMII;
tw32(MAC_MODE, mac_mode); tw32(MAC_MODE, mac_mode);
} else if (loopback_mode == TG3_PHY_LOOPBACK) { } else if (loopback_mode == TG3_PHY_LOOPBACK) {
tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
BMCR_SPEED1000);
udelay(40);
/* reset to prevent losing 1st rx packet intermittently */
if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10);
tw32_f(MAC_RX_MODE, tp->rx_mode);
}
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
mac_mode &= ~MAC_MODE_LINK_POLARITY; mac_mode &= ~MAC_MODE_LINK_POLARITY;
tw32(MAC_MODE, mac_mode); tw32(MAC_MODE, mac_mode);
tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
BMCR_SPEED1000);
} }
else else
return -EINVAL; return -EINVAL;
...@@ -10324,6 +10353,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) ...@@ -10324,6 +10353,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
}; };
} }
static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
{
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
strcpy(str, "PCI Express");
return str;
} else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
strcpy(str, "PCIX:");
if ((clock_ctrl == 7) ||
((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) ==
GRC_MISC_CFG_BOARD_ID_5704CIOBE))
strcat(str, "133MHz");
else if (clock_ctrl == 0)
strcat(str, "33MHz");
else if (clock_ctrl == 2)
strcat(str, "50MHz");
else if (clock_ctrl == 4)
strcat(str, "66MHz");
else if (clock_ctrl == 6)
strcat(str, "100MHz");
else if (clock_ctrl == 7)
strcat(str, "133MHz");
} else {
strcpy(str, "PCI:");
if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED)
strcat(str, "66MHz");
else
strcat(str, "33MHz");
}
if (tp->tg3_flags & TG3_FLAG_PCI_32BIT)
strcat(str, ":32-bit");
else
strcat(str, ":64-bit");
return str;
}
static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
{ {
struct pci_dev *peer; struct pci_dev *peer;
...@@ -10386,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, ...@@ -10386,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
struct net_device *dev; struct net_device *dev;
struct tg3 *tp; struct tg3 *tp;
int i, err, pci_using_dac, pm_cap; int i, err, pci_using_dac, pm_cap;
char str[40];
if (tg3_version_printed++ == 0) if (tg3_version_printed++ == 0)
printk(KERN_INFO "%s", version); printk(KERN_INFO "%s", version);
...@@ -10631,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, ...@@ -10631,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
dev->name, dev->name,
tp->board_part_number, tp->board_part_number,
tp->pci_chip_rev_id, tp->pci_chip_rev_id,
tg3_phy_string(tp), tg3_phy_string(tp),
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""), tg3_bus_string(tp, str),
((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
(tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
......
...@@ -2246,6 +2246,7 @@ struct tg3 { ...@@ -2246,6 +2246,7 @@ struct tg3 {
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
(X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \
(X) == PHY_ID_BCM8002) (X) == PHY_ID_BCM8002)
struct tg3_hw_stats *hw_stats; struct tg3_hw_stats *hw_stats;
......
...@@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card, ...@@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->watchdog_timeo = HZ; /* 1 second timeout */
dev->get_stats = orinoco_get_stats; dev->get_stats = orinoco_get_stats;
dev->ethtool_ops = &orinoco_ethtool_ops; dev->ethtool_ops = &orinoco_ethtool_ops;
dev->get_wireless_stats = orinoco_get_wireless_stats;
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
dev->change_mtu = orinoco_change_mtu; dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list; dev->set_multicast_list = orinoco_set_multicast_list;
...@@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = { ...@@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = {
.standard = orinoco_handler, .standard = orinoco_handler,
.private = orinoco_private_handler, .private = orinoco_private_handler,
.private_args = orinoco_privtab, .private_args = orinoco_privtab,
.get_wireless_stats = orinoco_get_wireless_stats,
}; };
static void orinoco_get_drvinfo(struct net_device *dev, static void orinoco_get_drvinfo(struct net_device *dev,
......
...@@ -146,7 +146,7 @@ config I82365 ...@@ -146,7 +146,7 @@ config I82365
config TCIC config TCIC
tristate "Databook TCIC host bridge support" tristate "Databook TCIC host bridge support"
depends on PCMCIA depends on PCMCIA && ISA
select PCCARD_NONSTATIC select PCCARD_NONSTATIC
help help
Say Y here to include support for the Databook TCIC family of PCMCIA Say Y here to include support for the Databook TCIC family of PCMCIA
......
...@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s) ...@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
cardbus_assign_irqs(bus, s->pci_irq); cardbus_assign_irqs(bus, s->pci_irq);
/* socket specific tune function */
if (s->tune_bridge)
s->tune_bridge(s, bus);
pci_enable_bridges(bus); pci_enable_bridges(bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
......
此差异已折叠。
此差异已折叠。
...@@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = { ...@@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
......
此差异已折叠。
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define FID_OP 0 #define FID_OP 0
#define FID_WALK 1 #define FID_WALK 1
#define FID_CREATE 2
struct v9fs_fid { struct v9fs_fid {
struct list_head list; /* list of fids associated with a dentry */ struct list_head list; /* list of fids associated with a dentry */
...@@ -52,6 +53,8 @@ struct v9fs_fid { ...@@ -52,6 +53,8 @@ struct v9fs_fid {
struct v9fs_session_info *v9ses; /* session info for this FID */ struct v9fs_session_info *v9ses; /* session info for this FID */
}; };
struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry);
struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
void v9fs_fid_destroy(struct v9fs_fid *fid); void v9fs_fid_destroy(struct v9fs_fid *fid);
struct v9fs_fid *v9fs_fid_create(struct dentry *); struct v9fs_fid *v9fs_fid_create(struct dentry *,
struct v9fs_session_info *v9ses, int fid, int create);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册