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

Merge by hand from Linus' tree.

Signed-off-by: NPaul Mackerras <paulus@samba.org>
......@@ -237,6 +237,12 @@ udev
udev is a userspace application for populating /dev dynamically with
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
==========
......@@ -390,6 +396,10 @@ udev
----
o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
FUSE
----
o <http://sourceforge.net/projects/fuse>
Networking
**********
......
......@@ -195,8 +195,8 @@ KEY ACCESS PERMISSIONS
======================
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
set of eight bits are defined. These permissions granted are:
has up to eight bits each for possessor, user, group and other access. Only
five of each set of eight bits are defined. These permissions granted are:
(*) View
......@@ -241,16 +241,16 @@ about the status of the key service:
type, description and permissions. The payload of the key is not available
this way:
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4
00000002 I----- 2 perm 1f0000 0 0 keyring _uid.0: empty
00000007 I----- 1 perm 1f0000 0 0 keyring _pid.1: empty
0000018d I----- 1 perm 1f0000 0 0 keyring _pid.412: empty
000004d2 I--Q-- 1 perm 1f0000 32 -1 keyring _uid.32: 1/4
000004d3 I--Q-- 3 perm 1f0000 32 -1 keyring _uid_ses.32: empty
00000892 I--QU- 1 perm 1f0000 0 0 user metal:copper: 0
00000893 I--Q-N 1 35s 1f0000 0 0 user metal:silver: 0
00000894 I--Q-- 1 10h 1f0000 0 0 user metal:gold: 0
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4
00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty
00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty
0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty
000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4
000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty
00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0
00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0
00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0
The flags are:
......@@ -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
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
prevent access vs modification races. See the section "Notes on accessing
payload contents" for more information.
......@@ -665,7 +693,11 @@ payload contents" for more information.
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.
......@@ -689,13 +721,17 @@ payload contents" for more information.
(*) If a keyring was found in the search, this can be further searched by:
struct key *keyring_search(struct key *keyring,
const struct key_type *type,
const char *description)
key_ref_t keyring_search(key_ref_t keyring_ref,
const struct key_type *type,
const char *description)
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
released.
is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful,
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:
......@@ -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
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
be accessed without any form of locking, provided that it's known to be
......
......@@ -604,6 +604,15 @@ P: H. Peter Anvin
M: hpa@zytor.com
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
W: http://sourceforge.net/projects/cramfs/
S: Orphan
......@@ -1906,6 +1915,13 @@ M: joern@wh.fh-wedel.de
L: linux-mtd@lists.infradead.org
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
P: George Anzinger
M: george@mvista.com
......
......@@ -175,10 +175,10 @@ else
endif
@touch $@
archprepare: maketools include/asm-arm/.arch
archprepare: maketools
.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
# Convert bzImage to zImage
......
此差异已折叠。
......@@ -125,7 +125,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
} else if (type & IRQT_LOW) {
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
irq_type = IXP4XX_IRQ_LEVEL;
}
} else
return -EINVAL;
ixp4xx_config_irq(irq, irq_type);
......@@ -142,6 +143,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
/* Set the new style */
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
return 0;
}
static void ixp4xx_irq_mask(unsigned int irq)
......
......@@ -27,7 +27,6 @@
#include <linux/config.h>
#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/dmi.h>
......
......@@ -18,7 +18,6 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
......
......@@ -7,7 +7,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -6,7 +6,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
......
......@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/processor.h>
......
......@@ -11,10 +11,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
......
......@@ -16,7 +16,6 @@
#include <asm/atomic.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/timer.h>
#include <asm/pgtable.h>
#include <asm/delay.h>
......@@ -25,8 +24,6 @@
#include <asm/arch_hooks.h>
#include <asm/i8259.h>
#include <linux/irq.h>
#include <io_ports.h>
/*
......
......@@ -21,7 +21,6 @@
*/
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
......
......@@ -14,7 +14,6 @@
*/
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/delay.h>
......
......@@ -15,7 +15,6 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
......
......@@ -47,13 +47,11 @@
#include <asm/ldt.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/irq.h>
#include <asm/desc.h>
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif
#include <linux/irq.h>
#include <linux/err.h>
#include <asm/tlbflush.h>
......
......@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
......
......@@ -42,7 +42,6 @@
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/smp_lock.h>
#include <linux/irq.h>
#include <linux/bootmem.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
......
......@@ -6,7 +6,6 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <linux/sysdev.h>
#include <linux/timex.h>
#include <asm/delay.h>
......
......@@ -52,7 +52,6 @@
#include <asm/arch_hooks.h>
#include <asm/kdebug.h>
#include <linux/irq.h>
#include <linux/module.h>
#include "mach_traps.h"
......
......@@ -5,7 +5,6 @@
#include <linux/config.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/acpi.h>
#include <asm/arch_hooks.h>
......
......@@ -5,7 +5,6 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/fixmap.h>
......
......@@ -19,7 +19,6 @@
#include <linux/config.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
......
......@@ -4,7 +4,6 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/acpi.h>
#include <asm/arch_hooks.h>
......
......@@ -27,7 +27,6 @@
#include <asm/voyager.h>
#include <asm/vic.h>
#include <linux/pm.h>
#include <linux/irq.h>
#include <asm/tlbflush.h>
#include <asm/arch_hooks.h>
#include <asm/i8253.h>
......
......@@ -30,8 +30,6 @@
#include <asm/tlbflush.h>
#include <asm/arch_hooks.h>
#include <linux/irq.h>
/* TLB state -- visible externally, indexed physically */
DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
......
......@@ -31,8 +31,6 @@
#include <asm/mtrr.h>
#include <asm/msr.h>
#include <linux/irq.h>
#define THREAD_NAME "kvoyagerd"
/* external variables */
......
......@@ -9,7 +9,7 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/oprofile.h>
#include <linux/rcupdate.h>
......
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/hw_irq.h>
#include <asm/numa.h>
#include "pci.h"
......
......@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/dmi.h>
#include <asm/io.h>
#include <asm/smp.h>
......
......@@ -8,25 +8,8 @@
*/
#include <linux/config.h>
#include <linux/kernel.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/acpi.h>
#include <asm/uaccess.h>
#include <asm/acpi.h>
#include <asm/tlbflush.h>
#include <asm/processor.h>
static struct saved_context saved_context;
......
......@@ -24,7 +24,7 @@ aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -Wa,-no-bitinst
CFLAGS += $(cflags-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
......
......@@ -13,7 +13,7 @@
#include <asm/uaccess.h>
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);
if (access_ok(VERIFY_WRITE, to, n))
......@@ -22,7 +22,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n)
}
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);
if (access_ok(VERIFY_READ, from, n))
......@@ -111,7 +111,7 @@ do { \
#endif /* CONFIG_ISA_DUAL_ISSUE */
long
__strncpy_from_user(char *dst, const char *src, long count)
__strncpy_from_user(char *dst, const char __user *src, long count)
{
long res;
__do_strncpy_from_user(dst, src, count, res);
......@@ -119,7 +119,7 @@ __strncpy_from_user(char *dst, const char *src, long count)
}
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;
if (access_ok(VERIFY_READ, src, 1))
......@@ -222,7 +222,7 @@ do { \
#endif /* not CONFIG_ISA_DUAL_ISSUE */
unsigned long
clear_user(void *to, unsigned long n)
clear_user(void __user *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
__do_clear_user(to, n);
......@@ -230,7 +230,7 @@ clear_user(void *to, unsigned long n)
}
unsigned long
__clear_user(void *to, unsigned long n)
__clear_user(void __user *to, unsigned long n)
{
__do_clear_user(to, n);
return n;
......@@ -244,7 +244,7 @@ __clear_user(void *to, unsigned long n)
#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 res;
......@@ -313,7 +313,7 @@ long strnlen_user(const char *s, long n)
#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 res;
......
......@@ -45,9 +45,8 @@ static void dummy_perf(struct pt_regs *regs)
mtpmr(PMRN_PMGC0, pmgc0);
}
#elif CONFIG_6xx
#elif defined(CONFIG_6xx)
/* Ensure exceptions are disabled */
static void dummy_perf(struct pt_regs *regs)
{
unsigned int mmcr0 = mfspr(SPRN_MMCR0);
......
......@@ -205,6 +205,7 @@ static void kexec_prepare_cpus(void)
continue;
while (paca[i].hw_cpu_id != -1) {
barrier();
if (!cpu_possible(i)) {
printk("kexec: cpu %d hw_cpu_id %d is not"
" possible, ignoring\n",
......
......@@ -342,14 +342,13 @@ static void native_flush_hash_range(unsigned long number, int local)
hpte_t *hptep;
unsigned long hpte_v;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
unsigned long large;
unsigned long large = batch->large;
local_irq_save(flags);
j = 0;
for (i = 0; i < number; i++) {
va = batch->vaddr[j];
large = pte_huge(batch->pte[i]);
if (large)
vpn = va >> HPAGE_SHIFT;
else
......@@ -399,7 +398,7 @@ static void native_flush_hash_range(unsigned long number, int local)
asm volatile("ptesync":::"memory");
for (i = 0; i < j; i++)
__tlbie(batch->vaddr[i], 0);
__tlbie(batch->vaddr[i], large);
asm volatile("eieio; tlbsync; ptesync":::"memory");
......
......@@ -141,12 +141,14 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
* up scanning and resetting referenced bits then our batch context
* 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();
i = 0;
}
if (i == 0)
if (i == 0) {
batch->mm = mm;
batch->large = pte_huge(pte);
}
if (addr < KERNELBASE) {
vsid = get_vsid(mm->context.id, addr);
WARN_ON(vsid == 0);
......
......@@ -33,6 +33,14 @@ config DEBUG_BOOTMEM
depends on DEBUG_KERNEL
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
bool
depends on STACK_DEBUG
......
......@@ -135,6 +135,28 @@ void __init device_scan(void)
cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
"clock-frequency",
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
......
......@@ -9,17 +9,7 @@
#include <asm/pgtable.h>
#include <asm/mmu.h>
#if PAGE_SHIFT == 13
#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 VALID_SZ_BITS (_PAGE_VALID | _PAGE_SZBITS)
#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P )
#define VPTE_SHIFT (PAGE_SHIFT - 3)
......@@ -163,7 +153,6 @@ sparc64_vpte_continue:
stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS
retry ! Load PTE once again
#undef SZ_BITS
#undef VALID_SZ_BITS
#undef VPTE_SHIFT
#undef VPTE_BITS
......
......@@ -71,7 +71,7 @@
from_tl1_trap:
rdpr %tl, %g5 ! For TL==3 test
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
cmp %g5, 4 ! Last trap level?
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
......@@ -83,9 +83,9 @@ from_tl1_trap:
nop ! Delay-slot
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
retry ! Trap return
3: brlz,pt %g4, 9b ! Kernel virtual map?
xor %g2, %g4, %g5 ! Finish bit twiddles
ba,a,pt %xcc, kvmap ! Yep, go check for obp/vmalloc
nop
nop
nop
/* DTLB ** ICACHE line 3: winfixups+real_faults */
longpath:
......
......@@ -30,159 +30,6 @@
.text
.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... */
.globl do_fpdis
do_fpdis:
......@@ -525,14 +372,13 @@ cheetah_plus_patch_fpdis:
*
* DATA 0: [low 32-bits] Address of function to call, jmp to this
* [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
*
* With this method we can do most of the cross-call tlb/cache
* flushing very quickly.
*
* Current CPU's IRQ worklist table is locked into %g1,
* don't touch.
* Current CPU's IRQ worklist table is locked into %g6, don't touch.
*/
.text
.align 32
......@@ -1006,13 +852,14 @@ cheetah_plus_dcpe_trap_vector:
nop
do_cheetah_plus_data_parity:
ba,pt %xcc, etrap
rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
mov 0x0, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
ba,pt %xcc, rtrap
clr %l6
ba,a,pt %xcc, rtrap_irq
cheetah_plus_dcpe_trap_vector_tl1:
membar #Sync
......@@ -1036,13 +883,14 @@ cheetah_plus_icpe_trap_vector:
nop
do_cheetah_plus_insn_parity:
ba,pt %xcc, etrap
rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
mov 0x1, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
ba,pt %xcc, rtrap
clr %l6
ba,a,pt %xcc, rtrap_irq
cheetah_plus_icpe_trap_vector_tl1:
membar #Sync
......@@ -1075,6 +923,10 @@ do_dcpe_tl1:
nop
wrpr %g1, %tl ! Restore original trap level
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 */
sethi %hi(1 << 16), %g1 ! D-cache size
mov (1 << 5), %g2 ! D-cache line size
......@@ -1121,6 +973,10 @@ do_icpe_tl1:
nop
wrpr %g1, %tl ! Restore original trap level
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 */
sethi %hi(1 << 15), %g1 ! I-cache size
mov (1 << 5), %g2 ! I-cache line size
......
......@@ -80,15 +80,165 @@ sparc_ramdisk_image64:
.xword 0
.word _end
/* We must be careful, 32-bit OpenBOOT will get confused if it
* tries to save away a register window to a 64-bit kernel
* stack address. Flush all windows, disable interrupts,
* remap if necessary, jump onto kernel trap table, then kernel
* stack, or else we die.
/* PROM cif handler code address is in %o4. */
sparc64_boot:
1: rd %pc, %g7
set 1b, %g1
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_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
ba,pt %xcc, spitfire_boot
......@@ -125,185 +275,7 @@ cheetah_generic_boot:
stxa %g0, [%g3] ASI_IMMU
membar #Sync
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
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
ba,a,pt %xcc, jump_to_sun4u_init
spitfire_boot:
/* Typically PROM has already enabled both MMU's and both on-chip
......@@ -313,6 +285,7 @@ spitfire_boot:
stxa %g1, [%g0] ASI_LSU_CONTROL
membar #Sync
jump_to_sun4u_init:
/*
* Make sure we are in privileged mode, have address masking,
* using the ordinary globals and have enabled floating
......@@ -324,151 +297,6 @@ spitfire_boot:
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
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
jmpl %g2 + %g0, %g0
nop
......@@ -483,38 +311,12 @@ sun4u_init:
stxa %g0, [%g7] ASI_DMMU
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)
ba,pt %xcc, spitfire_tlb_fixup
nop
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+. */
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
......@@ -551,21 +353,6 @@ cheetah_tlb_fixup:
nop
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. */
mov 0, %g2
sethi %hi(tlb_type), %g1
......@@ -578,24 +365,6 @@ tlb_fixup_done:
mov %sp, %l6
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
mov 1, %g1
sllx %g1, THREAD_SHIFT, %g1
......@@ -756,12 +525,7 @@ bootup_user_stack_end:
#include "ttable.S"
#include "systbls.S"
.align 1024
.globl swapper_pg_dir
swapper_pg_dir:
.word 0
#include "ktlb.S"
#include "etrap.S"
#include "rtrap.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)
static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_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;
int limit;
......
......@@ -496,7 +496,6 @@ extern void paging_init(void);
void __init setup_arch(char **cmdline_p)
{
unsigned long highest_paddr;
int i;
/* Initialize PROM console and command line. */
......@@ -519,11 +518,7 @@ void __init setup_arch(char **cmdline_p)
idprom_init();
(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;
highest_paddr = 0UL;
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
unsigned long top;
......@@ -531,25 +526,10 @@ void __init setup_arch(char **cmdline_p)
phys_base = sp_banks[i].base_addr;
top = sp_banks[i].base_addr +
sp_banks[i].num_bytes;
if (highest_paddr < top)
highest_paddr = top;
}
pfn_base = phys_base >> PAGE_SHIFT;
switch (tlb_type) {
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_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
if (!root_flags)
......@@ -625,6 +605,9 @@ extern void smp_info(struct seq_file *);
extern void smp_bogo(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)
{
seq_printf(m,
......@@ -635,6 +618,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
"type\t\t: sun4u\n"
"ncpus probed\t: %ld\n"
"ncpus active\t: %ld\n"
"D$ parity tl1\t: %u\n"
"I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP
"Cpu0Bogo\t: %lu.%02lu\n"
"Cpu0ClkTck\t: %016lx\n"
......@@ -647,7 +632,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
(prom_prev >> 8) & 0xff,
prom_prev & 0xff,
(long)num_possible_cpus(),
(long)num_online_cpus()
(long)num_online_cpus(),
dcache_parity_tl1_occurred,
icache_parity_tl1_occurred
#ifndef CONFIG_SMP
, cpu_data(0).udelay_val/(500000/HZ),
(cpu_data(0).udelay_val/(5000/HZ)) % 100,
......
......@@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id)
cpu_data(id).pte_cache[1] = NULL;
cpu_data(id).pgd_cache = NULL;
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);
......
......@@ -119,8 +119,8 @@ startup_continue:
sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
......@@ -156,8 +156,8 @@ startup_continue:
sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
......@@ -190,8 +190,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
......@@ -228,8 +228,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
......
......@@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr)
*/
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. */
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"
"membar #Sync"
: /* 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)
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"
"membar #Sync"
: /* no outputs */
: "r" (i), "i" (ASI_DCACHE_TAG));
: "r" (addr), "i" (ASI_DCACHE_TAG));
}
}
......@@ -921,24 +930,29 @@ static void cheetah_flush_dcache(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)) {
unsigned long tag = (i >> 14);
unsigned long j;
for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
unsigned long tag = (addr >> 14);
unsigned long line;
__asm__ __volatile__("membar #Sync\n\t"
"stxa %0, [%1] %2\n\t"
"membar #Sync"
: /* no outputs */
: "r" (tag), "r" (i),
: "r" (tag), "r" (addr),
"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"
"stxa %%g0, [%0] %1\n\t"
"membar #Sync"
: /* no outputs */
: "r" (j), "i" (ASI_DCACHE_DATA));
: "r" (line),
"i" (ASI_DCACHE_DATA));
}
}
......
......@@ -9,8 +9,7 @@ ENTRY(_start)
jiffies = jiffies_64;
SECTIONS
{
swapper_pmd_dir = 0x0000000000402000;
empty_pg_dir = 0x0000000000403000;
swapper_low_pmd_dir = 0x0000000000402000;
. = 0x4000;
.text 0x0000000000404000 :
{
......
此差异已折叠。
......@@ -144,42 +144,29 @@ __flush_icache_page: /* %o0 = phys_page */
#define DTAG_MASK 0x3
/* This routine is Spitfire specific so the hardcoded
* D-cache size and line-size are OK.
*/
.align 64
.globl __flush_dcache_page
__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1
sub %o0, %g1, %o0
clr %o4
srlx %o0, 11, %o0
sethi %hi(1 << 14), %o2
1: ldxa [%o4] ASI_DCACHE_TAG, %o3 ! LSU Group
add %o4, (1 << 5), %o4 ! IEU0
ldxa [%o4] ASI_DCACHE_TAG, %g1 ! LSU Group
add %o4, (1 << 5), %o4 ! IEU0
ldxa [%o4] ASI_DCACHE_TAG, %g2 ! LSU Group o3 available
add %o4, (1 << 5), %o4 ! IEU0
andn %o3, DTAG_MASK, %o3 ! IEU1
ldxa [%o4] ASI_DCACHE_TAG, %g3 ! LSU Group
add %o4, (1 << 5), %o4 ! IEU0
andn %g1, DTAG_MASK, %g1 ! IEU1
cmp %o0, %o3 ! IEU1 Group
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
sub %o0, %g1, %o0 ! physical address
srlx %o0, 11, %o0 ! make D-cache TAG
sethi %hi(1 << 14), %o2 ! D-cache size
sub %o2, (1 << 5), %o2 ! D-cache line size
1: ldxa [%o2] ASI_DCACHE_TAG, %o3 ! load D-cache TAG
andcc %o3, DTAG_MASK, %g0 ! Valid?
be,pn %xcc, 2f ! Nope, branch
andn %o3, DTAG_MASK, %o3 ! Clear valid bits
cmp %o3, %o0 ! TAG match?
bne,pt %xcc, 2f ! Nope, branch
nop
stxa %g0, [%o2] ASI_DCACHE_TAG ! Invalidate TAG
membar #Sync
2: brnz,pt %o2, 1b
sub %o2, (1 << 5), %o2 ! D-cache line size
/* The I-cache does not snoop local stores so we
* better flush that too when necessary.
......@@ -189,48 +176,9 @@ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
retl
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 */
.previous .text
.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
.previous
/* Cheetah specific versions, patched at boot time. */
__cheetah_flush_tlb_mm: /* 18 insns */
......@@ -283,7 +231,7 @@ __cheetah_flush_tlb_pending: /* 26 insns */
wrpr %g7, 0x0, %pstate
#ifdef DCACHE_ALIASING_POSSIBLE
flush_dcpage_cheetah: /* 11 insns */
__cheetah_flush_dcache_page: /* 11 insns */
sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1
sub %o0, %g1, %o0
......@@ -329,8 +277,8 @@ cheetah_patch_cachetlbops:
#ifdef DCACHE_ALIASING_POSSIBLE
sethi %hi(__flush_dcache_page), %o0
or %o0, %lo(__flush_dcache_page), %o0
sethi %hi(flush_dcpage_cheetah), %o1
or %o1, %lo(flush_dcpage_cheetah), %o1
sethi %hi(__cheetah_flush_dcache_page), %o1
or %o1, %lo(__cheetah_flush_dcache_page), %o1
call cheetah_patch_one
mov 11, %o2
#endif /* DCACHE_ALIASING_POSSIBLE */
......
......@@ -7,4 +7,4 @@ EXTRA_AFLAGS := -ansi
EXTRA_CFLAGS := -Werror
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)
}
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_INOUT(3,1),
......
......@@ -16,7 +16,7 @@
* Returns 0 on failure.
*/
int
prom_devopen(char *dstr)
prom_devopen(const char *dstr)
{
return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
P1275_INOUT(1,1),
......
......@@ -46,7 +46,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
if((prom_root_node == 0) || (prom_root_node == -1))
prom_halt();
prom_chosen_node = prom_finddevice("/chosen");
prom_chosen_node = prom_finddevice(prom_chosen_path);
if (!prom_chosen_node || prom_chosen_node == -1)
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 @@
#include <asm/system.h>
/* 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_INOUT(1, 0), bcommand);
}
/* Forth evaluate the expression contained in 'fstring'. */
void prom_feval(char *fstring)
void prom_feval(const char *fstring)
{
if (!fstring || fstring[0] == 0)
return;
......@@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba)
p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
}
int mmu_ihandle_cache = 0;
int prom_get_mmu_ihandle(void)
{
int node, ret;
if (mmu_ihandle_cache != 0)
return mmu_ihandle_cache;
if (prom_mmu_ihandle_cache != 0)
return prom_mmu_ihandle_cache;
node = prom_finddevice("/chosen");
ret = prom_getint(node, "mmu");
node = prom_finddevice(prom_chosen_path);
ret = prom_getint(node, prom_mmu_name);
if (ret == -1 || ret == 0)
mmu_ihandle_cache = -1;
prom_mmu_ihandle_cache = -1;
else
mmu_ihandle_cache = ret;
prom_mmu_ihandle_cache = ret;
return ret;
}
......@@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index,
unsigned long tte_data,
unsigned long vaddr)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
......@@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index,
unsigned long tte_data,
unsigned long vaddr)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
......@@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index,
int prom_map(int mode, unsigned long size,
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(3, P1275_ARG_IN_64B) |
P1275_ARG(4, P1275_ARG_IN_64B) |
P1275_ARG(6, P1275_ARG_IN_64B) |
P1275_INOUT(7, 1)),
"map",
prom_map_name,
prom_get_mmu_ihandle(),
mode,
size,
......@@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size,
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(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
P1275_INOUT(4, 0)),
"unmap",
prom_unmap_name,
prom_get_mmu_ihandle(),
size,
vaddr);
......@@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr)
/* Set aside physical memory which is not touched or modified
* across soft resets.
*/
unsigned long prom_retain(char *name,
unsigned long prom_retain(const char *name,
unsigned long pa_low, unsigned long pa_high,
long size, long align)
{
......@@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code,
unsigned long phys_addr,
char *buf, int buflen)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(3, P1275_ARG_OUT_BUF) |
P1275_ARG(6, P1275_ARG_IN_64B) |
......
......@@ -46,7 +46,7 @@ static inline unsigned long spitfire_get_primary_context(void)
*/
DEFINE_SPINLOCK(prom_entry_lock);
long p1275_cmd (char *service, long fmt, ...)
long p1275_cmd(const char *service, long fmt, ...)
{
char *p, *q;
unsigned long flags;
......
......@@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n)
}
void
prom_printf(char *fmt, ...)
prom_printf(const char *fmt, ...)
{
va_list args;
int i;
......
......@@ -69,7 +69,7 @@ prom_getsibling(int node)
* Return -1 on error.
*/
__inline__ int
prom_getproplen(int node, char *prop)
prom_getproplen(int node, const char *prop)
{
if((!node) || (!prop)) return -1;
return p1275_cmd ("getproplen",
......@@ -83,20 +83,20 @@ prom_getproplen(int node, char *prop)
* was successful the length will be returned, else -1 is returned.
*/
__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;
plen = prom_getproplen(node, prop);
if((plen > bufsize) || (plen == 0) || (plen == -1))
if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
return -1;
else {
} else {
/* Ok, things seem all right. */
return p1275_cmd ("getprop",
P1275_ARG(1,P1275_ARG_IN_STRING)|
P1275_ARG(2,P1275_ARG_OUT_BUF)|
P1275_INOUT(4, 1),
node, prop, buffer, P1275_SIZE(plen));
return p1275_cmd(prom_getprop_name,
P1275_ARG(1,P1275_ARG_IN_STRING)|
P1275_ARG(2,P1275_ARG_OUT_BUF)|
P1275_INOUT(4, 1),
node, prop, buffer, P1275_SIZE(plen));
}
}
......@@ -104,7 +104,7 @@ prom_getproperty(int node, char *prop, char *buffer, int bufsize)
* on failure.
*/
__inline__ int
prom_getint(int node, char *prop)
prom_getint(int node, const char *prop)
{
int intprop;
......@@ -119,7 +119,7 @@ prom_getint(int node, char *prop)
*/
int
prom_getintdefault(int node, char *property, int deflt)
prom_getintdefault(int node, const char *property, int deflt)
{
int retval;
......@@ -131,7 +131,7 @@ prom_getintdefault(int node, char *property, int deflt)
/* Acquire a boolean property, 1=TRUE 0=FALSE. */
int
prom_getbool(int node, char *prop)
prom_getbool(int node, const char *prop)
{
int retval;
......@@ -145,7 +145,7 @@ prom_getbool(int node, char *prop)
* buffer.
*/
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;
......@@ -160,7 +160,7 @@ prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
* YES = 1 NO = 0
*/
int
prom_nodematch(int node, char *name)
prom_nodematch(int node, const char *name)
{
char namebuf[128];
prom_getproperty(node, "name", namebuf, sizeof(namebuf));
......@@ -172,7 +172,7 @@ prom_nodematch(int node, char *name)
* 'nodename'. Return node if successful, zero if not.
*/
int
prom_searchsiblings(int node_start, char *nodename)
prom_searchsiblings(int node_start, const char *nodename)
{
int thisnode, error;
......@@ -294,7 +294,7 @@ prom_firstprop(int node, char *buffer)
* property types for this node.
*/
__inline__ char *
prom_nextprop(int node, char *oprop, char *buffer)
prom_nextprop(int node, const char *oprop, char *buffer)
{
char buf[32];
......@@ -314,15 +314,17 @@ prom_nextprop(int node, char *oprop, char *buffer)
}
int
prom_finddevice(char *name)
prom_finddevice(const char *name)
{
if(!name) return 0;
return p1275_cmd ("finddevice", P1275_ARG(0,P1275_ARG_IN_STRING)|
P1275_INOUT(1, 1),
name);
if (!name)
return 0;
return p1275_cmd(prom_finddev_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];
......@@ -339,7 +341,7 @@ int prom_node_has_property(int node, char *prop)
* of 'size' bytes. Return the number of bytes the prom accepted.
*/
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((pname == 0) || (value == 0)) return 0;
......@@ -364,7 +366,7 @@ prom_inst2pkg(int inst)
* FIXME: Should work for v0 as well
*/
int
prom_pathtoinode(char *path)
prom_pathtoinode(const char *path)
{
int node, inst;
......
......@@ -959,9 +959,6 @@ static __init int unsynchronized_tsc(void)
are handled in the OEM check above. */
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
return 0;
/* All in a single socket - should be synchronized */
if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
return 0;
#endif
/* Assume multi socket systems are not synchronized */
return num_online_cpus() > 1;
......
......@@ -55,7 +55,7 @@ extern void (*pm_power_off)(void);
static int poweroff_powercycle;
/* 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.");
/* Stuff from the get device id command. */
......
......@@ -31,16 +31,19 @@
#include <linux/connector.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);
cbq->destruct_data(cbq->ddata);
cbq->ddata = NULL;
d->callback(d->callback_priv);
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;
......@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac
return NULL;
}
cbq->cb = cb;
INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq);
snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
memcpy(&cbq->id.id, id, sizeof(struct cb_id));
cbq->data.callback = callback;
INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
return cbq;
}
......@@ -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));
}
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;
int found = 0;
cbq = cn_queue_alloc_callback_entry(cb);
cbq = cn_queue_alloc_callback_entry(name, id, callback);
if (!cbq)
return -ENOMEM;
......@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
spin_lock_bh(&dev->queue_lock);
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;
break;
}
......@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
cbq->nls = dev->nls;
cbq->seq = 0;
cbq->group = cbq->cb->id.idx;
cbq->group = cbq->id.id.idx;
return 0;
}
......@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
spin_lock_bh(&dev->queue_lock);
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);
found = 1;
break;
......
......@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
spin_lock_bh(&dev->cbdev->queue_lock);
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)) {
found = 1;
group = __cbq->group;
}
......@@ -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_dev *dev = &cdev;
int found = 0;
int err = -ENODEV;
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->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 (cn_cb_equal(&__cbq->id.id, &msg->id)) {
if (likely(!test_bit(0, &__cbq->work.pending) &&
__cbq->ddata == NULL)) {
__cbq->cb->priv = msg;
__cbq->data.ddata == NULL)) {
__cbq->data.callback_priv = msg;
__cbq->ddata = data;
__cbq->destruct_data = destruct_data;
__cbq->data.ddata = data;
__cbq->data.destruct_data = destruct_data;
if (queue_work(dev->cbdev->cn_queue,
&__cbq->work))
found = 1;
err = 0;
} else {
printk("%s: cbq->data=%p, "
"work->pending=%08lx.\n",
__func__, __cbq->ddata,
__cbq->work.pending);
WARN_ON(1);
struct work_struct *w;
struct cn_callback_data *d;
w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
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;
}
}
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 *))
{
int err;
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));
cb->callback = callback;
err = cn_queue_add_callback(dev->cbdev, cb);
if (err) {
kfree(cb);
err = cn_queue_add_callback(dev->cbdev, name, id, callback);
if (err)
return err;
}
cn_notify(id, 0);
......
......@@ -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", "PCIDEII", 0x547e66dc, 0xb3662674),
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", "PnPIDE", 0x281f1c5d, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
......
......@@ -69,6 +69,7 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file {
struct kref ref;
struct semaphore mutex;
struct ib_uverbs_device *device;
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
......
......@@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
struct ib_uverbs_get_context_resp resp;
struct ib_udata udata;
struct ib_device *ibdev = file->device->ib_dev;
struct ib_ucontext *ucontext;
int i;
int ret = in_len;
int ret;
if (out_len < sizeof resp)
return -ENOSPC;
......@@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
down(&file->mutex);
if (file->ucontext) {
ret = -EINVAL;
goto err;
}
INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
file->ucontext = ibdev->alloc_ucontext(ibdev, &udata);
if (IS_ERR(file->ucontext)) {
ret = PTR_ERR(file->ucontext);
file->ucontext = NULL;
return ret;
}
ucontext = ibdev->alloc_ucontext(ibdev, &udata);
if (IS_ERR(ucontext))
return PTR_ERR(file->ucontext);
file->ucontext->device = ibdev;
INIT_LIST_HEAD(&file->ucontext->pd_list);
INIT_LIST_HEAD(&file->ucontext->mr_list);
INIT_LIST_HEAD(&file->ucontext->mw_list);
INIT_LIST_HEAD(&file->ucontext->cq_list);
INIT_LIST_HEAD(&file->ucontext->qp_list);
INIT_LIST_HEAD(&file->ucontext->srq_list);
INIT_LIST_HEAD(&file->ucontext->ah_list);
spin_lock_init(&file->ucontext->lock);
ucontext->device = ibdev;
INIT_LIST_HEAD(&ucontext->pd_list);
INIT_LIST_HEAD(&ucontext->mr_list);
INIT_LIST_HEAD(&ucontext->mw_list);
INIT_LIST_HEAD(&ucontext->cq_list);
INIT_LIST_HEAD(&ucontext->qp_list);
INIT_LIST_HEAD(&ucontext->srq_list);
INIT_LIST_HEAD(&ucontext->ah_list);
resp.async_fd = file->async_file.fd;
for (i = 0; i < file->device->num_comp; ++i)
if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
i * sizeof (__u32),
&file->comp_file[i].fd, sizeof (__u32)))
goto err;
&file->comp_file[i].fd, sizeof (__u32))) {
ret = -EFAULT;
goto err_free;
}
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp))
goto err;
&resp, sizeof resp)) {
ret = -EFAULT;
goto err_free;
}
file->ucontext = ucontext;
up(&file->mutex);
return in_len;
err:
ibdev->dealloc_ucontext(file->ucontext);
file->ucontext = NULL;
err_free:
ibdev->dealloc_ucontext(ucontext);
return -EFAULT;
err:
up(&file->mutex);
return ret;
}
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,
if (ret)
goto err_pd;
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
memset(&resp, 0, sizeof resp);
resp.pd_handle = uobj->id;
......@@ -368,9 +380,9 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
return in_len;
err_list:
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_pd_idr, uobj->id);
......@@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
kfree(uobj);
......@@ -512,9 +524,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
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);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
......@@ -527,9 +539,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
return in_len;
err_list:
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&obj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
err_unreg:
ib_dereg_mr(mr);
......@@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&memobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj);
......@@ -647,9 +659,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (ret)
goto err_cq;
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
memset(&resp, 0, sizeof resp);
resp.cq_handle = uobj->uobject.id;
......@@ -664,9 +676,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
return in_len;
err_list:
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
......@@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
spin_lock_irq(&file->comp_file[0].lock);
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,
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);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
......@@ -862,9 +874,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
return in_len;
err_list:
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
err_destroy:
ib_destroy_qp(qp);
......@@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
spin_lock_irq(&file->async_file.lock);
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,
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);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
......@@ -1151,9 +1163,9 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
return in_len;
err_list:
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
err_destroy:
ib_destroy_srq(srq);
......@@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
spin_lock_irq(&file->ucontext->lock);
down(&file->mutex);
list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
up(&file->mutex);
spin_lock_irq(&file->async_file.lock);
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,
if (hdr.in_words * 4 != count)
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;
if (!file->ucontext &&
......@@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file = kmalloc(sizeof *file +
(dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
GFP_KERNEL);
if (!file)
return -ENOMEM;
if (!file) {
ret = -ENOMEM;
goto err;
}
file->device = dev;
kref_init(&file->ref);
init_MUTEX(&file->mutex);
file->ucontext = NULL;
kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->async_file, file);
if (ret)
goto err;
goto err_kref;
file->async_file.is_async = 1;
kref_get(&file->ref);
for (i = 0; i < dev->num_comp; ++i) {
kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->comp_file[i], file);
if (ret)
goto err_async;
kref_get(&file->ref);
file->comp_file[i].is_async = 0;
}
......@@ -524,9 +528,16 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
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);
err:
module_put(dev->ib_dev->owner);
return ret;
}
......
......@@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
err = -EINVAL;
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) {
pages[nent * 2] = cpu_to_be64(virt);
virt += 1 << lg;
......@@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
ts += 1 << (lg - 10);
++tc;
if (nent == MTHCA_MAILBOX_SIZE / 16) {
if (++nent == MTHCA_MAILBOX_SIZE / 16) {
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
CMD_TIME_CLASS_B, status);
if (err || *status)
......
......@@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
dev->eq_table.clr_mask =
swab32(1 << (dev->eq_table.inta_pin & 31));
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;
......
......@@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
int i;
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);
if (!table)
......@@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
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) {
ret = -ENOMEM;
goto out;
}
if (group == 0)
++dev->db_tab->max_group1;
else
--dev->db_tab->min_group2;
page = dev->db_tab->page + end;
alloc:
page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
&page->mapping, GFP_KERNEL);
if (!page->db_rec) {
......@@ -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);
if (group == 0)
++dev->db_tab->max_group1;
else
--dev->db_tab->min_group2;
found:
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,
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
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->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
static void __hash_remove(struct hash_cell *hc)
{
struct dm_table *table;
/* remove from the dev hash */
list_del(&hc->uuid_list);
list_del(&hc->name_list);
unregister_with_devfs(hc);
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);
if (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,
/*
* 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;
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;
if (!m->queue_if_no_path && m->queue_size)
queue_work(kmultipathd, &m->process_queued_ios);
......@@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m,
return 0;
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 {
ti->error = "Unrecognised multipath feature request";
return -EINVAL;
......@@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti)
{
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)
if (argc == 1) {
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")))
return queue_if_no_path(m, 0);
return queue_if_no_path(m, 0, 0);
}
if (argc != 2)
......
......@@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2)
printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n",
state->frontend.dvb->num, __FUNCTION__, ret);
printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
__FUNCTION__, ret);
return b1[0];
}
......
......@@ -140,6 +140,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#if ALLOW_DMA
#include <asm/dma.h>
#endif
......
......@@ -67,8 +67,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.40"
#define DRV_MODULE_RELDATE "September 15, 2005"
#define DRV_MODULE_VERSION "3.41"
#define DRV_MODULE_RELDATE "September 27, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
struct tg3 *tp = netdev_priv(dev);
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,
0x00000001);
return IRQ_RETVAL(1);
......@@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
struct tg3 *tp = netdev_priv(dev);
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_bh(&tp->lock);
......@@ -5806,6 +5810,13 @@ static int tg3_reset_hw(struct tg3 *tp)
}
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 |
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);
......@@ -5937,7 +5948,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_LED_CTRL, tp->led_ctrl);
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);
udelay(10);
}
......@@ -7360,12 +7371,17 @@ static int tg3_nway_reset(struct net_device *dev)
if (!netif_running(dev))
return -EAGAIN;
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
return -EINVAL;
spin_lock_bh(&tp->lock);
r = -EINVAL;
tg3_readphy(tp, MII_BMCR, &bmcr);
if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
(bmcr & BMCR_ANENABLE)) {
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
((bmcr & BMCR_ANENABLE) ||
(tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE);
r = 0;
}
spin_unlock_bh(&tp->lock);
......@@ -7927,19 +7943,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
struct tg3_rx_buffer_desc *desc;
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_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
MAC_MODE_PORT_MODE_GMII;
tw32(MAC_MODE, mac_mode);
} 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_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
mac_mode &= ~MAC_MODE_LINK_POLARITY;
tw32(MAC_MODE, mac_mode);
tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
BMCR_SPEED1000);
}
else
return -EINVAL;
......@@ -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)
{
struct pci_dev *peer;
......@@ -10386,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
struct net_device *dev;
struct tg3 *tp;
int i, err, pci_using_dac, pm_cap;
char str[40];
if (tg3_version_printed++ == 0)
printk(KERN_INFO "%s", version);
......@@ -10631,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
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,
tp->board_part_number,
tp->pci_chip_rev_id,
tg3_phy_string(tp),
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
((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"),
tg3_bus_string(tp, str),
(tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
for (i = 0; i < 6; i++)
......
......@@ -2246,6 +2246,7 @@ struct tg3 {
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
(X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \
(X) == PHY_ID_BCM8002)
struct tg3_hw_stats *hw_stats;
......
......@@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->watchdog_timeo = HZ; /* 1 second timeout */
dev->get_stats = orinoco_get_stats;
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->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list;
......@@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = {
.standard = orinoco_handler,
.private = orinoco_private_handler,
.private_args = orinoco_privtab,
.get_wireless_stats = orinoco_get_wireless_stats,
};
static void orinoco_get_drvinfo(struct net_device *dev,
......
......@@ -146,7 +146,7 @@ config I82365
config TCIC
tristate "Databook TCIC host bridge support"
depends on PCMCIA
depends on PCMCIA && ISA
select PCCARD_NONSTATIC
help
Say Y here to include support for the Databook TCIC family of PCMCIA
......
......@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
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_bus_add_devices(bus);
......
此差异已折叠。
此差异已折叠。
......@@ -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, 0x0101, 0x0035, "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("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"),
......
此差异已折叠。
......@@ -25,6 +25,7 @@
#define FID_OP 0
#define FID_WALK 1
#define FID_CREATE 2
struct v9fs_fid {
struct list_head list; /* list of fids associated with a dentry */
......@@ -52,6 +53,8 @@ struct v9fs_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);
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.
先完成此消息的编辑!
想要评论请 注册