summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/config.in1
-rw-r--r--arch/alpha/kernel/Makefile7
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c4
-rw-r--r--arch/alpha/kernel/core_cia.c609
-rw-r--r--arch/alpha/kernel/core_pyxis.c644
-rw-r--r--arch/alpha/kernel/core_tsunami.c2
-rw-r--r--arch/alpha/kernel/entry.S7
-rw-r--r--arch/alpha/kernel/irq.c67
-rw-r--r--arch/alpha/kernel/irq_alpha.c17
-rw-r--r--arch/alpha/kernel/irq_pyxis.c127
-rw-r--r--arch/alpha/kernel/irq_srm.c3
-rw-r--r--arch/alpha/kernel/machvec_impl.h12
-rw-r--r--arch/alpha/kernel/osf_sys.c14
-rw-r--r--arch/alpha/kernel/pci_impl.h1
-rw-r--r--arch/alpha/kernel/pci_iommu.c61
-rw-r--r--arch/alpha/kernel/proto.h8
-rw-r--r--arch/alpha/kernel/setup.c25
-rw-r--r--arch/alpha/kernel/smp.c12
-rw-r--r--arch/alpha/kernel/sys_alcor.c4
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c17
-rw-r--r--arch/alpha/kernel/sys_dp264.c76
-rw-r--r--arch/alpha/kernel/sys_eiger.c4
-rw-r--r--arch/alpha/kernel/sys_miata.c10
-rw-r--r--arch/alpha/kernel/sys_mikasa.c2
-rw-r--r--arch/alpha/kernel/sys_noritake.c2
-rw-r--r--arch/alpha/kernel/sys_ruffian.c10
-rw-r--r--arch/alpha/kernel/sys_sx164.c12
-rw-r--r--arch/alpha/kernel/sys_takara.c2
-rw-r--r--arch/alpha/kernel/time.c6
-rw-r--r--arch/alpha/kernel/traps.c4
-rw-r--r--arch/arm/Makefile3
-rw-r--r--arch/arm/config.in10
-rw-r--r--arch/arm/kernel/arch.c89
-rw-r--r--arch/arm/kernel/bios32.c69
-rw-r--r--arch/arm/kernel/bios32.h24
-rw-r--r--arch/arm/kernel/dec21285.c30
-rw-r--r--arch/arm/kernel/hw-footbridge.c4
-rw-r--r--arch/arm/kernel/process.c20
-rw-r--r--arch/arm/mm/fault-armv.c3
-rw-r--r--arch/arm/mm/mm-armo.c12
-rw-r--r--arch/arm/mm/mm-armv.c21
-rw-r--r--arch/arm/mm/proc-arm6,7.S14
-rw-r--r--arch/arm/mm/proc-sa110.S31
-rw-r--r--arch/i386/Makefile5
-rw-r--r--arch/i386/boot/compressed/head.S8
-rw-r--r--arch/i386/defconfig2
-rw-r--r--arch/i386/kernel/acpi.c30
-rw-r--r--arch/i386/kernel/head.S10
-rw-r--r--arch/i386/kernel/i386_ksyms.c3
-rw-r--r--arch/i386/kernel/pci-i386.c14
-rw-r--r--arch/i386/kernel/pci-pc.c38
-rw-r--r--arch/i386/kernel/setup.c44
-rw-r--r--arch/i386/kernel/time.c22
-rw-r--r--arch/mips/defconfig-decstation19
-rw-r--r--arch/mips/kernel/irixelf.c27
-rw-r--r--arch/mips64/defconfig-ip2221
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/sparc/Makefile2
-rw-r--r--arch/sparc/config.in63
-rw-r--r--arch/sparc/defconfig80
-rw-r--r--arch/sparc/kernel/ioport.c6
-rw-r--r--arch/sparc/kernel/setup.c39
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c10
-rw-r--r--arch/sparc/kernel/sys_solaris.c1
-rw-r--r--arch/sparc/kernel/sys_sunos.c32
-rw-r--r--arch/sparc/kernel/systbls.S6
-rw-r--r--arch/sparc/kernel/unaligned.c40
-rw-r--r--arch/sparc/lib/Makefile4
-rw-r--r--arch/sparc/lib/muldi3.S76
-rw-r--r--arch/sparc/mm/init.c91
-rw-r--r--arch/sparc64/config.in31
-rw-r--r--arch/sparc64/defconfig74
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c28
-rw-r--r--arch/sparc64/kernel/ioctl32.c425
-rw-r--r--arch/sparc64/kernel/setup.c27
-rw-r--r--arch/sparc64/kernel/smp.c17
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c12
-rw-r--r--arch/sparc64/kernel/sys_sparc.c7
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c99
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c29
-rw-r--r--arch/sparc64/kernel/systbls.S10
-rw-r--r--arch/sparc64/kernel/unaligned.c18
-rw-r--r--arch/sparc64/lib/VIScopy.S8
-rw-r--r--arch/sparc64/lib/atomic.S26
-rw-r--r--arch/sparc64/lib/blockops.S85
-rw-r--r--arch/sparc64/lib/rwlock.S38
-rw-r--r--arch/sparc64/mm/fault.c4
-rw-r--r--arch/sparc64/mm/init.c80
88 files changed, 2213 insertions, 1600 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index df7ae01ca..d70d42421 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -126,6 +126,7 @@ if [ "$CONFIG_ALPHA_MIATA" = "y" -o "$CONFIG_ALPHA_LX164" = "y" \
then
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_EV5 y
+ define_bool CONFIG_ALPHA_CIA y
define_bool CONFIG_ALPHA_PYXIS y
fi
if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ]
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 6c538f4ba..9d87b6e0c 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -18,7 +18,7 @@ O_OBJS := entry.o traps.o process.o osf_sys.o irq.o irq_alpha.o \
OX_OBJS := alpha_ksyms.o
L_TARGET := rest.a
-L_OBJS := irq_i8259.o irq_srm.o \
+L_OBJS := irq_i8259.o irq_srm.o irq_pyxis.o \
es1888.o smc37c669.o smc37c93x.o ns87312.o
ifdef CONFIG_SMP
@@ -32,7 +32,7 @@ endif
ifdef CONFIG_ALPHA_GENERIC
O_OBJS += core_apecs.o core_cia.o core_irongate.o core_lca.o core_mcpcia.o \
- core_polaris.o core_pyxis.o core_t2.o core_tsunami.o \
+ core_polaris.o core_t2.o core_tsunami.o \
sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
@@ -56,9 +56,6 @@ endif
ifdef CONFIG_ALPHA_MCPCIA
O_OBJS += core_mcpcia.o
endif
-ifdef CONFIG_ALPHA_PYXIS
-O_OBJS += core_pyxis.o
-endif
ifdef CONFIG_ALPHA_T2
O_OBJS += core_t2.o
endif
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 25d9583dd..0001799db 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -37,6 +37,7 @@ extern struct hwrpb_struct *hwrpb;
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
extern spinlock_t kernel_flag;
+extern spinlock_t rtc_lock;
/* these are C runtime functions with special calling conventions: */
extern void __divl (void);
@@ -106,6 +107,7 @@ EXPORT_SYMBOL(pci_map_single);
EXPORT_SYMBOL(pci_unmap_single);
EXPORT_SYMBOL(pci_map_sg);
EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(pci_dma_supported);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
@@ -202,6 +204,8 @@ EXPORT_SYMBOL(__local_bh_count);
EXPORT_SYMBOL(__local_irq_count);
#endif /* __SMP__ */
+EXPORT_SYMBOL(rtc_lock);
+
/*
* The following are special because they're not called
* explicitly (the C compiler or assembler generates them in
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index b8a7f18ee..481a682b1 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1997, 1998 Jay Estabrook
- * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1998, 1999, 2000 Richard Henderson
*
* Code common to all CIA core logic chips.
*/
@@ -25,6 +25,8 @@
#include <asm/core_cia.h>
#undef __EXTERN_INLINE
+#include <linux/bootmem.h>
+
#include "proto.h"
#include "pci_impl.h"
@@ -35,27 +37,20 @@
* handle the system transaction. Another involves timing. Ho hum.
*/
-/*
- * BIOS32-style PCI interface:
- */
-
#define DEBUG_CONFIG 0
-#define DEBUG_DUMP_REGS 0
-
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
# define DBGC(args)
#endif
-#define vuip volatile unsigned int *
+#define vip volatile int *
/*
* Given a bus, device, and function number, compute resulting
- * configuration space address and setup the CIA_HAXR2 register
- * accordingly. It is therefore not safe to have concurrent
- * invocations to configuration space access routines, but there
- * really shouldn't be any need for this.
+ * configuration space address. It is therefore not safe to have
+ * concurrent invocations to configuration space access routines, but
+ * there really shouldn't be any need for this.
*
* Type 0:
*
@@ -96,34 +91,16 @@ static int
mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
- unsigned long addr;
u8 bus = dev->bus->number;
u8 device_fn = dev->devfn;
- DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, "
- "pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
+ *type1 = (bus != 0);
+ *pci_addr = (bus << 16) | (device_fn << 8) | where;
- if (bus == 0) {
- int device = device_fn >> 3;
+ DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " returning address 0x%p\n"
+ bus, device_fn, where, *pci_addr));
- /* Type 0 configuration cycle. */
-
- if (device > 20) {
- DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
- device));
- return -1;
- }
-
- *type1 = 0;
- addr = (device_fn << 8) | (where);
- } else {
- /* Type 1 configuration cycle. */
- *type1 = 1;
- addr = (bus << 16) | (device_fn << 8) | (where);
- }
- *pci_addr = addr;
- DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return 0;
}
@@ -131,43 +108,37 @@ static unsigned int
conf_read(unsigned long addr, unsigned char type1)
{
unsigned long flags;
- unsigned int stat0, value;
- unsigned int cia_cfg = 0;
+ int stat0, value;
+ int cia_cfg = 0;
- value = 0xffffffffU;
- mb();
-
- __save_and_cli(flags); /* avoid getting hit by machine check */
-
- DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+ DBGC(("conf_read(addr=0x%lx, type1=%d) ", addr, type1));
+ __save_and_cli(flags);
/* Reset status register to avoid losing errors. */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- *(vuip)CIA_IOC_CIA_ERR = stat0;
+ stat0 = *(vip)CIA_IOC_CIA_ERR;
+ *(vip)CIA_IOC_CIA_ERR = stat0;
mb();
- DBGC(("conf_read: CIA ERR was 0x%x\n", stat0));
/* If Type1 access, must set CIA CFG. */
if (type1) {
- cia_cfg = *(vuip)CIA_IOC_CFG;
- *(vuip)CIA_IOC_CFG = cia_cfg | 1;
+ cia_cfg = *(vip)CIA_IOC_CFG;
+ *(vip)CIA_IOC_CFG = (cia_cfg & ~3) | 1;
mb();
- DBGC(("conf_read: TYPE1 access\n"));
+ *(vip)CIA_IOC_CFG;
}
- mb();
draina();
mcheck_expected(0) = 1;
mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
- value = *(vuip)addr;
+ value = *(vip)addr;
mb();
mb(); /* magic */
if (mcheck_taken(0)) {
mcheck_taken(0) = 0;
- value = 0xffffffffU;
+ value = 0xffffffff;
mb();
}
mcheck_expected(0) = 0;
@@ -175,13 +146,14 @@ conf_read(unsigned long addr, unsigned char type1)
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
- *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
+ *(vip)CIA_IOC_CFG = cia_cfg;
mb();
+ *(vip)CIA_IOC_CFG;
}
- DBGC(("conf_read(): finished\n"));
-
__restore_flags(flags);
+ DBGC(("done\n"));
+
return value;
}
@@ -189,31 +161,31 @@ static void
conf_write(unsigned long addr, unsigned int value, unsigned char type1)
{
unsigned long flags;
- unsigned int stat0;
- unsigned int cia_cfg = 0;
+ int stat0, cia_cfg = 0;
- __save_and_cli(flags); /* avoid getting hit by machine check */
+ DBGC(("conf_write(addr=0x%lx, type1=%d) ", addr, type1));
+ __save_and_cli(flags);
/* Reset status register to avoid losing errors. */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- *(vuip)CIA_IOC_CIA_ERR = stat0;
+ stat0 = *(vip)CIA_IOC_CIA_ERR;
+ *(vip)CIA_IOC_CIA_ERR = stat0;
mb();
- DBGC(("conf_write: CIA ERR was 0x%x\n", stat0));
/* If Type1 access, must set CIA CFG. */
if (type1) {
- cia_cfg = *(vuip)CIA_IOC_CFG;
- *(vuip)CIA_IOC_CFG = cia_cfg | 1;
+ cia_cfg = *(vip)CIA_IOC_CFG;
+ *(vip)CIA_IOC_CFG = (cia_cfg & ~3) | 1;
mb();
- DBGC(("conf_write: TYPE1 access\n"));
+ *(vip)CIA_IOC_CFG;
}
draina();
mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
- *(vuip)addr = value;
+ *(vip)addr = value;
mb();
mb(); /* magic */
@@ -222,12 +194,13 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
- *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
+ *(vip)CIA_IOC_CFG = cia_cfg;
mb();
+ *(vip)CIA_IOC_CFG;
}
- DBGC(("conf_write(): finished\n"));
__restore_flags(flags);
+ DBGC(("done\n"));
}
static int
@@ -314,158 +287,442 @@ struct pci_ops cia_pci_ops =
write_dword: cia_write_config_dword
};
+/*
+ * CIA Pass 1 and PYXIS Pass 1 and 2 have a broken scatter-gather tlb.
+ * It cannot be invalidated. Rather than hard code the pass numbers,
+ * actually try the tbia to see if it works.
+ */
+
void
cia_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
{
wmb();
*(vip)CIA_IOC_PCI_TBIA = 3; /* Flush all locked and unlocked. */
mb();
+ *(vip)CIA_IOC_PCI_TBIA;
+}
+
+/*
+ * Fixup attempt number 1.
+ *
+ * Write zeros directly into the tag registers.
+ */
+
+static void
+cia_pci_tbi_try1(struct pci_controler *hose,
+ dma_addr_t start, dma_addr_t end)
+{
+ wmb();
+ *(vip)CIA_IOC_TB_TAGn(0) = 0;
+ *(vip)CIA_IOC_TB_TAGn(1) = 0;
+ *(vip)CIA_IOC_TB_TAGn(2) = 0;
+ *(vip)CIA_IOC_TB_TAGn(3) = 0;
+ *(vip)CIA_IOC_TB_TAGn(4) = 0;
+ *(vip)CIA_IOC_TB_TAGn(5) = 0;
+ *(vip)CIA_IOC_TB_TAGn(6) = 0;
+ *(vip)CIA_IOC_TB_TAGn(7) = 0;
+ mb();
+ *(vip)CIA_IOC_TB_TAGn(0);
+}
+
+#if 0
+/*
+ * Fixup attempt number 2. This is the method NT and NetBSD use.
+ *
+ * Allocate mappings, and put the chip into DMA loopback mode to read a
+ * garbage page. This works by causing TLB misses, causing old entries to
+ * be purged to make room for the new entries coming in for the garbage page.
+ */
+
+#define CIA_BROKEN_TBI_TRY2_BASE 0xE0000000
+
+static void __init
+cia_enable_broken_tbi_try2(void)
+{
+ unsigned long *ppte, pte;
+ long i;
+
+ ppte = __alloc_bootmem(PAGE_SIZE, 32768, 0);
+ pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1;
+
+ for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); ++i)
+ ppte[i] = pte;
+
+ *(vip)CIA_IOC_PCI_W3_BASE = CIA_BROKEN_TBI_TRY2_BASE | 3;
+ *(vip)CIA_IOC_PCI_W3_MASK = (PAGE_SIZE - 1) & 0xfff00000;
+ *(vip)CIA_IOC_PCI_T3_BASE = virt_to_phys(ppte) >> 2;
+}
+
+static void
+cia_pci_tbi_try2(struct pci_controler *hose,
+ dma_addr_t start, dma_addr_t end)
+{
+ unsigned long flags;
+ unsigned long bus_addr;
+ int ctrl;
+ long i;
+
+ __save_and_cli(flags);
+
+ /* Put the chip into PCI loopback mode. */
+ mb();
+ ctrl = *(vip)CIA_IOC_CIA_CTRL;
+ *(vip)CIA_IOC_CIA_CTRL = ctrl | CIA_CTRL_PCI_LOOP_EN;
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL;
+ mb();
+
+ /* Read from PCI dense memory space at TBI_ADDR, skipping 32k on
+ each read. This forces SG TLB misses. NetBSD claims that the
+ TLB entries are not quite LRU, meaning that we need to read more
+ times than there are actual tags. The 2117x docs claim strict
+ round-robin. Oh well, we've come this far... */
+
+ bus_addr = cia_ioremap(CIA_BROKEN_TBI_TRY2_BASE);
+ for (i = 0; i < 12; ++i, bus_addr += 32768)
+ cia_readl(bus_addr);
+
+ /* Restore normal PCI operation. */
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL = ctrl;
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL;
+ mb();
+
+ __restore_flags(flags);
+}
+#endif
+
+static void __init
+verify_tb_operation(void)
+{
+ static int page[PAGE_SIZE/4]
+ __attribute__((aligned(PAGE_SIZE)))
+ __initlocaldata = { 0 };
+
+ struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
+ int ctrl, addr0, tag0, pte0, data0;
+ int temp;
+
+ /* Put the chip into PCI loopback mode. */
+ mb();
+ ctrl = *(vip)CIA_IOC_CIA_CTRL;
+ *(vip)CIA_IOC_CIA_CTRL = ctrl | CIA_CTRL_PCI_LOOP_EN;
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL;
+ mb();
+
+ /* Write a valid entry directly into the TLB registers. */
+
+ addr0 = arena->dma_base;
+ tag0 = addr0 | 1;
+ pte0 = (virt_to_phys(page) >> (PAGE_SHIFT - 1)) | 1;
+
+ *(vip)CIA_IOC_TB_TAGn(0) = tag0;
+ *(vip)CIA_IOC_TB_TAGn(1) = 0;
+ *(vip)CIA_IOC_TB_TAGn(2) = 0;
+ *(vip)CIA_IOC_TB_TAGn(3) = 0;
+ *(vip)CIA_IOC_TB_TAGn(4) = 0;
+ *(vip)CIA_IOC_TB_TAGn(5) = 0;
+ *(vip)CIA_IOC_TB_TAGn(6) = 0;
+ *(vip)CIA_IOC_TB_TAGn(7) = 0;
+ *(vip)CIA_IOC_TBn_PAGEm(0,0) = pte0;
+ *(vip)CIA_IOC_TBn_PAGEm(0,1) = 0;
+ *(vip)CIA_IOC_TBn_PAGEm(0,2) = 0;
+ *(vip)CIA_IOC_TBn_PAGEm(0,3) = 0;
+ mb();
+
+ /* First, verify we can read back what we've written. If
+ this fails, we can't be sure of any of the other testing
+ we're going to do, so bail. */
+ /* ??? Actually, we could do the work with machine checks.
+ By passing this register update test, we pretty much
+ guarantee that cia_pci_tbi_try1 works. If this test
+ fails, cia_pci_tbi_try2 might still work. */
+
+ temp = *(vip)CIA_IOC_TB_TAGn(0);
+ if (temp != tag0) {
+ printk("pci: failed tb register update test "
+ "(tag0 %#x != %#x)\n", temp, tag0);
+ goto failed;
+ }
+ temp = *(vip)CIA_IOC_TB_TAGn(1);
+ if (temp != 0) {
+ printk("pci: failed tb register update test "
+ "(tag1 %#x != 0)\n", temp);
+ goto failed;
+ }
+ temp = *(vip)CIA_IOC_TBn_PAGEm(0,0);
+ if (temp != pte0) {
+ printk("pci: failed tb register update test "
+ "(pte0 %#x != %#x)\n", temp, pte0);
+ goto failed;
+ }
+ printk("pci: passed tb register update test\n");
+
+ /* Second, verify we can actually do I/O through this entry. */
+
+ data0 = 0xdeadbeef;
+ page[0] = data0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
+ mb();
+ temp = cia_readl(cia_ioremap(addr0));
+ mb();
+ mcheck_expected(0) = 0;
+ mb();
+ if (mcheck_taken(0)) {
+ printk("pci: failed sg loopback i/o read test (mcheck)\n");
+ goto failed;
+ }
+ if (temp != data0) {
+ printk("pci: failed sg loopback i/o read test "
+ "(%#x != %#x)\n", temp, data0);
+ goto failed;
+ }
+ printk("pci: passed sg loopback i/o read test\n");
+
+ /* Third, try to invalidate the TLB. */
+
+ cia_pci_tbi(arena->hose, 0, -1);
+ temp = *(vip)CIA_IOC_TB_TAGn(0);
+ if (temp & 1) {
+ cia_pci_tbi_try1(arena->hose, 0, -1);
+
+ temp = *(vip)CIA_IOC_TB_TAGn(0);
+ if (temp & 1) {
+ printk("pci: failed tbia test; "
+ "no usable workaround\n");
+ goto failed;
+ }
+
+ alpha_mv.mv_pci_tbi = cia_pci_tbi_try1;
+ printk("pci: failed tbia test; workaround 1 succeeded\n");
+ } else {
+ printk("pci: passed tbia test\n");
+ }
+
+ /* Fourth, verify the TLB snoops the EV5's caches when
+ doing a tlb fill. */
+
+ data0 = 0x5adda15e;
+ page[0] = data0;
+ arena->ptes[4] = pte0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
+ mb();
+ temp = cia_readl(cia_ioremap(addr0 + 4*PAGE_SIZE));
+ mb();
+ mcheck_expected(0) = 0;
+ mb();
+ if (mcheck_taken(0)) {
+ printk("pci: failed pte write cache snoop test (mcheck)\n");
+ goto failed;
+ }
+ if (temp != data0) {
+ printk("pci: failed pte write cache snoop test "
+ "(%#x != %#x)\n", temp, data0);
+ goto failed;
+ }
+ printk("pci: passed pte write cache snoop test\n");
+
+ /* Fifth, verify that a previously invalid PTE entry gets
+ filled from the page table. */
+
+ data0 = 0xabcdef123;
+ page[0] = data0;
+ arena->ptes[5] = pte0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
+ mb();
+ temp = cia_readl(cia_ioremap(addr0 + 5*PAGE_SIZE));
+ mb();
+ mcheck_expected(0) = 0;
+ mb();
+ if (mcheck_taken(0)) {
+ printk("pci: failed valid tag invalid pte reload test "
+ "(mcheck; workaround available)\n");
+ /* Work around this bug by aligning new allocations
+ on 4 page boundaries. */
+ arena->align_entry = 4;
+ } else if (temp != data0) {
+ printk("pci: failed valid tag invalid pte reload test "
+ "(%#x != %#x)\n", temp, data0);
+ goto failed;
+ } else {
+ printk("pci: passed valid tag invalid pte reload test\n");
+ }
+
+ /* Sixth, verify machine checks are working. Test invalid
+ pte under the same valid tag as we used above. */
+
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
+ mb();
+ temp = cia_readl(cia_ioremap(addr0 + 6*PAGE_SIZE));
+ mb();
+ mcheck_expected(0) = 0;
+ mb();
+ printk("pci: %s pci machine check test\n",
+ mcheck_taken(0) ? "passed" : "failed");
+
+ /* Clean up after the tests. */
+ arena->ptes[4] = 0;
+ arena->ptes[5] = 0;
+ alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
+
+exit:
+ /* Restore normal PCI operation. */
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL = ctrl;
+ mb();
+ *(vip)CIA_IOC_CIA_CTRL;
+ mb();
+ return;
+
+failed:
+ printk("pci: disabling sg translation window\n");
+ *(vip)CIA_IOC_PCI_W0_BASE = 0;
+ alpha_mv.mv_pci_tbi = NULL;
+ goto exit;
}
-void __init
-cia_init_arch(void)
+static void __init
+do_init_arch(int is_pyxis)
{
struct pci_controler *hose;
- struct resource *hae_mem;
- unsigned int temp;
-
-#if DEBUG_DUMP_REGS
- temp = *(vuip)CIA_IOC_CIA_REV; mb();
- printk("cia_init: CIA_REV was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PCI_LAT; mb();
- printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("cia_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)0xfffffc8740000140UL; mb();
- printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_MEM; mb();
- printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_IO; mb();
- printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("cia_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CACK_EN; mb();
- printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("cia_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
- printk("cia_init: CIA_DIAG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
- printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
- printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
- printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_ERR; mb();
- printk("cia_init: CIA_ERR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_STAT; mb();
- printk("cia_init: CIA_STAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_MCR; mb();
- printk("cia_init: CIA_MCR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("cia_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_ERR_MASK; mb();
- printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
- printk("cia_init: W0_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
- printk("cia_init: W1_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
- printk("cia_init: W2_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
- printk("cia_init: W3_BASE was 0x%x\n", temp);
-#endif /* DEBUG_DUMP_REGS */
+ int temp;
+ int cia_rev;
+
+ cia_rev = *(vip)CIA_IOC_CIA_REV & CIA_REV_MASK;
+ printk("pci: cia revision %d%s\n",
+ cia_rev, is_pyxis ? " (pyxis)" : "");
+
+ /* Set up error reporting. */
+ temp = *(vip)CIA_IOC_ERR_MASK;
+ temp &= ~(CIA_ERR_CPU_PE | CIA_ERR_MEM_NEM | CIA_ERR_PA_PTE_INV
+ | CIA_ERR_RCVD_MAS_ABT | CIA_ERR_RCVD_TAR_ABT);
+ *(vip)CIA_IOC_ERR_MASK = temp;
+
+ /* Clear all currently pending errors. */
+ *(vip)CIA_IOC_CIA_ERR = 0;
+
+ /* Turn on mchecks. */
+ temp = *(vip)CIA_IOC_CIA_CTRL;
+ temp |= CIA_CTRL_FILL_ERR_EN | CIA_CTRL_MCHK_ERR_EN;
+ *(vip)CIA_IOC_CIA_CTRL = temp;
+
+ /* Clear the CFG register, which gets used for PCI config space
+ accesses. That is the way we want to use it, and we do not
+ want to depend on what ARC or SRM might have left behind. */
+ *(vip)CIA_IOC_CFG = 0;
+
+ /* Zero the HAEs. */
+ *(vip)CIA_IOC_HAE_MEM = 0;
+ *(vip)CIA_IOC_HAE_IO = 0;
+
+ /* For PYXIS, we always use BWX bus and i/o accesses. To that end,
+ make sure they're enabled on the controler. */
+ if (is_pyxis) {
+ temp = *(vip)CIA_IOC_CIA_CNFG;
+ temp |= CIA_CNFG_IOA_BWEN;
+ *(vip)CIA_IOC_CIA_CNFG = temp;
+ }
+
+ /* Syncronize with all previous changes. */
+ mb();
+ *(vip)CIA_IOC_CIA_REV;
/*
* Create our single hose.
*/
pci_isa_hose = hose = alloc_pci_controler();
- hae_mem = alloc_resource();
-
hose->io_space = &ioport_resource;
- hose->mem_space = hae_mem;
+ hose->mem_space = &iomem_resource;
hose->config_space = CIA_CONF;
hose->index = 0;
- hae_mem->start = 0;
- hae_mem->end = CIA_MEM_R1_MASK;
- hae_mem->name = pci_hae0_name;
- hae_mem->flags = IORESOURCE_MEM;
+ if (! is_pyxis) {
+ struct resource *hae_mem = alloc_resource();
+ hose->mem_space = hae_mem;
+
+ hae_mem->start = 0;
+ hae_mem->end = CIA_MEM_R1_MASK;
+ hae_mem->name = pci_hae0_name;
+ hae_mem->flags = IORESOURCE_MEM;
- if (request_resource(&iomem_resource, hae_mem) < 0)
- printk(KERN_ERR "Failed to request HAE_MEM\n");
+ if (request_resource(&iomem_resource, hae_mem) < 0)
+ printk(KERN_ERR "Failed to request HAE_MEM\n");
+ }
/*
* Set up the PCI to main memory translation windows.
*
* Window 0 is scatter-gather 8MB at 8MB (for isa)
- * Window 1 is scatter-gather 128MB at 1GB
- * Window 2 is direct access 2GB at 2GB
- * ??? We ought to scale window 1 with memory.
+ * Window 1 is direct access 1GB at 1GB
+ * Window 2 is direct access 1GB at 2GB
+ *
+ * We must actually use 2 windows to direct-map the 2GB space,
+ * because of an idiot-syncrasy of the CYPRESS chip used on
+ * many PYXIS systems. It may respond to a PCI bus address in
+ * the last 1MB of the 4GB address range.
+ *
+ * ??? NetBSD hints that page tables must be aligned to 32K,
+ * possibly due to a hardware bug. This is over-aligned
+ * from the 8K alignment one would expect for an 8MB window.
+ * No description of what revisions affected.
*/
- /* ??? NetBSD hints that page tables must be aligned to 32K,
- possibly due to a hardware bug. This is over-aligned
- from the 8K alignment one would expect for an 8MB window.
- No description of what CIA revisions affected. */
- hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0x8000);
- hose->sg_pci = iommu_arena_new(hose, 0x40000000, 0x08000000, 0);
- __direct_map_base = 0x80000000;
+ hose->sg_pci = NULL;
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 32768);
+ __direct_map_base = 0x40000000;
__direct_map_size = 0x80000000;
- *(vuip)CIA_IOC_PCI_W0_BASE = hose->sg_isa->dma_base | 3;
- *(vuip)CIA_IOC_PCI_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
- *(vuip)CIA_IOC_PCI_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
-
- *(vuip)CIA_IOC_PCI_W1_BASE = hose->sg_pci->dma_base | 3;
- *(vuip)CIA_IOC_PCI_W1_MASK = (hose->sg_pci->size - 1) & 0xfff00000;
- *(vuip)CIA_IOC_PCI_T1_BASE = virt_to_phys(hose->sg_pci->ptes) >> 2;
+ *(vip)CIA_IOC_PCI_W0_BASE = hose->sg_isa->dma_base | 3;
+ *(vip)CIA_IOC_PCI_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
+ *(vip)CIA_IOC_PCI_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
- *(vuip)CIA_IOC_PCI_W2_BASE = __direct_map_base | 1;
- *(vuip)CIA_IOC_PCI_W2_MASK = (__direct_map_size - 1) & 0xfff00000;
- *(vuip)CIA_IOC_PCI_T2_BASE = 0;
+ *(vip)CIA_IOC_PCI_W1_BASE = 0x40000000 | 1;
+ *(vip)CIA_IOC_PCI_W1_MASK = (0x40000000 - 1) & 0xfff00000;
+ *(vip)CIA_IOC_PCI_T1_BASE = 0;
- *(vuip)CIA_IOC_PCI_W3_BASE = 0;
+ *(vip)CIA_IOC_PCI_W2_BASE = 0x80000000 | 1;
+ *(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000;
+ *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000;
- cia_pci_tbi(hose, 0, -1);
+ *(vip)CIA_IOC_PCI_W3_BASE = 0;
+}
- /*
- * Set up error reporting.
- */
- temp = *(vuip)CIA_IOC_CIA_ERR;
- temp |= 0x180; /* master, target abort */
- *(vuip)CIA_IOC_CIA_ERR = temp;
+void __init
+cia_init_arch(void)
+{
+ do_init_arch(0);
+}
- temp = *(vuip)CIA_IOC_CIA_CTRL;
- temp |= 0x400; /* turn on FILL_ERR to get mchecks */
- *(vuip)CIA_IOC_CIA_CTRL = temp;
+void __init
+pyxis_init_arch(void)
+{
+ do_init_arch(1);
+}
- /*
- * Next, clear the CIA_CFG register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- *(vuip)CIA_IOC_CFG = 0;
-
- /*
- * Zero the HAEs.
- */
- *(vuip)CIA_IOC_HAE_MEM = 0;
- *(vuip)CIA_IOC_HAE_IO = 0;
- mb();
+void __init
+cia_init_pci(void)
+{
+ /* Must delay this from init_arch, as we need machine checks. */
+ verify_tb_operation();
+ common_init_pci();
}
static inline void
cia_pci_clr_err(void)
{
- unsigned int jd;
+ int jd;
- jd = *(vuip)CIA_IOC_CIA_ERR;
- *(vuip)CIA_IOC_CIA_ERR = jd;
+ jd = *(vip)CIA_IOC_CIA_ERR;
+ *(vip)CIA_IOC_CIA_ERR = jd;
mb();
- *(vuip)CIA_IOC_CIA_ERR; /* re-read to force write. */
+ *(vip)CIA_IOC_CIA_ERR; /* re-read to force write. */
}
void
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
deleted file mode 100644
index f6106c475..000000000
--- a/arch/alpha/kernel/core_pyxis.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * linux/arch/alpha/kernel/core_pyxis.c
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- * Code common to all PYXIS core logic chips.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#define __EXTERN_INLINE inline
-#include <asm/io.h>
-#include <asm/core_pyxis.h>
-#undef __EXTERN_INLINE
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-
-#include "proto.h"
-#include "irq_impl.h"
-#include "pci_impl.h"
-
-
-/* NOTE: Herein are back-to-back mb instructions. They are magic.
- One plausible explanation is that the I/O controller does not properly
- handle the system transaction. Another involves timing. Ho hum. */
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#define DEBUG_CONFIG 0
-#if DEBUG_CONFIG
-# define DBG_CNF(args) printk args
-#else
-# define DBG_CNF(args)
-#endif
-
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the PYXIS_HAXR2 register
- * accordingly. It is therefore not safe to have concurrent
- * invocations to configuration space access routines, but there
- * really shouldn't be any need for this.
- *
- * Type 0:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:11 Device select bit.
- * 10:8 Function number
- * 7:2 Register number
- *
- * Type 1:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:24 reserved
- * 23:16 bus number (8 bits = 128 possible buses)
- * 15:11 Device number (5 bits)
- * 10:8 function number
- * 7:2 register number
- *
- * Notes:
- * The function number selects which function of a multi-function device
- * (e.g., SCSI and Ethernet).
- *
- * The register selects a DWORD (32 bit) register offset. Hence it
- * doesn't get shifted by 2 bits as we want to "drop" the bottom two
- * bits.
- */
-
-static int
-mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
- unsigned char *type1)
-{
- u8 bus = dev->bus->number;
- u8 device_fn = dev->devfn;
-
- *type1 = (bus == 0) ? 0 : 1;
- *pci_addr = (bus << 16) | (device_fn << 8) | (where);
-
- DBG_CNF(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
- " returning address 0x%p\n"
- bus, device_fn, where, *pci_addr));
-
- return 0;
-}
-
-static unsigned int
-conf_read(unsigned long addr, unsigned char type1)
-{
- unsigned long flags;
- unsigned int stat0, value, temp;
- unsigned int pyxis_cfg = 0;
-
- __save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* Reset status register to avoid losing errors. */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
-
- /* If Type1 access, must set PYXIS CFG. */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = (pyxis_cfg & ~3L) | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- mb();
- draina();
- mcheck_expected(0) = 1;
- mcheck_taken(0) = 0;
- mb();
-
- /* Access configuration space. */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
-
- if (mcheck_taken(0)) {
- mcheck_taken(0) = 0;
- value = 0xffffffffU;
- mb();
- }
- mcheck_expected(0) = 0;
- mb();
-
- /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~3L; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- __restore_flags(flags);
-
- DBG_CNF(("conf_read(addr=0x%lx, type1=%d) = %#x\n",
- addr, type1, value));
-
- return value;
-}
-
-static void
-conf_write(unsigned long addr, unsigned int value, unsigned char type1)
-{
- unsigned long flags;
- unsigned int stat0, temp;
- unsigned int pyxis_cfg = 0;
-
- __save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* Reset status register to avoid losing errors. */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
-
- /* If Type1 access, must set PYXIS CFG. */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = (pyxis_cfg & ~3L) | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- mb();
- draina();
- mcheck_expected(0) = 1;
- mcheck_taken(0) = 0;
- mb();
-
- /* Access configuration space. */
- *(vuip)addr = value;
- mb();
- temp = *(vuip)addr; /* read back to force the write */
- mcheck_expected(0) = 0;
- mb();
-
- /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~3L; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- __restore_flags(flags);
-
- DBG_CNF(("conf_write(addr=%#lx, value=%#x, type1=%d)\n",
- addr, value, type1));
-}
-
-static int
-pyxis_read_config_byte(struct pci_dev *dev, int where, u8 *value)
-{
- unsigned long addr, pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(dev, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = (pci_addr << 5) + 0x00 + PYXIS_CONF;
- *value = conf_read(addr, type1) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pyxis_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
- unsigned long addr, pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(dev, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = (pci_addr << 5) + 0x08 + PYXIS_CONF;
- *value = conf_read(addr, type1) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pyxis_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
- unsigned long addr, pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(dev, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = (pci_addr << 5) + 0x18 + PYXIS_CONF;
- *value = conf_read(addr, type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pyxis_write_config(struct pci_dev *dev, int where, u32 value, long mask)
-{
- unsigned long addr, pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(dev, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = (pci_addr << 5) + mask + PYXIS_CONF;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pyxis_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
- return pyxis_write_config(dev, where, value, 0x00);
-}
-
-static int
-pyxis_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
- return pyxis_write_config(dev, where, value, 0x08);
-}
-
-static int
-pyxis_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
- return pyxis_write_config(dev, where, value, 0x18);
-}
-
-struct pci_ops pyxis_pci_ops =
-{
- read_byte: pyxis_read_config_byte,
- read_word: pyxis_read_config_word,
- read_dword: pyxis_read_config_dword,
- write_byte: pyxis_write_config_byte,
- write_word: pyxis_write_config_word,
- write_dword: pyxis_write_config_dword
-};
-
-/* Note mask bit is true for ENABLED irqs. */
-static unsigned long cached_irq_mask;
-
-static inline void
-pyxis_update_irq_hw(unsigned long mask)
-{
- *(vulp)PYXIS_INT_MASK = mask;
- mb();
- *(vulp)PYXIS_INT_MASK;
-}
-
-static inline void
-pyxis_enable_irq(unsigned int irq)
-{
- pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
-}
-
-static void
-pyxis_disable_irq(unsigned int irq)
-{
- pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
-}
-
-static unsigned int
-pyxis_startup_irq(unsigned int irq)
-{
- pyxis_enable_irq(irq);
- return 0;
-}
-
-static void
-pyxis_end_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- pyxis_enable_irq(irq);
-}
-
-static void
-pyxis_mask_and_ack_irq(unsigned int irq)
-{
- unsigned long bit = 1UL << (irq - 16);
- unsigned long mask = cached_irq_mask &= ~bit;
-
- /* Disable the interrupt. */
- *(vulp)PYXIS_INT_MASK = mask;
- wmb();
- /* Ack PYXIS PCI interrupt. */
- *(vulp)PYXIS_INT_REQ = bit;
- mb();
- /* Re-read to force both writes. */
- *(vulp)PYXIS_INT_MASK;
-}
-
-static struct hw_interrupt_type pyxis_irq_type = {
- typename: "PYXIS",
- startup: pyxis_startup_irq,
- shutdown: pyxis_disable_irq,
- enable: pyxis_enable_irq,
- disable: pyxis_disable_irq,
- ack: pyxis_mask_and_ack_irq,
- end: pyxis_end_irq,
-};
-
-void
-pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
- pld &= cached_irq_mask;
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7)
- isa_device_interrupt(vector, regs);
- else
- handle_irq(16+i, regs);
- }
-}
-
-void __init
-init_pyxis_irqs(unsigned long ignore_mask)
-{
- long i;
-
- *(vulp)PYXIS_INT_MASK = 0; /* disable all */
- *(vulp)PYXIS_INT_REQ = -1; /* flush all */
- mb();
-
- /* Send -INTA pulses to clear any pending interrupts ...*/
- *(vuip) PYXIS_IACK_SC;
-
- for (i = 16; i < 48; ++i) {
- if ((ignore_mask >> i) & 1)
- continue;
- irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
- irq_desc[i].handler = &pyxis_irq_type;
- }
-
- setup_irq(16+7, &isa_cascade_irqaction);
-}
-
-void
-pyxis_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
-{
- wmb();
- *(vip)PYXIS_TBIA = 3; /* Flush all locked and unlocked. */
- mb();
-}
-
-/*
- * Pass 1 and 2 have a broken scatter-gather tlb -- it cannot be invalidated.
- * To work around this problem, we allocate mappings, and put the chip into
- * DMA loopback mode to read a garbage page. This works by causing TLB
- * misses, causing old entries to be purged to make room for the new entries
- * coming in for the garbage page.
- *
- * Thanks to NetBSD sources for pointing out this bug. What a pain.
- */
-
-static unsigned long broken_tbi_addr;
-
-#define BROKEN_TBI_READS 12
-
-static void
-pyxis_broken_pci_tbi(struct pci_controler *hose,
- dma_addr_t start, dma_addr_t end)
-{
- unsigned long flags;
- unsigned long bus_addr;
- unsigned int ctrl;
- long i;
-
- __save_and_cli(flags);
-
- /* Put the chip into PCI loopback mode. */
- mb();
- ctrl = *(vuip)PYXIS_CTRL;
- *(vuip)PYXIS_CTRL = ctrl | 4;
- mb();
- *(vuip)PYXIS_CTRL;
- mb();
-
- /* Read from PCI dense memory space at TBI_ADDR, skipping 64k
- on each read. This forces SG TLB misses. It appears that
- the TLB entries are "not quite LRU", meaning that we need
- to read more times than there are actual tags. */
-
- bus_addr = broken_tbi_addr;
- for (i = 0; i < BROKEN_TBI_READS; ++i, bus_addr += 64*1024)
- pyxis_readl(bus_addr);
-
- /* Restore normal PCI operation. */
- mb();
- *(vuip)PYXIS_CTRL = ctrl;
- mb();
- *(vuip)PYXIS_CTRL;
- mb();
-
- __restore_flags(flags);
-}
-
-static void __init
-pyxis_enable_broken_tbi(struct pci_iommu_arena *arena)
-{
- void *page;
- unsigned long *ppte, ofs, pte;
- long i, npages;
-
- page = alloc_bootmem_pages(PAGE_SIZE);
- pte = (virt_to_phys(page) >> (PAGE_SHIFT - 1)) | 1;
- npages = (BROKEN_TBI_READS + 1) * 64*1024 / PAGE_SIZE;
-
- ofs = iommu_arena_alloc(arena, npages);
- ppte = arena->ptes + ofs;
- for (i = 0; i < npages; ++i)
- ppte[i] = pte;
-
- broken_tbi_addr = pyxis_ioremap(arena->dma_base + ofs*PAGE_SIZE);
- alpha_mv.mv_pci_tbi = pyxis_broken_pci_tbi;
-
- printk("PYXIS: Enabling broken tbia workaround.\n");
-}
-
-void __init
-pyxis_init_arch(void)
-{
- struct pci_controler *hose;
- unsigned int temp;
-
- /* Set up error reporting. Make sure CPU_PE is OFF in the mask. */
- temp = *(vuip)PYXIS_ERR_MASK;
- *(vuip)PYXIS_ERR_MASK = temp & ~4;
-
- /* Enable master/target abort. */
- temp = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = temp | 0x180;
-
- /* Clear the PYXIS_CFG register, which gets used for PCI Config
- Space accesses. That is the way we want to use it, and we do
- not want to depend on what ARC or SRM might have left behind. */
- *(vuip)PYXIS_CFG = 0;
-
- /* Zero the HAEs. */
- *(vuip)PYXIS_HAE_MEM = 0;
- *(vuip)PYXIS_HAE_IO = 0;
-
- /* Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
- enabling byte/word PCI bus space(s) access. */
- temp = *(vuip)PYXIS_CTRL1;
- *(vuip)PYXIS_CTRL1 = temp | 1;
-
- /* Syncronize with all previous changes. */
- mb();
- *(vuip)PYXIS_REV;
-
- /*
- * Create our single hose.
- */
-
- hose = alloc_pci_controler();
- hose->io_space = &ioport_resource;
- hose->mem_space = &iomem_resource;
- hose->config_space = PYXIS_CONF;
- hose->index = 0;
-
- /*
- * Set up the PCI to main memory translation windows.
- *
- * Window 0 is scatter-gather 8MB at 8MB (for isa)
- * Window 1 is scatter-gather 128MB at 3GB
- * Window 2 is direct access 1GB at 1GB
- * Window 3 is direct access 1GB at 2GB
- * ??? We ought to scale window 1 with memory.
- *
- * We must actually use 2 windows to direct-map the 2GB space,
- * because of an idiot-syncrasy of the CYPRESS chip. It may
- * respond to a PCI bus address in the last 1MB of the 4GB
- * address range.
- */
-
-#if 1
- /* ??? There's some bit of syncronization wrt writing new tlb
- entries that's missing. Sometimes it works, sometimes invalid
- tlb machine checks, sometimes hard lockup. And this just within
- the boot sequence.
-
- I've tried extra memory barriers, extra alignment, pyxis
- register reads, tlb flushes, and loopback tlb accesses.
-
- I guess the pyxis revision in the sx164 is just too buggy... */
-
- hose->sg_isa = hose->sg_pci = NULL;
- __direct_map_base = 0x40000000;
- __direct_map_size = 0x80000000;
-
- *(vuip)PYXIS_W0_BASE = 0x40000000 | 1;
- *(vuip)PYXIS_W0_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vuip)PYXIS_T0_BASE = 0;
-
- *(vuip)PYXIS_W1_BASE = 0x80000000 | 1;
- *(vuip)PYXIS_W1_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vuip)PYXIS_T1_BASE = 0;
-
- *(vuip)PYXIS_W2_BASE = 0;
- *(vuip)PYXIS_W3_BASE = 0;
-
- alpha_mv.mv_pci_tbi = NULL;
- mb();
-#else
- /* ??? NetBSD hints that page tables must be aligned to 32K,
- possibly due to a hardware bug. This is over-aligned
- from the 8K alignment one would expect for an 8MB window.
- No description of what CIA revisions affected. */
- hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0x08000);
- hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0x20000);
- __direct_map_base = 0x40000000;
- __direct_map_size = 0x80000000;
-
- *(vuip)PYXIS_W0_BASE = hose->sg_isa->dma_base | 3;
- *(vuip)PYXIS_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
- *(vuip)PYXIS_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
-
- *(vuip)PYXIS_W1_BASE = hose->sg_pci->dma_base | 3;
- *(vuip)PYXIS_W1_MASK = (hose->sg_pci->size - 1) & 0xfff00000;
- *(vuip)PYXIS_T1_BASE = virt_to_phys(hose->sg_pci->ptes) >> 2;
-
- *(vuip)PYXIS_W2_BASE = 0x40000000 | 1;
- *(vuip)PYXIS_W2_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vuip)PYXIS_T2_BASE = 0;
-
- *(vuip)PYXIS_W3_BASE = 0x80000000 | 1;
- *(vuip)PYXIS_W3_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vuip)PYXIS_T3_BASE = 0;
-
- /* Pass 1 and 2 (ie revision <= 1) have a broken TBIA. See the
- complete description next to pyxis_broken_pci_tbi for details. */
- if ((*(vuip)PYXIS_REV & 0xff) <= 1)
- pyxis_enable_broken_tbi(hose->sg_pci);
-
- alpha_mv.mv_pci_tbi(hose, 0, -1);
-#endif
-}
-
-static inline void
-pyxis_pci_clr_err(void)
-{
- unsigned int tmp;
-
- tmp = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = tmp;
- mb();
- *(vuip)PYXIS_ERR; /* re-read to force write */
-}
-
-void
-pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- int expected;
-
- /* Clear the error before reporting anything. */
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
-
- expected = mcheck_expected(0);
- if (!expected && vector == 0x660) {
- struct el_common *com;
- struct el_common_EV5_uncorrectable_mcheck *ev5;
- struct el_PYXIS_sysdata_mcheck *pyxis;
-
- com = (void *)la_ptr;
- ev5 = (void *)(la_ptr + com->proc_offset);
- pyxis = (void *)(la_ptr + com->sys_offset);
-
- if (com->code == 0x202) {
- printk(KERN_CRIT "PYXIS PCI machine check: err0=%08x "
- "err1=%08x err2=%08x\n",
- (int) pyxis->pci_err0, (int) pyxis->pci_err1,
- (int) pyxis->pci_err2);
- expected = 1;
- }
- }
- process_mcheck_info(vector, la_ptr, regs, "PYXIS", expected);
-}
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 1fa5a8088..1ddcd36d1 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -363,7 +363,7 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
pchip->wsba[3].csr = 0x80000000 | 1;
pchip->wsm[3].csr = (0x40000000 - 1) & 0xfff00000;
- pchip->tba[3].csr = 0;
+ pchip->tba[3].csr = 0x40000000;
tsunami_pci_tbi(hose, 0, -1);
}
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 5f1a6f59a..0b9e1786d 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -8,7 +8,7 @@
#define SIGCHLD 20
-#define NR_SYSCALLS 374
+#define NR_SYSCALLS 376
/*
* These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -991,7 +991,7 @@ sys_call_table:
.quad osf_shmat
.quad sys_shmctl /* 210 */
.quad sys_shmdt
- .quad osf_shmget
+ .quad sys_shmget
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 215 */
@@ -1154,4 +1154,5 @@ sys_call_table:
.quad sys_setresgid
.quad sys_getresgid
.quad sys_ni_syscall /* sys_dipc */
- .quad sys_shmget
+ .quad sys_pivot_root
+ .quad sys_mincore /* 375 */
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index bc8ca101a..1f454cf48 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -219,15 +219,33 @@ setup_irq(unsigned int irq, struct irqaction * new)
}
spin_unlock_irqrestore(&desc->lock,flags);
- register_irq_proc(irq);
return 0;
}
static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+static struct proc_dir_entry * irq_dir[NR_IRQS];
-static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+#ifdef CONFIG_SMP
+static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
+static char irq_user_affinity[NR_IRQS];
+static unsigned long irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+
+static void
+select_smp_affinity(int irq)
+{
+ static int last_cpu;
+ int cpu = last_cpu + 1;
+
+ if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
+ return;
+
+ while (((cpu_present_mask >> cpu) & 1) == 0)
+ cpu = (cpu < NR_CPUS ? cpu + 1 : 0);
+ last_cpu = cpu;
+
+ irq_affinity[irq] = 1UL << cpu;
+ irq_desc[irq].handler->set_affinity(irq, 1UL << cpu);
+}
#define HEX_DIGITS 16
@@ -290,18 +308,22 @@ irq_affinity_write_proc(struct file *file, const char *buffer,
err = parse_hex_value(buffer, count, &new_value);
-#if CONFIG_SMP
- /*
- * Do not allow disabling IRQs completely - it's a too easy
- * way to make the system unusable accidentally :-) At least
- * one online CPU still has to be targeted.
- */
- if (!(new_value & cpu_present_mask))
+ /* The special value 0 means release control of the
+ affinity to kernel. */
+ if (new_value == 0) {
+ irq_user_affinity[irq] = 0;
+ select_smp_affinity(irq);
+ }
+ /* Do not allow disabling IRQs completely - it's a too easy
+ way to make the system unusable accidentally :-) At least
+ one online CPU still has to be targeted. */
+ else if (!(new_value & cpu_present_mask))
return -EINVAL;
-#endif
-
- irq_affinity[irq] = new_value;
- irq_desc[irq].handler->set_affinity(irq, new_value);
+ else {
+ irq_affinity[irq] = new_value;
+ irq_user_affinity[irq] = 1;
+ irq_desc[irq].handler->set_affinity(irq, new_value);
+ }
return full_count;
}
@@ -313,7 +335,7 @@ prof_cpu_mask_read_proc(char *page, char **start, off_t off,
unsigned long *mask = (unsigned long *) data;
if (count < HEX_DIGITS+1)
return -EINVAL;
- return sprintf (page, "%08lx\n", *mask);
+ return sprintf (page, "%016lx\n", *mask);
}
static int
@@ -330,6 +352,7 @@ prof_cpu_mask_write_proc(struct file *file, const char *buffer,
*mask = new_value;
return full_count;
}
+#endif /* CONFIG_SMP */
#define MAX_NAMELEN 10
@@ -348,6 +371,7 @@ register_irq_proc (unsigned int irq)
/* create /proc/irq/1234 */
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+#ifdef CONFIG_SMP
/* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
@@ -357,6 +381,7 @@ register_irq_proc (unsigned int irq)
entry->write_proc = irq_affinity_write_proc;
smp_affinity_entry[irq] = entry;
+#endif
}
unsigned long prof_cpu_mask = ~0UL;
@@ -370,6 +395,7 @@ init_irq_proc (void)
/* create /proc/irq */
root_irq_dir = proc_mkdir("irq", 0);
+#ifdef CONFIG_SMP
/* create /proc/irq/prof_cpu_mask */
entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
@@ -377,6 +403,7 @@ init_irq_proc (void)
entry->data = (void *)&prof_cpu_mask;
entry->read_proc = prof_cpu_mask_read_proc;
entry->write_proc = prof_cpu_mask_write_proc;
+#endif
/*
* Create entries for all existing IRQs.
@@ -426,6 +453,10 @@ request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
action->next = NULL;
action->dev_id = dev_id;
+#ifdef CONFIG_SMP
+ select_smp_affinity(irq);
+#endif
+
retval = setup_irq(irq, action);
if (retval)
kfree(action);
@@ -522,10 +553,10 @@ get_irq_list(char *buf)
*p++ = '\n';
}
#if CONFIG_SMP
- p += sprintf(p, "LOC: ");
+ p += sprintf(p, "IPI: ");
for (j = 0; j < smp_num_cpus; j++)
p += sprintf(p, "%10lu ",
- cpu_data[cpu_logical_map(j)].smp_local_irq_count);
+ cpu_data[cpu_logical_map(j)].ipi_count);
p += sprintf(p, "\n");
#endif
p += sprintf(p, "ERR: %10lu\n", irq_err_count);
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 62ba2362f..774fcf8a6 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -6,6 +6,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/irq.h>
+#include <linux/kernel_stat.h>
#include <asm/machvec.h>
#include <asm/dma.h>
@@ -61,14 +62,22 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
break;
case 1:
#ifdef CONFIG_SMP
- cpu_data[smp_processor_id()].smp_local_irq_count++;
+ {
+ long cpu;
smp_percpu_timer_interrupt(&regs);
- if (smp_processor_id() == boot_cpuid)
-#endif
+ cpu = smp_processor_id();
+ if (cpu != boot_cpuid) {
+ irq_attempt(cpu, RTC_IRQ)++;
+ kstat.irqs[cpu][RTC_IRQ]++;
+ } else {
handle_irq(RTC_IRQ, &regs);
+ }
+ }
+#else
+ handle_irq(RTC_IRQ, &regs);
+#endif
return;
case 2:
- irq_err_count++;
alpha_mv.machine_check(vector, la_ptr, &regs);
return;
case 3:
diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c
new file mode 100644
index 000000000..65414a7f5
--- /dev/null
+++ b/arch/alpha/kernel/irq_pyxis.c
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/alpha/kernel/irq_pyxis.c
+ *
+ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
+ *
+ * IRQ Code common to all PYXIS core logic chips.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq_impl.h"
+
+
+/* Note mask bit is true for ENABLED irqs. */
+static unsigned long cached_irq_mask;
+
+static inline void
+pyxis_update_irq_hw(unsigned long mask)
+{
+ *(vulp)PYXIS_INT_MASK = mask;
+ mb();
+ *(vulp)PYXIS_INT_MASK;
+}
+
+static inline void
+pyxis_enable_irq(unsigned int irq)
+{
+ pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
+}
+
+static void
+pyxis_disable_irq(unsigned int irq)
+{
+ pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
+}
+
+static unsigned int
+pyxis_startup_irq(unsigned int irq)
+{
+ pyxis_enable_irq(irq);
+ return 0;
+}
+
+static void
+pyxis_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ pyxis_enable_irq(irq);
+}
+
+static void
+pyxis_mask_and_ack_irq(unsigned int irq)
+{
+ unsigned long bit = 1UL << (irq - 16);
+ unsigned long mask = cached_irq_mask &= ~bit;
+
+ /* Disable the interrupt. */
+ *(vulp)PYXIS_INT_MASK = mask;
+ wmb();
+ /* Ack PYXIS PCI interrupt. */
+ *(vulp)PYXIS_INT_REQ = bit;
+ mb();
+ /* Re-read to force both writes. */
+ *(vulp)PYXIS_INT_MASK;
+}
+
+static struct hw_interrupt_type pyxis_irq_type = {
+ typename: "PYXIS",
+ startup: pyxis_startup_irq,
+ shutdown: pyxis_disable_irq,
+ enable: pyxis_enable_irq,
+ disable: pyxis_disable_irq,
+ ack: pyxis_mask_and_ack_irq,
+ end: pyxis_end_irq,
+};
+
+void
+pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+ pld &= cached_irq_mask;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7)
+ isa_device_interrupt(vector, regs);
+ else
+ handle_irq(16+i, regs);
+ }
+}
+
+void __init
+init_pyxis_irqs(unsigned long ignore_mask)
+{
+ long i;
+
+ *(vulp)PYXIS_INT_MASK = 0; /* disable all */
+ *(vulp)PYXIS_INT_REQ = -1; /* flush all */
+ mb();
+
+ /* Send -INTA pulses to clear any pending interrupts ...*/
+ *(vuip) CIA_IACK_SC;
+
+ for (i = 16; i < 48; ++i) {
+ if ((ignore_mask >> i) & 1)
+ continue;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i].handler = &pyxis_irq_type;
+ }
+
+ setup_irq(16+7, &isa_cascade_irqaction);
+}
diff --git a/arch/alpha/kernel/irq_srm.c b/arch/alpha/kernel/irq_srm.c
index 8b14a59fe..51806c996 100644
--- a/arch/alpha/kernel/irq_srm.c
+++ b/arch/alpha/kernel/irq_srm.c
@@ -6,9 +6,6 @@
#include <linux/sched.h>
#include <linux/irq.h>
-#include <asm/machvec.h>
-#include <asm/dma.h>
-
#include "proto.h"
#include "irq_impl.h"
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index cc55781cb..bc9c0d3de 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -77,27 +77,26 @@
mv_writew: CAT(low,_writew), \
mv_writel: CAT(low,_writel), \
mv_writeq: CAT(low,_writeq), \
- mv_ioremap: CAT(low,_ioremap), \
- mv_is_ioaddr: CAT(low,_is_ioaddr)
+ mv_ioremap: CAT(low,_ioremap) \
#define IO(UP,low) \
IO_LITE(UP,low), \
pci_ops: &CAT(low,_pci_ops)
-/* Any assembler that can generate a GENERIC kernel can generate BWX
- instructions. So always use them for PYXIS I/O. */
-
#define DO_APECS_IO IO(APECS,apecs)
#define DO_CIA_IO IO(CIA,cia)
#define DO_IRONGATE_IO IO(IRONGATE,irongate)
#define DO_LCA_IO IO(LCA,lca)
#define DO_MCPCIA_IO IO(MCPCIA,mcpcia)
#define DO_POLARIS_IO IO(POLARIS,polaris)
-#define DO_PYXIS_IO IO(PYXIS,pyxis)
#define DO_T2_IO IO(T2,t2)
#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami)
+#define DO_PYXIS_IO IO_LITE(CIA,cia_bwx), \
+ pci_ops: &CAT(cia,_pci_ops)
+
#define BUS(which) \
+ mv_is_ioaddr: CAT(which,_is_ioaddr), \
mv_pci_tbi: CAT(which,_pci_tbi)
#define DO_APECS_BUS BUS(apecs)
@@ -105,7 +104,6 @@
#define DO_IRONGATE_BUS BUS(irongate)
#define DO_LCA_BUS BUS(lca)
#define DO_MCPCIA_BUS BUS(mcpcia)
-#define DO_PYXIS_BUS BUS(pyxis)
#define DO_POLARIS_BUS BUS(polaris)
#define DO_T2_BUS BUS(t2)
#define DO_TSUNAMI_BUS BUS(tsunami)
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 091edaf37..0395f87f1 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -189,15 +189,6 @@ asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4,
return prio;
}
-
-/*
- * Heh. As documented by DEC..
- */
-asmlinkage unsigned long sys_madvise(void)
-{
- return 0;
-}
-
/*
* No need to acquire the kernel lock, we're local..
*/
@@ -1374,8 +1365,3 @@ asmlinkage int sys_old_adjtimex(struct timex32 *txc_p)
return ret;
}
-
-asmlinkage long osf_shmget (key_t key, int size, int flag)
-{
- return sys_shmget (key, size, flag);
-}
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index 3aee6ec34..f434b329d 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -138,6 +138,7 @@ struct pci_iommu_arena
dma_addr_t dma_base;
unsigned int size;
unsigned int next_entry;
+ unsigned int align_entry;
};
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 9e7e13e9b..5a36aa578 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -67,6 +67,10 @@ iommu_arena_new(struct pci_controler *hose, dma_addr_t base,
arena->size = window_size;
arena->next_entry = 0;
+ /* Align allocations to a multiple of a page size. Not needed
+ unless there are chip bugs. */
+ arena->align_entry = 1;
+
return arena;
}
@@ -74,28 +78,36 @@ long
iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
{
unsigned long flags;
- unsigned long *beg, *p, *end;
- long i;
+ unsigned long *ptes;
+ long i, p, nent, mask;
spin_lock_irqsave(&arena->lock, flags);
/* Search forward for the first sequence of N empty ptes. */
- beg = arena->ptes;
- end = beg + (arena->size >> PAGE_SHIFT);
- p = beg + arena->next_entry;
+ ptes = arena->ptes;
+ nent = arena->size >> PAGE_SHIFT;
+ mask = arena->align_entry - 1;
+ p = (arena->next_entry + mask) & ~mask;
i = 0;
- while (i < n && p < end)
- i = (*p++ == 0 ? i + 1 : 0);
+ while (i < n && p+i < nent) {
+ if (ptes[p+i])
+ p = (p + i + 1 + mask) & ~mask, i = 0;
+ else
+ i = i + 1;
+ }
if (i < n) {
/* Reached the end. Flush the TLB and restart the
search from the beginning. */
alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
- p = beg;
- i = 0;
- while (i < n && p < end)
- i = (*p++ == 0 ? i + 1 : 0);
+ p = 0, i = 0;
+ while (i < n && p+i < nent) {
+ if (ptes[p+i])
+ p = (p + i + 1 + mask) & ~mask, i = 0;
+ else
+ i = i + 1;
+ }
if (i < n) {
spin_unlock_irqrestore(&arena->lock, flags);
@@ -107,13 +119,13 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
bit zero is the valid bit, so write ~1 into everything.
The chip specific bits will fill this in with something
kosher when we return. */
- for (p = p - n, i = 0; i < n; ++i)
- p[i] = ~1UL;
+ for (i = 0; i < n; ++i)
+ ptes[p+i] = ~1UL;
- arena->next_entry = p - beg + n;
+ arena->next_entry = p + n;
spin_unlock_irqrestore(&arena->lock, flags);
- return p - beg;
+ return p;
}
static void
@@ -238,6 +250,12 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
iommu_arena_free(arena, dma_ofs, npages);
+ /* If we're freeing ptes above the `next_entry' pointer, they
+ may have snuck back into the TLB since the last wrap flush.
+ We need to flush the TLB before reallocating these. */
+ if (dma_ofs >= arena->next_entry)
+ alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
+
DBGA("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
dma_addr, size, npages, __builtin_return_address(0));
}
@@ -509,6 +527,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
struct pci_iommu_arena *arena;
struct scatterlist *end;
dma_addr_t max_dma;
+ dma_addr_t fbeg, fend;
if (direction == PCI_DMA_NONE)
BUG();
@@ -522,9 +541,11 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
if (!arena || arena->dma_base + arena->size > max_dma)
arena = hose->sg_isa;
+ fbeg = -1, fend = 0;
for (end = sg + nents; sg < end; ++sg) {
unsigned long addr, size;
long npages, ofs;
+ dma_addr_t tend;
addr = sg->dma_address;
size = sg->dma_length;
@@ -547,8 +568,18 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
npages = calc_npages((addr & ~PAGE_MASK) + size);
ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
iommu_arena_free(arena, ofs, npages);
+
+ tend = addr + size - 1;
+ if (fbeg > addr) fbeg = addr;
+ if (fend < tend) fend = tend;
}
+ /* If we're freeing ptes above the `next_entry' pointer, they
+ may have snuck back into the TLB since the last wrap flush.
+ We need to flush the TLB before reallocating these. */
+ if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
+ alpha_mv.mv_pci_tbi(hose, fbeg, fend);
+
DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg));
}
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 8e7bbcfaf..f13edeebf 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -20,7 +20,9 @@ extern void apecs_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
/* core_cia.c */
extern struct pci_ops cia_pci_ops;
+extern void cia_init_pci(void);
extern void cia_init_arch(void);
+extern void pyxis_init_arch(void);
extern void cia_machine_check(u64, u64, struct pt_regs *);
extern void cia_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
@@ -52,12 +54,6 @@ extern void polaris_init_arch(void);
extern void polaris_machine_check(u64, u64, struct pt_regs *);
#define polaris_pci_tbi ((void *)0)
-/* core_pyxis.c */
-extern struct pci_ops pyxis_pci_ops;
-extern void pyxis_init_arch(void);
-extern void pyxis_machine_check(u64, u64, struct pt_regs *);
-extern void pyxis_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
-
/* core_t2.c */
extern struct pci_ops t2_pci_ops;
extern void t2_init_arch(void);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 615914535..49ddca2e4 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -846,6 +846,22 @@ platform_string(void)
}
}
+static int
+get_nr_processors(struct percpu_struct *cpubase, unsigned long num)
+{
+ struct percpu_struct *cpu;
+ int i, count = 0;
+
+ for (i = 0; i < num; i++) {
+ cpu = (struct percpu_struct *)
+ ((char *)cpubase + i*hwrpb->processor_size);
+ if ((cpu->flags & 0x1cc) == 0x1cc)
+ count++;
+ }
+ return count;
+}
+
+
/*
* BUFFER is PAGE_SIZE bytes long.
*/
@@ -865,7 +881,7 @@ int get_cpuinfo(char *buffer)
char *cpu_name;
char *systype_name;
char *sysvariation_name;
- int len;
+ int len, nr_processors;
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
cpu_index = (unsigned) (cpu->type - 1);
@@ -876,6 +892,8 @@ int get_cpuinfo(char *buffer)
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&systype_name, &sysvariation_name);
+ nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
+
len = sprintf(buffer,
"cpu\t\t\t: Alpha\n"
"cpu model\t\t: %s\n"
@@ -894,7 +912,8 @@ int get_cpuinfo(char *buffer)
"BogoMIPS\t\t: %lu.%02lu\n"
"kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
"user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
- "platform string\t\t: %s\n",
+ "platform string\t\t: %s\n"
+ "cpus detected\t\t: %d\n",
cpu_name, cpu->variation, cpu->revision,
(char*)cpu->serial_no,
systype_name, sysvariation_name, hwrpb->sys_revision,
@@ -909,7 +928,7 @@ int get_cpuinfo(char *buffer)
loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
unaligned[0].count, unaligned[0].pc, unaligned[0].va,
unaligned[1].count, unaligned[1].pc, unaligned[1].va,
- platform_string());
+ platform_string(), nr_processors);
#ifdef __SMP__
len += smp_info(buffer+len);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index ab1fb9ab2..1ddaaf74d 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -1003,15 +1003,11 @@ flush_icache_page(struct vm_area_struct *vma, struct page *page)
int
smp_info(char *buffer)
{
- long i;
- unsigned long sum = 0;
- for (i = 0; i < NR_CPUS; i++)
- sum += cpu_data[i].ipi_count;
-
- return sprintf(buffer, "CPUs probed %d active %d map 0x%lx IPIs %ld\n",
- smp_num_probed, smp_num_cpus, cpu_present_mask, sum);
+ return sprintf(buffer,
+ "cpus active\t\t: %d\n"
+ "cpu active mask\t\t: %016lx\n",
+ smp_num_cpus, cpu_present_mask);
}
-
#if DEBUG_SPINLOCK
void
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index 867d762f8..656a0a8df 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -249,7 +249,7 @@ struct alpha_machine_vector alcor_mv __initmv = {
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
init_rtc: common_init_rtc,
- init_pci: common_init_pci,
+ init_pci: cia_init_pci,
kill_arch: alcor_kill_arch,
pci_map_irq: alcor_map_irq,
pci_swizzle: common_swizzle,
@@ -279,7 +279,7 @@ struct alpha_machine_vector xlt_mv __initmv = {
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
init_rtc: common_init_rtc,
- init_pci: common_init_pci,
+ init_pci: cia_init_pci,
kill_arch: alcor_kill_arch,
pci_map_irq: alcor_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index 8e016ada0..9b2b39d73 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1998, 1999, 2000 Richard Henderson
*
* Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
* PC164 and LX164.
@@ -28,7 +28,6 @@
#include <asm/core_apecs.h>
#include <asm/core_cia.h>
#include <asm/core_lca.h>
-#include <asm/core_pyxis.h>
#include "proto.h"
#include "irq_impl.h"
@@ -223,6 +222,12 @@ cabriolet_init_pci(void)
ns87312_enable_ide(0x398);
}
+static inline void __init
+cia_cab_init_pci(void)
+{
+ cia_init_pci();
+ ns87312_enable_ide(0x398);
+}
/*
* The PC164 and LX164 have 19 PCI interrupts, four from each of the four
@@ -286,7 +291,7 @@ alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
static inline void __init
alphapc164_init_pci(void)
{
- common_init_pci();
+ cia_init_pci();
SMC93x_Init();
}
@@ -339,7 +344,7 @@ struct alpha_machine_vector eb164_mv __initmv = {
init_arch: cia_init_arch,
init_irq: cabriolet_init_irq,
init_rtc: common_init_rtc,
- init_pci: cabriolet_init_pci,
+ init_pci: cia_cab_init_pci,
pci_map_irq: cabriolet_map_irq,
pci_swizzle: common_swizzle,
};
@@ -377,8 +382,8 @@ struct alpha_machine_vector lx164_mv __initmv = {
DO_EV5_MMU,
DO_DEFAULT_RTC,
DO_PYXIS_IO,
- DO_PYXIS_BUS,
- machine_check: pyxis_machine_check,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
min_io_address: DEFAULT_IO_BASE,
min_mem_address: DEFAULT_MEM_BASE,
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 63abc109f..c10018fff 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -36,32 +36,31 @@
/* Note mask bit is true for ENABLED irqs. */
static unsigned long cached_irq_mask;
/* dp264 boards handle at max four CPUs */
-static unsigned long cpu_irq_affinity[4];
+static unsigned long cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
spinlock_t dp264_irq_lock = SPIN_LOCK_UNLOCKED;
static void
-tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
+tsunami_update_irq_hw(unsigned long mask)
{
register tsunami_cchip *cchip = TSUNAMI_cchip;
+ unsigned long isa_enable = 1UL << 55;
register int bcpu = boot_cpuid;
#ifdef CONFIG_SMP
register unsigned long cpm = cpu_present_mask;
volatile unsigned long *dim0, *dim1, *dim2, *dim3;
- unsigned long mask0, mask1, mask2, mask3, maskB, dummy;
+ unsigned long mask0, mask1, mask2, mask3, dummy;
- mask0 = mask1 = mask2 = mask3 = mask;
- maskB = mask | isa_enable;
- if (bcpu == 0) mask0 = maskB;
- else if (bcpu == 1) mask1 = maskB;
- else if (bcpu == 2) mask2 = maskB;
- else if (bcpu == 3) mask3 = maskB;
+ mask0 = mask & cpu_irq_affinity[0];
+ mask1 = mask & cpu_irq_affinity[1];
+ mask2 = mask & cpu_irq_affinity[2];
+ mask3 = mask & cpu_irq_affinity[3];
- mask0 &= cpu_irq_affinity[0];
- mask1 &= cpu_irq_affinity[1];
- mask2 &= cpu_irq_affinity[2];
- mask3 &= cpu_irq_affinity[3];
+ if (bcpu == 0) mask0 |= isa_enable;
+ else if (bcpu == 1) mask1 |= isa_enable;
+ else if (bcpu == 2) mask2 |= isa_enable;
+ else mask3 |= isa_enable;
dim0 = &cchip->dim0.csr;
dim1 = &cchip->dim1.csr;
@@ -86,7 +85,7 @@ tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
if (bcpu == 0) dimB = &cchip->dim0.csr;
else if (bcpu == 1) dimB = &cchip->dim1.csr;
else if (bcpu == 2) dimB = &cchip->dim2.csr;
- else if (bcpu == 3) dimB = &cchip->dim3.csr;
+ else dimB = &cchip->dim3.csr;
*dimB = mask | isa_enable;
mb();
@@ -94,24 +93,12 @@ tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
#endif
}
-static inline void
-dp264_update_irq_hw(unsigned long mask)
-{
- tsunami_update_irq_hw(mask, (1UL << 55) | 0xffff);
-}
-
-static inline void
-clipper_update_irq_hw(unsigned long mask)
-{
- tsunami_update_irq_hw(mask, 1UL << 55);
-}
-
static void
dp264_enable_irq(unsigned int irq)
{
spin_lock(&dp264_irq_lock);
cached_irq_mask |= 1UL << irq;
- dp264_update_irq_hw(cached_irq_mask);
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -120,7 +107,7 @@ dp264_disable_irq(unsigned int irq)
{
spin_lock(&dp264_irq_lock);
cached_irq_mask &= ~(1UL << irq);
- dp264_update_irq_hw(cached_irq_mask);
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -142,8 +129,8 @@ static void
clipper_enable_irq(unsigned int irq)
{
spin_lock(&dp264_irq_lock);
- cached_irq_mask |= 1UL << irq;
- clipper_update_irq_hw(cached_irq_mask);
+ cached_irq_mask |= 1UL << (irq - 16);
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -151,8 +138,8 @@ static void
clipper_disable_irq(unsigned int irq)
{
spin_lock(&dp264_irq_lock);
- cached_irq_mask &= ~(1UL << irq);
- clipper_update_irq_hw(cached_irq_mask);
+ cached_irq_mask &= ~(1UL << (irq - 16));
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -191,7 +178,7 @@ dp264_set_affinity(unsigned int irq, unsigned long affinity)
{
spin_lock(&dp264_irq_lock);
cpu_set_irq_affinity(irq, affinity);
- dp264_update_irq_hw(cached_irq_mask);
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -199,8 +186,8 @@ static void
clipper_set_affinity(unsigned int irq, unsigned long affinity)
{
spin_lock(&dp264_irq_lock);
- cpu_set_irq_affinity(irq, affinity);
- clipper_update_irq_hw(cached_irq_mask);
+ cpu_set_irq_affinity(irq - 16, affinity);
+ tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -304,12 +291,10 @@ clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
}
static void __init
-init_tsunami_irqs(struct hw_interrupt_type * ops)
+init_tsunami_irqs(struct hw_interrupt_type * ops, int imin, int imax)
{
long i;
-
- /* Only irqs between 16 and 47 are tsunami irqs. */
- for (i = 16; i < 48; ++i) {
+ for (i = imin; i <= imax; ++i) {
irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = ops;
}
@@ -318,8 +303,6 @@ init_tsunami_irqs(struct hw_interrupt_type * ops)
static void __init
dp264_init_irq(void)
{
- int cpu;
-
outb(0, DMA1_RESET_REG);
outb(0, DMA2_RESET_REG);
outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
@@ -328,13 +311,10 @@ dp264_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = dp264_srm_device_interrupt;
- /* this is single threaded by design so no need of any smp lock */
- for (cpu = 0; cpu < 4; cpu++)
- cpu_irq_affinity[cpu] = ~0UL;
- dp264_update_irq_hw(0UL);
+ tsunami_update_irq_hw(0);
init_i8259a_irqs();
- init_tsunami_irqs(&dp264_irq_type);
+ init_tsunami_irqs(&dp264_irq_type, 16, 47);
}
static void __init
@@ -348,10 +328,10 @@ clipper_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = clipper_srm_device_interrupt;
- clipper_update_irq_hw(0UL);
+ tsunami_update_irq_hw(0);
init_i8259a_irqs();
- init_tsunami_irqs(&clipper_irq_type);
+ init_tsunami_irqs(&clipper_irq_type, 24, 63);
}
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index 9e4fbe569..4545ff0e2 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -34,10 +34,6 @@
#include "machvec_impl.h"
-/*
- * HACK ALERT! only the boot cpu is used for interrupts.
- */
-
/* Note that this interrupt code is identical to TAKARA. */
/* Note mask bit is true for DISABLED irqs. */
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index 0191ef91b..f54de2c87 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1998, 1999, 2000 Richard Henderson
*
* Code supporting the MIATA (EV56+PYXIS).
*/
@@ -22,7 +22,7 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/core_pyxis.h>
+#include <asm/core_cia.h>
#include "proto.h"
#include "irq_impl.h"
@@ -215,7 +215,7 @@ miata_swizzle(struct pci_dev *dev, u8 *pinp)
static void __init
miata_init_pci(void)
{
- common_init_pci();
+ cia_init_pci();
SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
es1888_init();
}
@@ -240,8 +240,8 @@ struct alpha_machine_vector miata_mv __initmv = {
DO_EV5_MMU,
DO_DEFAULT_RTC,
DO_PYXIS_IO,
- DO_PYXIS_BUS,
- machine_check: pyxis_machine_check,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
min_io_address: DEFAULT_IO_BASE,
min_mem_address: DEFAULT_MEM_BASE,
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index a66731154..f436b4902 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -258,7 +258,7 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
init_arch: cia_init_arch,
init_irq: mikasa_init_irq,
init_rtc: common_init_rtc,
- init_pci: common_init_pci,
+ init_pci: cia_init_pci,
pci_map_irq: mikasa_map_irq,
pci_swizzle: common_swizzle,
};
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index 523d29853..8ef79db13 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -309,7 +309,7 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
init_arch: cia_init_arch,
init_irq: noritake_init_irq,
init_rtc: common_init_rtc,
- init_pci: common_init_pci,
+ init_pci: cia_init_pci,
pci_map_irq: noritake_map_irq,
pci_swizzle: noritake_swizzle,
};
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 01d80ab97..23069e06d 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1998, 1999, 2000 Richard Henderson
*
* Code supporting the RUFFIAN.
*/
@@ -23,7 +23,7 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/core_pyxis.h>
+#include <asm/core_cia.h>
#include "proto.h"
#include "irq_impl.h"
@@ -149,8 +149,8 @@ struct alpha_machine_vector ruffian_mv __initmv = {
DO_EV5_MMU,
DO_DEFAULT_RTC,
DO_PYXIS_IO,
- DO_PYXIS_BUS,
- machine_check: pyxis_machine_check,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_RUFFIAN_MAX_DMA_ADDRESS,
min_io_address: DEFAULT_IO_BASE,
min_mem_address: DEFAULT_MEM_BASE,
@@ -161,7 +161,7 @@ struct alpha_machine_vector ruffian_mv __initmv = {
init_arch: pyxis_init_arch,
init_irq: ruffian_init_irq,
init_rtc: ruffian_init_rtc,
- init_pci: common_init_pci,
+ init_pci: cia_init_pci,
kill_arch: ruffian_kill_arch,
pci_map_irq: ruffian_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index bad57d35e..b98e46028 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998, 1999 Richard Henderson
+ * Copyright (C) 1998, 1999, 2000 Richard Henderson
*
* Code supporting the SX164 (PCA56+PYXIS).
*/
@@ -23,7 +23,7 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/core_pyxis.h>
+#include <asm/core_cia.h>
#include "proto.h"
#include "irq_impl.h"
@@ -107,10 +107,10 @@ sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
return COMMON_TABLE_LOOKUP;
}
-void __init
+static void __init
sx164_init_pci(void)
{
- common_init_pci();
+ cia_init_pci();
SMC669_Init(0);
}
@@ -124,8 +124,8 @@ struct alpha_machine_vector sx164_mv __initmv = {
DO_EV5_MMU,
DO_DEFAULT_RTC,
DO_PYXIS_IO,
- DO_PYXIS_BUS,
- machine_check: pyxis_machine_check,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
min_io_address: DEFAULT_IO_BASE,
min_mem_address: DEFAULT_MEM_BASE,
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index a0bc57125..9ebba3955 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -258,7 +258,7 @@ takara_init_pci(void)
if (alpha_using_srm)
alpha_mv.pci_map_irq = takara_map_irq_srm;
- common_init_pci();
+ cia_init_pci();
ns87312_enable_ide(0x26e);
}
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 291682e33..6119ea371 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -48,6 +48,7 @@ extern volatile unsigned long lost_ticks; /* kernel/sched.c */
static int set_rtc_mmss(unsigned long);
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
/*
* Shift amount by which scaled_ticks_per_cycle is scaled. Shifting
@@ -163,7 +164,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
}
void
-common_init_rtc()
+common_init_rtc(void)
{
unsigned char x;
@@ -406,6 +407,8 @@ set_rtc_mmss(unsigned long nowtime)
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
+ /* irq are locally disabled here */
+ spin_lock(&rtc_lock);
/* Tell the clock it's being set */
save_control = CMOS_READ(RTC_CONTROL);
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
@@ -455,6 +458,7 @@ set_rtc_mmss(unsigned long nowtime)
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
return retval;
}
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 828044b24..76504a1ef 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -215,10 +215,8 @@ do_entIF(unsigned long type, unsigned long a1,
/* EV4 does not implement anything except normal
rounding. Everything else will come here as
an illegal instruction. Emulate them. */
- if (alpha_fp_emul(regs.pc)) {
- regs.pc += 4;
+ if (alpha_fp_emul(regs.pc-4))
return;
- }
}
send_sig(SIGILL, current, 1);
break;
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ad8e9423a..ff732b8fa 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -14,7 +14,6 @@
OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
CPP := $(CC) -E
-PERL := perl
LINKFLAGS := -p -X -T arch/arm/vmlinux.lds
ARCHCC := $(word 1,$(CC))
@@ -101,6 +100,8 @@ endif
LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
+export LIBGCC
+
ifeq ($(CONFIG_ARCH_A5K),y)
MACHINE = a5k
ARCHDIR = arc
diff --git a/arch/arm/config.in b/arch/arm/config.in
index ff4f954df..2ff7f6414 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -35,9 +35,9 @@ fi
if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
bool ' Include support for EBSA285' CONFIG_ARCH_EBSA285
- bool ' Include support for CATS' CONFIG_CATS
+ bool ' Include support for CATS' CONFIG_ARCH_CATS
bool ' Include support for NetWinder' CONFIG_ARCH_NETWINDER
- bool ' Include support for Compaq Personal Server' CONFIG_PERSONAL_SERVER
+ bool ' Include support for Compaq Personal Server' CONFIG_ARCH_PERSONAL_SERVER
fi
if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then
@@ -124,7 +124,7 @@ fi
#
# These machines have ISA-DMA
#
-if [ "$CONFIG_CATS" = "y" -o \
+if [ "$CONFIG_ARCH_CATS" = "y" -o \
"$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_NETWINDER" = "y" ]; then
define_bool CONFIG_ISA_DMA y
@@ -171,8 +171,8 @@ source drivers/parport/Config.in
if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
"$CONFIG_ARCH_SA1100" = "y" -o \
"$CONFIG_ARCH_NETWINDER" = "y" -o \
- "$CONFIG_PERSONAL_SERVER" = "y" -o \
- "$CONFIG_CATS" = "y" ]; then
+ "$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \
+ "$CONFIG_ARCH_CATS" = "y" ]; then
string 'Initial kernel command string' CONFIG_CMDLINE
fi
if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
index 8645497ae..536e614ff 100644
--- a/arch/arm/kernel/arch.c
+++ b/arch/arm/kernel/arch.c
@@ -192,6 +192,7 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
* in head-armv.S.
*/
static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.info"))) = {
+#ifdef CONFIG_ARCH_EBSA110
{
MACH_TYPE_EBSA110,
"EBSA110", /* RMK */
@@ -199,119 +200,160 @@ static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.in
NO_VIDEO,
1, 0, 1, 1, 1,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_RPC
+ {
MACH_TYPE_RISCPC,
"Acorn-RiscPC", /* RMK */
0x10000100,
NO_VIDEO,
1, 1, 0, 0, 0,
fixup_acorn
- }, {
- 2,
- "unknown",
- NO_PARAMS,
- NO_VIDEO,
- 0, 0, 0, 0, 0,
- NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_NEXUSPCI
+ {
MACH_TYPE_NEXUSPCI,
"FTV/PCI", /* Philip Blundell */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_EBSA285
+ {
MACH_TYPE_EBSA285,
"EBSA285", /* RMK */
0x00000100,
0x000a0000, 0x000bffff,
0, 0, 0, 0, 0,
fixup_ebsa285
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_NETWINDER
+ {
MACH_TYPE_NETWINDER,
"Rebel-NetWinder", /* RMK */
0x00000100,
0x000a0000, 0x000bffff,
1, 0, 1, 0, 0,
fixup_netwinder
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_CATS
+ {
MACH_TYPE_CATS,
"Chalice-CATS", /* Philip Blundell */
NO_PARAMS,
0x000a0000, 0x000bffff,
0, 0, 0, 0, 1,
fixup_cats
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_TBOX
+ {
MACH_TYPE_TBOX,
"unknown-TBOX", /* Philip Blundell */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_CO285
+ {
MACH_TYPE_CO285,
"co-EBSA285", /* Mark van Doesburg */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
fixup_coebsa285
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_CLPS7110
+ {
MACH_TYPE_CLPS7110,
"CL-PS7110", /* Werner Almesberger */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_ARC
+ {
MACH_TYPE_ARCHIMEDES,
"Acorn-Archimedes",/* RMK/DAG */
0x0207c000,
NO_VIDEO,
0, 0, 0, 0, 0,
fixup_acorn
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_A5K
+ {
MACH_TYPE_A5K,
"Acorn-A5000", /* RMK/PB */
0x0207c000,
NO_VIDEO,
0, 0, 0, 0, 0,
fixup_acorn
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_ETOILE
+ {
MACH_TYPE_ETOILE,
"Etoile", /* Alex de Vries */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_LACIE_NAS
+ {
MACH_TYPE_LACIE_NAS,
"LaCie_NAS", /* Benjamin Herrenschmidt */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_CLPS7500
+ {
MACH_TYPE_CLPS7500,
"CL-PS7500", /* Philip Blundell */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_SHARK
+ {
MACH_TYPE_SHARK,
"Shark", /* Alexander Schulz */
NO_PARAMS,
0x06000000, 0x06000000+0x001fffff,
0, 0, 0, 0, 0,
NULL
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_SA1100
+ {
MACH_TYPE_SA1100,
"SA1100-based", /* Nicolas Pitre */
NO_PARAMS,
NO_VIDEO,
0, 0, 0, 0, 0,
fixup_sa1100
- }, {
+ },
+#endif
+#ifdef CONFIG_ARCH_PERSONAL_SERVER
+ {
MACH_TYPE_PERSONAL_SERVER,
"Compaq Personal Server",
NO_PARAMS,
@@ -319,4 +361,5 @@ static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.in
0, 0, 0, 0, 0,
NULL
}
+#endif
};
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 1b0a064d0..109e2f96d 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -164,7 +164,52 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
struct list_head *walk = &bus->devices;
+ struct arm_pci_sysdata *sysdata =
+ (struct arm_pci_sysdata *)bus->sysdata;
+ struct arm_bus_sysdata *busdata;
+ if (bus->number < MAX_NR_BUS)
+ busdata = sysdata->bus + bus->number;
+ else
+ BUG();
+
+ /*
+ * Walk the devices on this bus, working out what we can
+ * and can't support.
+ */
+ for (walk = walk->next; walk != &bus->devices; walk = walk->next) {
+ struct pci_dev *dev = pci_dev_b(walk);
+ u16 status;
+
+ pci_read_config_word(dev, PCI_STATUS, &status);
+
+ /*
+ * If this device does not support fast back to back
+ * transfers, the bus as a whole cannot support them.
+ */
+ if (!(status & PCI_STATUS_FAST_BACK))
+ busdata->features &= ~PCI_COMMAND_FAST_BACK;
+
+ /*
+ * Calculate the maximum devsel latency.
+ */
+ if (busdata->maxdevsel < (status & PCI_STATUS_DEVSEL_MASK))
+ busdata->maxdevsel = (status & PCI_STATUS_DEVSEL_MASK);
+
+ /*
+ * If this device is an ISA bridge, set the have_isa_bridge
+ * flag. We will then go looking for things like keyboard,
+ * etc
+ */
+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
+ dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
+ have_isa_bridge = !0;
+ }
+
+ /*
+ * Now walk the devices again, this time setting them up.
+ */
+ walk = &bus->devices;
for (walk = walk->next; walk != &bus->devices; walk = walk->next) {
struct pci_dev *dev = pci_dev_b(walk);
u16 cmd;
@@ -182,25 +227,15 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
pci_write_config_dword(dev, 0x40, 0x80000000);
/*
- * If this device is an ISA bridge, set the have_isa_bridge
- * flag. We will then go looking for things like keyboard,
- * etc
- */
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
- dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
- have_isa_bridge = !0;
-
- /*
* Set latency timer to 32, and a cache line size to 32 bytes.
- * Also, set system error enable, parity error enable, and
- * fast back to back transaction enable. Disable ROM.
+ * Also, set system error enable, parity error enable.
+ * Disable ROM.
*/
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR |
- PCI_COMMAND_PARITY;
+ cmd |= busdata->features;
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -254,7 +289,7 @@ static struct hw_pci ebsa285_pci __initdata = {
};
#endif
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ARCH_CATS
/* cats host-specific stuff */
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
@@ -323,7 +358,7 @@ static struct hw_pci netwinder_pci __initdata = {
};
#endif
-#ifdef CONFIG_PERSONAL_SERVER
+#ifdef CONFIG_ARCH_PERSONAL_SERVER
static int irqmap_personal_server[] __initdata = {
IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
@@ -399,7 +434,7 @@ void __init pcibios_init(void)
break;
}
#endif
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ARCH_CATS
if (machine_is_cats()) {
hw_pci = &cats_pci;
break;
@@ -411,7 +446,7 @@ void __init pcibios_init(void)
break;
}
#endif
-#ifdef CONFIG_PERSONAL_SERVER
+#ifdef CONFIG_ARCH_PERSONAL_SERVER
if (machine_is_personal_server()) {
hw_pci = &personal_server_pci;
break;
diff --git a/arch/arm/kernel/bios32.h b/arch/arm/kernel/bios32.h
index 9a4380732..525af165b 100644
--- a/arch/arm/kernel/bios32.h
+++ b/arch/arm/kernel/bios32.h
@@ -1,9 +1,27 @@
+#define MAX_NR_BUS 2
+
+struct arm_bus_sysdata {
+ /*
+ * bitmask of features we can turn.
+ * See PCI command register for more info.
+ */
+ u16 features;
+ /*
+ * Maximum devsel for this bus.
+ */
+ u16 maxdevsel;
+};
+
+struct arm_pci_sysdata {
+ struct arm_bus_sysdata bus[MAX_NR_BUS];
+};
+
struct hw_pci {
- void (*init)(void);
+ void (*init)(void);
unsigned long io_start;
unsigned long mem_start;
- u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
- int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+ u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
+ int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
};
void __init dc21285_init(void);
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index 6158e995a..64c5861f0 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -206,8 +206,11 @@ static struct irqaction dc21285_error_action = {
void __init dc21285_init(void)
{
static struct resource csrmem, csrio;
- unsigned int mem_size;
+ struct arm_pci_sysdata sysdata;
unsigned long cntl;
+ unsigned int mem_size, pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+ int i;
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
*CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
@@ -240,25 +243,34 @@ void __init dc21285_init(void)
*CSR_PCICSRIOBASE = csrio.start;
*CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET);
*CSR_PCIROMBASE = 0;
- *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
- PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ *CSR_PCICMD = pci_cmd |
(1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
#endif
printk(KERN_DEBUG "PCI: DC21285 footbridge, revision %02lX\n",
*CSR_CLASSREV & 0xff);
- pci_scan_bus(0, &dc21285_ops, NULL);
+ for (i = 0; i < MAX_NR_BUS; i++) {
+ sysdata.bus[i].features = PCI_COMMAND_FAST_BACK |
+ PCI_COMMAND_SERR |
+ PCI_COMMAND_PARITY;
+ sysdata.bus[i].maxdevsel = PCI_STATUS_DEVSEL_FAST;
+ }
+
+ pci_scan_bus(0, &dc21285_ops, &sysdata);
+
+ pci_cmd |= sysdata.bus[0].features;
+
+ printk("Fast back to back PCI transfers %sabled\n",
+ (sysdata.bus[0].features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
/*
* Clear any existing errors - we aren't
* interested in historical data...
*/
- cntl = *CSR_SA110_CNTL & 0xffffde07;
- *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
- cntl = *CSR_PCICMD & 0x0000ffff;
- *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
+ cntl = *CSR_SA110_CNTL & 0xffffde07;
+ *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
+ *CSR_PCICMD = pci_cmd | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
/*
* Initialise PCI error IRQ after we've finished probing
diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c
index 8dcad0b93..f47e169c5 100644
--- a/arch/arm/kernel/hw-footbridge.c
+++ b/arch/arm/kernel/hw-footbridge.c
@@ -613,7 +613,7 @@ EXPORT_SYMBOL(cpld_modify);
/*
* CATS stuff
*/
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ARCH_CATS
#define CONFIG_PORT 0x370
#define INDEX_PORT (CONFIG_PORT)
@@ -698,7 +698,7 @@ void __init hw_init(void)
#endif
}
#endif
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ARCH_CATS
if (machine_is_cats())
cats_hw_init();
#endif
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 46afd5938..6ea7916ef 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/kernel/process.c
*
- * Copyright (C) 1996-1999 Russell King - Converted to ARM.
+ * Copyright (C) 1996-2000 Russell King - Converted to ARM.
* Origional Copyright (C) 1995 Linus Torvalds
*/
@@ -32,6 +32,7 @@
#include <asm/io.h>
extern char *processor_modes[];
+extern void setup_mm_for_reboot(char mode);
asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
@@ -96,15 +97,28 @@ __setup("reboot=", reboot_setup);
void machine_restart(char * __unused)
{
/*
- * Turn off caches, interrupts, etc
+ * Clean and disable cache, and turn off interrupts
*/
cpu_proc_fin();
+ /*
+ * Tell the mm system that we are going to reboot -
+ * we may need it to insert some 1:1 mappings so that
+ * soft boot works.
+ */
+ setup_mm_for_reboot(reboot_mode);
+
+ /*
+ * Now call the architecture specific reboot code.
+ */
arch_reset(reboot_mode);
+ /*
+ * Whoops - the architecture was unable to reboot.
+ * Tell the user!
+ */
mdelay(1000);
printk("Reboot failed -- System halted\n");
- cli();
while (1);
}
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 4a23d14bd..13336c008 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -379,7 +379,8 @@ static const struct fsr_info {
*/
#define BUG_PROC_MSG \
KERN_DEBUG "Weird data abort (%08X).\n" \
- KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for more information"
+ KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for " \
+ "more information\n"
asmlinkage void
do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mm/mm-armo.c
index a5d4cdfe8..f4bf7cad5 100644
--- a/arch/arm/mm/mm-armo.c
+++ b/arch/arm/mm/mm-armo.c
@@ -3,7 +3,7 @@
*
* Page table sludge for older ARM processor architectures.
*
- * Copyright (C) 1998-1999 Russell King
+ * Copyright (C) 1998-2000 Russell King
*/
#include <linux/sched.h>
#include <linux/mm.h>
@@ -135,6 +135,13 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
}
/*
+ * No special code is required here.
+ */
+void setup_mm_for_reboot(char mode)
+{
+}
+
+/*
* This contains the code to setup the memory map on an ARM2/ARM250/ARM3
* machine. This is both processor & architecture specific, and requires
* some more work to get it to fit into our separate processor and
@@ -155,6 +162,9 @@ void __init pagetable_init(void)
pgd_val(swapper_pg_dir[i]) = 0;
}
+/*
+ * We never have holes in the memmap
+ */
void __init create_memmap_holes(void)
{
}
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index ddc69089a..cb29618a3 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -3,7 +3,7 @@
*
* Page table sludge for ARM v3 and v4 processor architectures.
*
- * Copyright (C) 1998-1999 Russell King
+ * Copyright (C) 1998-2000 Russell King
*/
#include <linux/sched.h>
#include <linux/mm.h>
@@ -286,6 +286,25 @@ static void __init create_mapping(struct map_desc *md)
}
}
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages. This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+ pgd_t *pgd = current->mm->pgd;
+ pmd_t pmd;
+ int i;
+
+ for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
+ pmd_val(pmd) = (i << PGDIR_SHIFT) |
+ PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
+ PMD_TYPE_SECT;
+ set_pmd(pmd_offset(pgd + i, i << PGDIR_SHIFT), pmd);
+ }
+}
+
void __init pagetable_init(void)
{
struct map_desc *init_maps, *p, *q;
diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
index 9814d2a9c..dd039f208 100644
--- a/arch/arm/mm/proc-arm6,7.S
+++ b/arch/arm/mm/proc-arm6,7.S
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/mm/proc-arm6,7.S: MMU functions for ARM6
*
- * (C) 1997-1999 Russell King
+ * (C) 1997-2000 Russell King
*
* These are the low level assembler for performing cache and TLB
* functions on the ARM6 & ARM7.
@@ -342,15 +342,17 @@ ENTRY(cpu_arm7_set_pte)
/*
* Function: _arm6_7_reset
- *
+ * Params : r0 = address to jump to
* Notes : This sets up everything for a reset
*/
ENTRY(cpu_arm6_reset)
ENTRY(cpu_arm7_reset)
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 0 @ flush cache
- mcr p15, 0, r0, c5, c0, 0 @ flush TLB
- mov pc, lr
+ mov r1, #0
+ mcr p15, 0, r1, c7, c0, 0 @ flush cache
+ mcr p15, 0, r1, c5, c0, 0 @ flush TLB
+ mov r1, #0x30
+ mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc
+ mov pc, r0
cpu_armvlsi_name:
.asciz "ARM/VLSI"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 933408451..9800643d9 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110
*
- * (C) 1997-1999 Russell King
+ * (C) 1997-2000 Russell King
*
* These are the low level assembler for performing cache and TLB
* functions on the StrongARM-110 and StrongARM-1100
@@ -225,9 +225,9 @@ ENTRY(cpu_sa1100_flush_ram_page)
.align 5
ENTRY(cpu_sa110_flush_tlb_all)
ENTRY(cpu_sa1100_flush_tlb_all)
- mov r0, #0
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs
+ mov ip, #0
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, ip, c8, c7, 0 @ flush I & D tlbs
mov pc, lr
/*
@@ -421,16 +421,18 @@ ENTRY(cpu_sa1100_proc_init)
ENTRY(cpu_sa110_proc_fin)
ENTRY(cpu_sa1100_proc_fin)
+ stmfd sp!, {r1, lr}
mrs r0, cpsr
orr r0, r0, #F_BIT | I_BIT
msr cpsr, r0
+ bl cpu_sa110_flush_cache_all @ clean caches
mov r0, #0
mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x1100 @ ...i...s........
+ bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ldmfd sp!, {r1, pc}
.align 5
ENTRY(cpu_sa110_do_idle)
@@ -448,18 +450,21 @@ ENTRY(cpu_sa1100_do_idle)
/*
* Function: sa110_reset
+ * Params : r0 = address to jump to
* Notes : This sets up everything for a reset
*/
+ .align 5
ENTRY(cpu_sa110_reset)
ENTRY(cpu_sa1100_reset)
- stmfd sp!, {r1, lr}
- bl cpu_sa110_flush_cache_all
- bl cpu_sa110_flush_tlb_all
+ mov ip, #0
mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches
- mrc p15, 0, r0, c1, c0, 0 @ ctrl register
- bic r0, r0, #0x000f @ ............wcam
- bic r0, r0, #0x1100 @ ...i...s........
- ldmfd sp!, {r1, pc}
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, ip, c8, c7, 0 @ flush I & D tlbs
+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
+ bic ip, ip, #0x000f @ ............wcam
+ bic ip, ip, #0x1100 @ ...i...s........
+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
+ mov pc, r0
/*
* Purpose : Function pointers used to access above functions - all calls
* come through these
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 2a84bf05f..0e16a45b6 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -30,7 +30,8 @@ CFLAGS += $(shell if ! $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/nul
CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mpreferred-stack-boundary=2"; fi)
ifdef CONFIG_M386
-CFLAGS := $(CFLAGS) -m386 -DCPU=386
+CFLAGS := $(CFLAGS) -DCPU=386
+CFLAGS += $(shell if $(CC) -march=i386 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i386"; else echo "-m386"; fi)
AFLAGS := $(AFLAGS) -DCPU=386
endif
@@ -65,7 +66,7 @@ AFLAGS := $(AFLAGS) -DCPU=586
endif
ifdef CONFIG_MK7
-CFLAGS := $(CFLAGS) -DCPU=686 -march=pentiumpro -mpentiumpro -malign-functions=4 -fschedule-insns2 -mwide-multiply -fexpensive-optimizations
+CFLAGS := $(CFLAGS) -malign-functions=4 -fschedule-insns2 -mwide-multiply -fexpensive-optimizations -DCPU=686
CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi)
AFLAGS := $(AFLAGS) -DCPU=686
endif
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index 51e0fc893..102850b74 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -33,10 +33,10 @@ startup_32:
cld
cli
movl $(__KERNEL_DS),%eax
- movl %ax,%ds
- movl %ax,%es
- movl %ax,%fs
- movl %ax,%gs
+ movl %eax,%ds
+ movl %eax,%es
+ movl %eax,%fs
+ movl %eax,%gs
lss SYMBOL_NAME(stack_start),%esp
xorl %eax,%eax
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 0f3f5cb8a..33f2d3cb1 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -179,7 +179,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -208,6 +207,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
CONFIG_BLK_DEV_IDE_MODES=y
#
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index 8efa2832a..f9410f3fd 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -488,13 +488,13 @@ static int __init acpi_find_tables(void)
if (!rsdt) {
printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n",
(void*) rsdp->rsdt);
- return -ENODEV;
+ return -EINVAL;
}
else if (rsdt->signature != ACPI_RSDT_SIG) {
printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n",
(void*) rsdp->rsdt, (unsigned) rsdt->signature);
acpi_unmap_table(rsdt);
- return -ENODEV;
+ return -EINVAL;
}
// search RSDT for FACP
acpi_facp.table = NULL;
@@ -532,7 +532,7 @@ static int __init acpi_find_tables(void)
if (!acpi_facp.table) {
printk(KERN_ERR "ACPI: missing FACP\n");
- return -ENODEV;
+ return -EINVAL;
}
return 0;
}
@@ -1461,8 +1461,19 @@ static int __init acpi_init(void)
switch (acpi_enabled) {
case ACPI_ENABLED:
- if (acpi_find_tables() && acpi_find_chipset())
+ switch (acpi_find_tables()) {
+ case 0:
+ // found valid ACPI tables
+ break;
+ case -ENODEV:
+ // found no ACPI tables, try chipset-specific
+ if (acpi_find_chipset())
+ return -ENODEV;
+ break;
+ default:
+ // found broken ACPI tables
return -ENODEV;
+ }
break;
case ACPI_TABLES_ONLY:
if (acpi_find_tables())
@@ -1478,6 +1489,12 @@ static int __init acpi_init(void)
facp = (struct acpi_facp*) acpi_facp.table;
+ if (PM_IS_ACTIVE()) {
+ printk(KERN_NOTICE "acpi: APM is already active.\n");
+ goto err_out;
+ }
+ pm_active = 1;
+
/*
* Internally we always keep latencies in timer
* ticks, which is simpler and more consistent (what is
@@ -1516,8 +1533,6 @@ static int __init acpi_init(void)
pm_power_off = acpi_power_off;
- pm_active = 1;
-
/*
* Set up the ACPI idle function. Note that we can't really
* do this with multiple CPU's, we'd need a per-CPU ACPI
@@ -1549,7 +1564,6 @@ static void __exit acpi_exit(void)
struct acpi_facp *facp = (struct acpi_facp*) acpi_facp.table;
pm_idle = NULL;
- pm_active = 0;
pm_power_off = NULL;
unregister_sysctl_table(acpi_sysctl);
@@ -1563,6 +1577,8 @@ static void __exit acpi_exit(void)
if (pci_driver_registered)
pci_unregister_driver(&acpi_driver);
+
+ pm_active = 0;
}
/*
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 3340946be..7a8a17b63 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -58,10 +58,19 @@ startup_32:
* New page tables may be in 4Mbyte page mode and may
* be using the global pages.
*
+ * NOTE! If we are on a 486 we may have no cr4 at all!
+ * So we do not try to touch it unless we really have
+ * some bits in it to set. This won't work if the BSP
+ * implements cr4 but this AP does not -- very unlikely
+ * but be warned! The same applies to the pse feature
+ * if not equally supported. --macro
+ *
* NOTE! We have to correct for the fact that we're
* not yet offset PAGE_OFFSET..
*/
#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+ cmpl $0,cr4_bits
+ je 1f
movl %cr4,%eax # Turn on 4Mb pages
orl cr4_bits,%eax
movl %eax,%cr4
@@ -219,7 +228,6 @@ is386: pushl %ecx # restore original EFLAGS
orl $2,%eax # set MP
2: movl %eax,%cr0
call check_x87
-4:
#ifdef __SMP__
incb ready
#endif
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index e21c33b6f..5327f24a4 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -25,6 +25,7 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
+extern spinlock_t rtc_lock;
#ifdef CONFIG_SMP
extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
@@ -131,3 +132,5 @@ EXPORT_SYMBOL(screen_info);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(irq_stat);
+
+EXPORT_SYMBOL(rtc_lock);
diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c
index 6dd0a4306..942de9c79 100644
--- a/arch/i386/kernel/pci-i386.c
+++ b/arch/i386/kernel/pci-i386.c
@@ -323,3 +323,17 @@ int pcibios_enable_resources(struct pci_dev *dev)
}
return 0;
}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+ */
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16) {
+ printk("PCI: Increasing latency timer of device %s to 64\n", dev->slot_name);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ }
+}
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index e51e96e43..b588642cc 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -1103,9 +1103,9 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
{
struct irq_info *q;
struct pci_dev *router;
- int i, pirq, newirq;
+ int i, pirq, newirq, reg;
u32 rtrid, mask;
- u8 x;
+ u8 x, y;
char *msg = NULL;
pin--;
@@ -1169,14 +1169,44 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
DBG(" -> [PIIX] set to %02x\n", newirq);
pci_write_config_byte(router, pirq, newirq);
msg = "PIIX-NEW";
- } else
- DBG(" -> [PIIX] sink\n");
+ } else DBG(" -> [PIIX] sink\n");
break;
case ID(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533):
newirq = ali_set_irq(router, pirq-1, newirq);
if (newirq)
msg = "ALI";
break;
+ case ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596):
+ case ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686):
+ reg = 0x55 + (pirq >> 1);
+ pci_read_config_byte(router, reg, &x);
+ y = (pirq & 1) ? (x >> 4) : (x & 0x0f);
+ if (y) {
+ DBG(" -> [VIA] %02x\n", y);
+ newirq = y;
+ msg = "VIA";
+ } else if (newirq) {
+ DBG(" -> [VIA] set to %02x\n", newirq);
+ x = (pirq & 1) ? ((x & 0x0f) | (newirq << 4)) : ((x & 0xf0) | newirq);
+ pci_write_config_byte(router, reg, y);
+ msg = "VIA-NEW";
+ } else DBG(" -> [VIA] sink\n");
+ break;
+ case ID(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700):
+ reg = 0xb8 + (pirq >> 5);
+ pci_read_config_byte(router, reg, &x);
+ y = (pirq & 0x10) ? (x >> 4) : (x & 0x0f);
+ if (y) {
+ DBG(" -> [OPTI] %02x\n", y);
+ newirq = y;
+ msg = "OPTI";
+ } else if (newirq) {
+ DBG(" -> [OPTI] set to %02x\n", newirq);
+ x = (pirq & 0x10) ? ((x & 0x0f) | (newirq << 4)) : ((x & 0xf0) | newirq);
+ pci_write_config_byte(router, reg, y);
+ msg = "OPTI-NEW";
+ } else DBG(" -> [OPTI] sink\n");
+ break;
default:
DBG(" -> unknown router %04x/%04x\n", rt->rtr_vendor, rt->rtr_device);
if (newirq && mask == (1 << newirq)) {
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index a12b6b73d..46292496d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -793,7 +793,7 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
unsigned int n, dummy, *v, ecx, edx;
/* Actually we must have cpuid or we could never have
- * figured out that this was AMD from the vendor info :-).
+ * figured out that this was AMD/Cyrix from the vendor info :-).
*/
cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
@@ -806,23 +806,27 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
c->x86_model_id[48] = 0;
/* Set MTRR capability flag if appropriate */
- if(boot_cpu_data.x86 == 5) {
- if((boot_cpu_data.x86_model == 9) ||
- ((boot_cpu_data.x86_model == 8) &&
- (boot_cpu_data.x86_mask >= 8)))
- c->x86_capability |= X86_FEATURE_MTRR;
- }
-
- if (n >= 0x80000005){
- cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
- printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
- ecx>>24, edx>>24);
- c->x86_cache_size=(ecx>>24)+(edx>>24);
- }
- if (n >= 0x80000006){
- cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
- printk("CPU: L2 Cache: %dK\n", ecx>>16);
- c->x86_cache_size=(ecx>>16);
+
+ if(c->x86_vendor==X86_VENDOR_AMD)
+ {
+ if(boot_cpu_data.x86 == 5) {
+ if((boot_cpu_data.x86_model == 9) ||
+ ((boot_cpu_data.x86_model == 8) &&
+ (boot_cpu_data.x86_mask >= 8)))
+ c->x86_capability |= X86_FEATURE_MTRR;
+ }
+
+ if (n >= 0x80000005){
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
+ ecx>>24, edx>>24);
+ c->x86_cache_size=(ecx>>24)+(edx>>24);
+ }
+ if (n >= 0x80000006){
+ cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
+ printk("CPU: L2 Cache: %dK\n", ecx>>16);
+ c->x86_cache_size=(ecx>>16);
+ }
}
return 1;
}
@@ -1034,6 +1038,8 @@ static void __init cyrix_model(struct cpuinfo_x86 *c)
printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
isa_dma_bridge_buggy = 2;
#endif
+ c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
+
/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
get_model_name(c); /* get CPU marketing name */
@@ -1546,7 +1552,7 @@ void __init cpu_init (void)
cpus_initialized++;
printk("Initializing CPU#%d\n", nr);
- if (cpu_has_pse)
+ if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
__asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index b4a7753b8..bcec04401 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -79,6 +79,9 @@ static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
unsigned long fast_gettimeoffset_quotient=0;
extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
+
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static inline unsigned long do_fast_gettimeoffset(void)
{
@@ -113,6 +116,8 @@ static inline unsigned long do_fast_gettimeoffset(void)
#ifndef CONFIG_X86_TSC
+spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
+
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
@@ -157,6 +162,8 @@ static unsigned long do_slow_gettimeoffset(void)
*/
unsigned long jiffies_t;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
@@ -215,6 +222,7 @@ static unsigned long do_slow_gettimeoffset(void)
}
} else
jiffies_p = jiffies_t;
+ spin_unlock(&i8253_lock);
count_p = count;
@@ -238,7 +246,6 @@ static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
*/
void do_gettimeofday(struct timeval *tv)
{
- extern volatile unsigned long lost_ticks;
unsigned long flags;
unsigned long usec, sec;
@@ -272,6 +279,7 @@ void do_settimeofday(struct timeval *tv)
* would have done, and then undo it!
*/
tv->tv_usec -= do_gettimeoffset();
+ tv->tv_usec -= lost_ticks * (1000000 / HZ);
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
@@ -302,6 +310,8 @@ static int set_rtc_mmss(unsigned long nowtime)
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
@@ -347,6 +357,7 @@ static int set_rtc_mmss(unsigned long nowtime)
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
return retval;
}
@@ -448,10 +459,19 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
rdtscl(last_tsc_low);
+#if 0 /*
+ * SUBTLE: this is not necessary from here because it's implicit in the
+ * write xtime_lock.
+ */
+ spin_lock(&i8253_lock);
+#endif
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
+#if 0
+ spin_unlock(&i8253_lock);
+#endif
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
diff --git a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation
index 0eda6e9fc..7bef250f8 100644
--- a/arch/mips/defconfig-decstation
+++ b/arch/mips/defconfig-decstation
@@ -76,12 +76,8 @@ CONFIG_TC=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
#
# Additional Block Devices
@@ -90,10 +86,6 @@ CONFIG_TC=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
#
# Networking options
@@ -151,6 +143,13 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_PHONE_IXJ is not set
#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
# SCSI support
#
CONFIG_SCSI=y
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 35055ac68..47947bbf0 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -1,4 +1,4 @@
-/* $Id: irixelf.c,v 1.26 2000/03/07 15:45:28 ralf Exp $
+/* $Id: irixelf.c,v 1.27 2000/03/19 01:28:43 ralf Exp $
*
* irixelf.c: Code to load IRIX ELF executables which conform to
* the MIPS ABI.
@@ -43,7 +43,7 @@
#undef DEBUG_ELF
static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
-static int load_irix_library(int fd);
+static int load_irix_library(struct file *);
static int irix_core_dump(long signr, struct pt_regs * regs,
struct file *file);
extern int dump_fpu (elf_fpregset_t *);
@@ -829,7 +829,7 @@ out_free_ph:
/* This is really simpleminded and specialized - we are loading an
* a.out library that is given an ELF header.
*/
-static inline int do_load_irix_library(struct file *file)
+static int load_irix_library(struct file *file)
{
struct elfhdr elf_ex;
struct elf_phdr *elf_phdata = NULL;
@@ -843,8 +843,6 @@ static inline int do_load_irix_library(struct file *file)
int i,j, k;
len = 0;
- if (!file->f_op)
- return -EACCES;
dentry = file->f_dentry;
inode = dentry->d_inode;
elf_bss = 0;
@@ -897,16 +895,18 @@ static inline int do_load_irix_library(struct file *file)
while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
/* Now use mmap to map the library into memory. */
+ down(&current->mm->mmap_sem);
error = do_mmap(file,
elf_phdata->p_vaddr & 0xfffff000,
elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
elf_phdata->p_offset & 0xfffff000);
+ up(&current->mm->mmap_sem);
k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
- if(k > elf_bss) elf_bss = k;
-
+ if (k > elf_bss) elf_bss = k;
+
if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
kfree(elf_phdata);
return error;
@@ -921,19 +921,6 @@ static inline int do_load_irix_library(struct file *file)
kfree(elf_phdata);
return 0;
}
-
-static int load_irix_library(int fd)
-{
- int retval = -EACCES;
- struct file *file;
-
- file = fget(fd);
- if (file) {
- retval = do_load_irix_library(file);
- fput(file);
- }
- return retval;
-}
/* Called through irix_syssgi() to map an elf image given an FD,
* a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many
diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22
index a5de95ca5..414d98df6 100644
--- a/arch/mips64/defconfig-ip22
+++ b/arch/mips64/defconfig-ip22
@@ -53,12 +53,8 @@ CONFIG_BINFMT_ELF=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
#
# Additional Block Devices
@@ -67,10 +63,6 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
#
# Networking options
@@ -102,6 +94,7 @@ CONFIG_SKB_LARGE=y
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
#
# Telephony Support
@@ -110,6 +103,13 @@ CONFIG_SKB_LARGE=y
# CONFIG_PHONE_IXJ is not set
#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
# SCSI support
#
# CONFIG_SCSI is not set
@@ -225,7 +225,6 @@ CONFIG_VT_CONSOLE=y
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_EFI_RTC is not set
#
# Video For Linux
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 73a6c2bf7..30595e694 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -756,7 +756,7 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->word92 = __le16_to_cpu(id->word92);
id->hw_config = __le16_to_cpu(id->hw_config);
- for (i=0; i<34; i++)
+ for (i=0; i<32; i++)
id->words94_125[i] = __le16_to_cpu(id->words94_125[i]);
id->last_lun = __le16_to_cpu(id->last_lun);
id->word127 = __le16_to_cpu(id->word127);
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index dec2105d8..6725e8cfe 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -49,6 +49,8 @@ SUBDIRS += arch/sparc/boot
CORE_FILES_NO_BTFIX := $(CORE_FILES)
CORE_FILES += arch/sparc/boot/btfix.o
+export CORE_FILES_NO_BTFIX
+
archclean:
rm -f $(TOPDIR)/vmlinux.aout
-$(MAKE) -C arch/sparc/boot clean
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index adb0ebe4c..e67a43022 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.88 2000/03/13 03:40:27 davem Exp $
+# $Id: config.in,v 1.90 2000/03/17 05:18:02 anton Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -19,18 +19,6 @@ define_bool CONFIG_VT_CONSOLE y
bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP
-bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
-if [ "$CONFIG_SUN4" != "y" ]; then
- bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
- source drivers/pci/Config.in
-fi
-
-mainmenu_option next_comment
-comment 'Console drivers'
-bool 'PROM console' CONFIG_PROM_CONSOLE
-source drivers/video/Config.in
-endmenu
-
# Global things across all Sun machines.
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
@@ -43,9 +31,11 @@ define_bool CONFIG_SUN_KEYBOARD y
define_bool CONFIG_SUN_CONSOLE y
define_bool CONFIG_SUN_AUXIO y
define_bool CONFIG_SUN_IO y
+
+bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
if [ "$CONFIG_SUN4" != "y" ]; then
- source drivers/sbus/char/Config.in
- source drivers/sbus/audio/Config.in
+ bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+ source drivers/pci/Config.in
fi
tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS
@@ -74,15 +64,27 @@ fi
endmenu
mainmenu_option next_comment
-comment 'Floppy and other block devices'
+comment 'Console drivers'
+bool 'PROM console' CONFIG_PROM_CONSOLE
+source drivers/video/Config.in
+endmenu
+
+if [ "$CONFIG_SUN4" != "y" ]; then
+ source drivers/sbus/char/Config.in
+ source drivers/sbus/audio/Config.in
+fi
+
+mainmenu_option next_comment
+comment 'Block devices'
bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
+
bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
tristate ' Linear (append) mode' CONFIG_MD_LINEAR
tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED
- tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
- tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
+# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
+# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
fi
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
@@ -99,16 +101,6 @@ if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
-mainmenu_option next_comment
-comment 'ISDN subsystem'
-
-tristate 'ISDN support' CONFIG_ISDN
-if [ "$CONFIG_ISDN" != "n" ]; then
- source drivers/isdn/Config.in
-fi
-endmenu
-
-
define_bool CONFIG_IDE n
define_bool CONFIG_BLK_DEV_IDE_MODES n
define_bool CONFIG_BLK_DEV_HD n
@@ -127,6 +119,15 @@ define_bool CONFIG_BLK_DEV_HD n
# endmenu
mainmenu_option next_comment
+comment 'ISDN subsystem'
+
+tristate 'ISDN support' CONFIG_ISDN
+if [ "$CONFIG_ISDN" != "n" ]; then
+ source drivers/isdn/Config.in
+fi
+endmenu
+
+mainmenu_option next_comment
comment 'SCSI support'
tristate 'SCSI support' CONFIG_SCSI
@@ -196,12 +197,16 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
tristate ' Sun LANCE support' CONFIG_SUNLANCE
tristate ' Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
- tristate ' Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate ' Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
+ fi
tristate ' Sun QuadEthernet support' CONFIG_SUNQE
tristate ' MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
+
# bool ' FDDI driver support' CONFIG_FDDI
# if [ "$CONFIG_FDDI" = "y" ]; then
# fi
+
if [ "$CONFIG_ATM" = "y" ]; then
source drivers/atm/Config.in
fi
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index de483af6e..b39da1989 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -14,8 +14,42 @@ CONFIG_EXPERIMENTAL=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SMP is not set
+CONFIG_SBUS=y
+CONFIG_SBUSCHAR=y
+CONFIG_BUSMOUSE=y
+CONFIG_SUN_MOUSE=y
+CONFIG_SERIAL=y
+CONFIG_SUN_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SUN_KEYBOARD=y
+CONFIG_SUN_CONSOLE=y
+CONFIG_SUN_AUXIO=y
+CONFIG_SUN_IO=y
# CONFIG_SUN4 is not set
# CONFIG_PCI is not set
+CONFIG_SUN_OPENPROMFS=m
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_SUNOS_EMUL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PRINTER is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
#
# Console drivers
@@ -42,17 +76,6 @@ CONFIG_FBCON_CFB8=y
CONFIG_FBCON_FONTWIDTH8_ONLY=y
CONFIG_FONT_SUN8x16=y
# CONFIG_FBCON_FONTS is not set
-CONFIG_SBUS=y
-CONFIG_SBUSCHAR=y
-CONFIG_BUSMOUSE=y
-CONFIG_SUN_MOUSE=y
-CONFIG_SERIAL=y
-CONFIG_SUN_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SUN_KEYBOARD=y
-CONFIG_SUN_CONSOLE=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
#
# Misc Linux/SPARC drivers
@@ -73,39 +96,14 @@ CONFIG_SUN_AURORA=m
# CONFIG_SPARCAUDIO_CS4231 is not set
# CONFIG_SPARCAUDIO_DBRI is not set
# CONFIG_SPARCAUDIO_DUMMY is not set
-CONFIG_SUN_OPENPROMFS=m
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_SUNOS_EMUL=y
#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_PRINTER is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Floppy, IDE, and other block devices
+# Block devices
#
CONFIG_BLK_DEV_FD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=m
CONFIG_MD_STRIPED=m
-CONFIG_MD_MIRRORING=m
-CONFIG_MD_RAID5=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_BLK_DEV_LOOP=m
@@ -162,6 +160,9 @@ CONFIG_DECNET_SIOCGIFCONF=y
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
#
# ISDN subsystem
@@ -169,11 +170,6 @@ CONFIG_DECNET_SIOCGIFCONF=y
# CONFIG_ISDN is not set
#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
# SCSI support
#
CONFIG_SCSI=y
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index e9b506e10..b1ed3c2af 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.35 2000/02/27 08:16:25 davem Exp $
+/* $Id: ioport.c,v 1.36 2000/03/16 08:22:53 anton Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -745,6 +745,10 @@ void ioport_init(void)
halt();
};
+}
+
+void register_proc_sparc_ioport(void)
+{
#ifdef CONFIG_PROC_FS
create_proc_read_entry("io_map",0,0,_sparc_io_get_info,&sparc_iomap);
create_proc_read_entry("dvma_map",0,0,_sparc_io_get_info,&_sparc_dvma);
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index d4ac34932..5966e04d7 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.115 2000/02/26 04:24:31 davem Exp $
+/* $Id: setup.c,v 1.116 2000/03/15 23:26:22 anton Exp $
* linux/arch/sparc/kernel/setup.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -268,8 +268,6 @@ extern void sun_serial_setup(void);
extern unsigned short root_flags;
extern unsigned short root_dev;
extern unsigned short ram_flags;
-extern unsigned sparc_ramdisk_image;
-extern unsigned sparc_ramdisk_size;
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
@@ -382,42 +380,9 @@ void __init setup_arch(char **cmdline_p)
rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-// FIXME needs to do the new bootmem alloc stuff
- if (sparc_ramdisk_image) {
- initrd_start = sparc_ramdisk_image;
- if (initrd_start < KERNBASE) initrd_start += KERNBASE;
- initrd_end = initrd_start + sparc_ramdisk_size;
- if (initrd_end > *memory_end_p) {
- printk(KERN_CRIT "initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- initrd_end,*memory_end_p);
- initrd_start = 0;
- }
- if (initrd_start >= *memory_start_p && initrd_start < *memory_start_p + 2 * PAGE_SIZE) {
- initrd_below_start_ok = 1;
- *memory_start_p = PAGE_ALIGN (initrd_end);
- } else if (initrd_start && sparc_ramdisk_image < KERNBASE) {
- switch (sparc_cpu_model) {
- case sun4m:
- case sun4d:
- initrd_start -= KERNBASE;
- initrd_end -= KERNBASE;
- break;
- default:
- break;
- }
- }
- }
-#endif
+
prom_setsync(prom_sync_me);
-#ifdef CONFIG_SUN_SERIAL
-#if 0
- /* XXX We can't do this until the bootmem allocator is working. */
- sun_serial_setup(); /* set this up ASAP */
-#endif
-#endif
{
#if !CONFIG_SUN_SERIAL
serial_console = 0;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index e0bb41045..7b7a0eb61 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.94 2000/02/28 04:00:53 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.96 2000/03/16 09:12:49 jj Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -68,6 +68,8 @@ extern void bcopy (const char *, char *, int);
extern int __ashrdi3(int, int);
extern int __ashldi3(int, int);
extern int __lshrdi3(int, int);
+extern int __muldi3(int, int);
+extern int __divdi3(int, int);
extern void dump_thread(struct pt_regs *, struct user *);
@@ -85,10 +87,10 @@ extern int __sparc_dot_ ## sym (int) __asm__("." #sym); \
__EXPORT_SYMBOL(__sparc_dot_ ## sym, "." #sym)
#define EXPORT_SYMBOL_PRIVATE(sym) \
-extern int __sparc_priv_ ## sym (int) __asm__("__" ## #sym); \
+extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \
const struct module_symbol __export_priv_##sym \
__attribute__((section("__ksymtab"))) = \
-{ (unsigned long) &__sparc_priv_ ## sym, "__" ## #sym }
+{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym }
/* used by various drivers */
EXPORT_SYMBOL(sparc_cpu_model);
@@ -273,6 +275,8 @@ EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
+EXPORT_SYMBOL_NOVERS(__muldi3);
+EXPORT_SYMBOL_NOVERS(__divdi3);
EXPORT_SYMBOL_DOT(rem);
EXPORT_SYMBOL_DOT(urem);
diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c
index 8a9d54913..eb79c344c 100644
--- a/arch/sparc/kernel/sys_solaris.c
+++ b/arch/sparc/kernel/sys_solaris.c
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/module.h>
/* CHECKME: this stuff looks rather bogus */
asmlinkage int
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 262f6afdd..0a8a5827c 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.115 2000/03/13 21:57:23 davem Exp $
+/* $Id: sys_sunos.c,v 1.117 2000/03/15 02:43:32 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -267,35 +267,6 @@ asmlinkage void sunos_vadvise(unsigned long strategy)
unlock_kernel();
}
-/* Same as vadvise, and just as bogus, but for a range of virtual
- * process address space.
- */
-#define MADV_NORMAL 0 /* Nothing special... */
-#define MADV_RANDOM 1 /* I am emacs... */
-#define MADV_SEQUENTIAL 2 /* I am researcher code... */
-#define MADV_WILLNEED 3 /* Pages in this range will be needed */
-#define MADV_DONTNEED 4 /* Pages in this range won't be needed */
-
-static char *mstrings[] = {
- "MADV_NORMAL",
- "MADV_RANDOM",
- "MADV_SEQUENTIAL",
- "MADV_WILLNEED",
- "MADV_DONTNEED",
-};
-
-asmlinkage void sunos_madvise(unsigned long address, unsigned long len,
- unsigned long strategy)
-{
- /* I wanna see who uses this... */
- lock_kernel();
- printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
- current->comm,
- strategy <= 4 ? mstrings[strategy] : "BOGUS",
- address, len);
- unlock_kernel();
-}
-
/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
* resource limit and is for backwards compatibility with older sunos
* revs.
@@ -733,7 +704,6 @@ static int get_default (int value, int def_value)
asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
{
- int ret = -ENODEV;
int server_fd;
char *the_name;
struct nfs_mount_data linux_nfs_mount;
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 42c072164..431f03daf 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.95 2000/03/13 21:57:23 davem Exp $
+/* $Id: systbls.S,v 1.96 2000/03/15 02:43:32 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -33,7 +33,7 @@ sys_call_table:
/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid
/*70*/ .long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect
-/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16
+/*75*/ .long sys_madvise, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16
/*80*/ .long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64
/*85*/ .long sys_swapon, sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
/*90*/ .long sys_dup2, sys_setfsuid, sys_fcntl, sys_select, sys_setfsgid
@@ -103,7 +103,7 @@ sunos_sys_table:
.long sys_msync, sys_vfork, sunos_nosys
.long sunos_nosys, sunos_sbrk, sunos_sstk
.long sunos_mmap, sunos_vadvise, sys_munmap
- .long sys_mprotect, sunos_madvise, sys_vhangup
+ .long sys_mprotect, sys_madvise, sys_vhangup
.long sunos_nosys, sys_mincore, sys_getgroups16
.long sys_setgroups16, sys_getpgrp, sunos_setpgrp
.long sys_setitimer, sunos_nosys, sys_swapon
diff --git a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned.c
index 592a2a4c0..2f051a6aa 100644
--- a/arch/sparc/kernel/unaligned.c
+++ b/arch/sparc/kernel/unaligned.c
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.20 2000/01/21 11:38:42 jj Exp $
+/* $Id: unaligned.c,v 1.21 2000/03/15 08:50:16 anton Exp $
* unaligned.c: Unaligned load/store trap handling with special
* cases for the kernel to do them more quickly.
*
@@ -106,6 +106,26 @@ static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
return win->locals[reg - 16]; /* yes, I know what this does... */
}
+static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs)
+{
+ struct reg_window *win;
+ unsigned long ret;
+
+ if(reg < 16)
+ return (!reg ? 0 : regs->u_regs[reg]);
+
+ /* Ho hum, the slightly complicated case. */
+ win = (struct reg_window *) regs->u_regs[UREG_FP];
+
+ if ((unsigned long)win & 3)
+ return -1;
+
+ if (get_user(ret, &win->locals[reg - 16]))
+ return -1;
+
+ return ret;
+}
+
static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{
struct reg_window *win;
@@ -132,6 +152,22 @@ static inline unsigned long compute_effective_address(struct pt_regs *regs,
}
}
+static inline unsigned long safe_compute_effective_address(struct pt_regs *regs,
+ unsigned int insn)
+{
+ unsigned int rs1 = (insn >> 14) & 0x1f;
+ unsigned int rs2 = insn & 0x1f;
+ unsigned int rd = (insn >> 25) & 0x1f;
+
+ if(insn & 0x2000) {
+ maybe_flush_windows(rs1, 0, rd);
+ return (safe_fetch_reg(rs1, regs) + sign_extend_imm13(insn));
+ } else {
+ maybe_flush_windows(rs1, rs2, rd);
+ return (safe_fetch_reg(rs1, regs) + safe_fetch_reg(rs2, regs));
+ }
+}
+
/* This is just to make gcc think panic does return... */
static void unaligned_panic(char *str)
{
@@ -427,7 +463,7 @@ void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
- info.si_addr = (void *)compute_effective_address(regs, insn);
+ info.si_addr = (void *)safe_compute_effective_address(regs, insn);
info.si_trapno = 0;
send_sig_info(SIGBUS, &info, current);
}
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index d269e148b..8c3e8e4a9 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.32 2000/02/28 04:00:48 anton Exp $
+# $Id: Makefile,v 1.33 2000/03/16 00:52:07 anton Exp $
# Makefile for Sparc library files..
#
@@ -6,7 +6,7 @@ OBJS = mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \
- ashldi3.o rwsem.o
+ ashldi3.o rwsem.o muldi3.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc/lib/muldi3.S b/arch/sparc/lib/muldi3.S
new file mode 100644
index 000000000..7f17872d0
--- /dev/null
+++ b/arch/sparc/lib/muldi3.S
@@ -0,0 +1,76 @@
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+ .text
+ .align 4
+ .globl __muldi3
+__muldi3:
+ save %sp, -104, %sp
+ wr %g0, %i1, %y
+ sra %i3, 0x1f, %g2
+ and %i1, %g2, %g2
+ andcc %g0, 0, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, %i3, %g1
+ mulscc %g1, 0, %g1
+ add %g1, %g2, %l2
+ rd %y, %o1
+ mov %o1, %l3
+ mov %i1, %o0
+ call .umul
+ mov %i2, %o1
+ mov %o0, %l0
+ mov %i0, %o0
+ call .umul
+ mov %i3, %o1
+ add %l0, %o0, %l0
+ mov %l2, %i0
+ add %l2, %l0, %i0
+ ret
+ restore %g0, %l3, %o1
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index d92fbbb0b..2fa3a2c56 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.83 2000/03/07 23:12:35 anton Exp $
+/* $Id: init.c,v 1.84 2000/03/15 23:26:26 anton Exp $
* linux/arch/sparc/mm/init.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -43,7 +43,11 @@ unsigned long sparc_unmapped_base;
struct pgtable_cache_struct pgt_quicklists = { 0, 0, 0, 0, SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED };
/* References to section boundaries */
-extern char __init_begin, __init_end, _start, end, etext , edata;
+extern char __init_begin, __init_end, _start, _end, etext , edata;
+
+/* Initial ramdisk setup */
+extern unsigned int sparc_ramdisk_image;
+extern unsigned int sparc_ramdisk_size;
unsigned long totalram_pages = 0;
@@ -118,6 +122,7 @@ unsigned long __init bootmem_init(void)
{
unsigned long bootmap_size, start_pfn, end_pfn;
unsigned long end_of_phys_memory = 0UL;
+ unsigned long bootmap_pfn;
int i;
/* Limit maximum memory until we implement highmem for sparc */
@@ -160,7 +165,7 @@ unsigned long __init bootmem_init(void)
/* Start with page aligned address of last symbol in kernel
* image.
*/
- start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &end));
+ start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end));
/* Adjust up to the physical address where the kernel begins. */
start_pfn += phys_base;
@@ -168,14 +173,36 @@ unsigned long __init bootmem_init(void)
/* Now shift down to get the real physical page frame number. */
start_pfn >>= PAGE_SHIFT;
+ bootmap_pfn = start_pfn;
+
end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
+ if (sparc_ramdisk_image) {
+ if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+ sparc_ramdisk_image -= KERNBASE;
+ initrd_start = sparc_ramdisk_image + phys_base;
+ initrd_end = initrd_start + sparc_ramdisk_size;
+ if (initrd_end > end_of_phys_memory) {
+ printk(KERN_CRIT "initrd extends beyond end of memory "
+ "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
+ initrd_end, end_of_phys_memory);
+ initrd_start = 0;
+ }
+ if (initrd_start) {
+ if (initrd_start >= (start_pfn << PAGE_SHIFT) &&
+ initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE)
+ bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT;
+ }
+ }
+#endif
/* Initialize the boot-time allocator. */
#ifdef DEBUG_BOOTMEM
- prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n",
- start_pfn, end_pfn);
+ prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n",
+ start_pfn, bootmap_pfn, end_pfn);
#endif
- bootmap_size = init_bootmem(start_pfn, end_pfn);
+ bootmap_size = init_bootmem(bootmap_pfn, end_pfn);
/* Now register the available physical memory with the
* allocator.
@@ -190,15 +217,27 @@ unsigned long __init bootmem_init(void)
sp_banks[i].num_bytes);
}
- /* Reserve the kernel text/data/bss and the bootmem bitmap. */
+ /* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */
#ifdef DEBUG_BOOTMEM
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+ initrd_start, initrd_end - initrd_start);
+#endif
prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
- phys_base,
- (start_pfn << PAGE_SHIFT) +
- bootmap_size + PAGE_SIZE-1 - phys_base);
+ phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
+ prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+ (bootmap_pfn << PAGE_SHIFT), bootmap_size);
#endif
- reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) +
- bootmap_size + PAGE_SIZE-1 - phys_base);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ reserve_bootmem(initrd_start, initrd_end - initrd_start);
+ initrd_start += PAGE_OFFSET;
+ initrd_end += PAGE_OFFSET;
+ }
+#endif
+ reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
+ reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
#ifdef DEBUG_BOOTMEM
prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
@@ -371,18 +410,6 @@ void __init mem_init(void)
}
memset(sparc_valid_addr_bitmap, 0, i << 2);
- /* fix this */
-#ifdef CONFIG_BLK_DEV_INITRD
- addr = __va(phys_base);
- last = PAGE_ALIGN((unsigned long)&end) + phys_base;
- while(addr < last) {
- if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end)
- mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
- else
- addr += PAGE_SIZE;
- }
-#endif
-
taint_real_pages();
max_mapnr = last_valid_pfn;
@@ -446,6 +473,22 @@ void free_initmem (void)
printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
}
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ if (start < end)
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ for (; start < end; start += PAGE_SIZE) {
+ struct page *p = mem_map + MAP_NR(start);
+
+ ClearPageReserved(p);
+ set_page_count(p, 1);
+ __free_page(p);
+ num_physpages++;
+ }
+}
+#endif
+
void si_meminfo(struct sysinfo *val)
{
val->totalram = totalram_pages;
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index a1fb222c1..b4d7e5da9 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.101 2000/03/13 05:49:55 jj Exp $
+# $Id: config.in,v 1.104 2000/03/15 15:02:28 jj Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -32,16 +32,6 @@ define_bool CONFIG_SUN_IO y
bool 'PCI support' CONFIG_PCI
source drivers/pci/Config.in
-mainmenu_option next_comment
-comment 'Console drivers'
-bool 'PROM console' CONFIG_PROM_CONSOLE
-bool 'Support Frame buffer devices' CONFIG_FB
-source drivers/video/Config.in
-endmenu
-
-source drivers/sbus/char/Config.in
-source drivers/sbus/audio/Config.in
-
tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
@@ -78,7 +68,17 @@ fi
endmenu
mainmenu_option next_comment
-comment 'Floppy, IDE, and other block devices'
+comment 'Console drivers'
+bool 'PROM console' CONFIG_PROM_CONSOLE
+bool 'Support Frame buffer devices' CONFIG_FB
+source drivers/video/Config.in
+endmenu
+
+source drivers/sbus/char/Config.in
+source drivers/sbus/audio/Config.in
+
+mainmenu_option next_comment
+comment 'Block devices'
bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
@@ -86,8 +86,8 @@ bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
tristate ' Linear (append) mode' CONFIG_MD_LINEAR
tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED
- tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
- tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
+# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
+# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
fi
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
@@ -98,6 +98,8 @@ fi
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+endmenu
+
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
@@ -224,6 +226,7 @@ if [ "$CONFIG_NET" = "y" ]; then
tristate ' Sun QuadEthernet support' CONFIG_SUNQE
if [ "$CONFIG_PCI" = "y" ]; then
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
+ tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
tristate 'RealTek RTL-8139 support' CONFIG_8139TOO
tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index db85cfe1e..2f1d42a19 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -26,6 +26,42 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_PCI=y
CONFIG_PCI_NAMES=y
+CONFIG_SUN_OPENPROMFS=m
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_KCORE_ELF=y
+CONFIG_SPARC32_COMPAT=y
+CONFIG_BINFMT_ELF32=y
+# CONFIG_BINFMT_AOUT32 is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_SUNOS_EMUL is not set
+CONFIG_SOLARIS_EMUL=m
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+CONFIG_PRINTER=m
+CONFIG_ENVCTRL=m
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
#
# Console drivers
@@ -84,44 +120,9 @@ CONFIG_SPARCAUDIO=y
CONFIG_SPARCAUDIO_CS4231=y
# CONFIG_SPARCAUDIO_DBRI is not set
# CONFIG_SPARCAUDIO_DUMMY is not set
-CONFIG_SUN_OPENPROMFS=m
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-CONFIG_SPARC32_COMPAT=y
-CONFIG_BINFMT_ELF32=y
-# CONFIG_BINFMT_AOUT32 is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_SUNOS_EMUL is not set
-CONFIG_SOLARIS_EMUL=m
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-CONFIG_PRINTER=m
-CONFIG_ENVCTRL=m
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
#
-# Floppy, IDE, and other block devices
+# Block devices
#
CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_MD is not set
@@ -331,6 +332,7 @@ CONFIG_HAPPYMEAL=y
CONFIG_SUNBMAC=m
CONFIG_SUNQE=m
CONFIG_DE4X5=m
+CONFIG_TULIP=m
CONFIG_VORTEX=m
CONFIG_8139TOO=m
CONFIG_NE2K_PCI=m
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index 3e95ed9cf..3504533d1 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -33,7 +33,7 @@
#include <asm/pgalloc.h>
static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
-static int load_aout32_library(int fd);
+static int load_aout32_library(struct file*);
static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
extern void dump_thread(struct pt_regs *, struct user *);
@@ -343,9 +343,8 @@ beyond_if:
}
/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
-static int load_aout32_library(int fd)
+static int load_aout32_library(struct file *file)
{
- struct file * file;
struct inode * inode;
unsigned long bss, start_addr, len;
unsigned long error;
@@ -353,12 +352,6 @@ static int load_aout32_library(int fd)
loff_t offset = 0;
struct exec ex;
- retval = -EACCES;
- file = fget(fd);
- if (!file)
- goto out;
- if (!file->f_op)
- goto out_putf;
inode = file->f_dentry->d_inode;
retval = -ENOEXEC;
@@ -367,23 +360,23 @@ static int load_aout32_library(int fd)
error = file->f_op->read(file, (char *) &ex, sizeof(ex), &offset);
set_fs(USER_DS);
if (error != sizeof(ex))
- goto out_putf;
+ goto out;
/* We come in here for the regular a.out style of shared libraries */
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
- goto out_putf;
+ goto out;
}
if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
(N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
- goto out_putf;
+ goto out;
}
if (N_FLAGS(ex))
- goto out_putf;
+ goto out;
/* For QMAGIC, the starting address is 0x20 into the page. We mask
this off to get the starting address for the page */
@@ -391,13 +384,15 @@ static int load_aout32_library(int fd)
start_addr = ex.a_entry & 0xfffff000;
/* Now use mmap to map the library into memory. */
+ down(&current->mm->mmap_sem);
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
N_TXTOFF(ex));
+ up(&current->mm->mmap_sem);
retval = error;
if (error != start_addr)
- goto out_putf;
+ goto out;
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
@@ -405,12 +400,9 @@ static int load_aout32_library(int fd)
error = do_brk(start_addr + len, bss - len);
retval = error;
if (error != start_addr + len)
- goto out_putf;
+ goto out;
}
retval = 0;
-
-out_putf:
- fput(file);
out:
return retval;
}
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index d3a3814a8..0ba88adf6 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.82 2000/03/13 21:57:27 davem Exp $
+/* $Id: ioctl32.c,v 1.83 2000/03/14 07:31:25 jj Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
@@ -8,6 +8,7 @@
* ioctls.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -44,6 +45,14 @@
#include <linux/raw.h>
#include <linux/smb_fs.h>
#include <linux/blkpg.h>
+#include <linux/blk.h>
+#include <linux/elevator.h>
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* Ugh. This header really is not clean */
+#define min min
+#define max max
+#include <linux/lvm.h>
+#endif /* LVM */
#include <scsi/scsi.h>
/* Ugly hack. */
@@ -1980,6 +1989,353 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
return -EINVAL;
}
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */
+typedef struct {
+ uint8_t vg_name[NAME_LEN];
+ uint32_t vg_number;
+ uint32_t vg_access;
+ uint32_t vg_status;
+ uint32_t lv_max;
+ uint32_t lv_cur;
+ uint32_t lv_open;
+ uint32_t pv_max;
+ uint32_t pv_cur;
+ uint32_t pv_act;
+ uint32_t dummy;
+ uint32_t vgda;
+ uint32_t pe_size;
+ uint32_t pe_total;
+ uint32_t pe_allocated;
+ uint32_t pvg_total;
+ u32 proc;
+ u32 pv[ABS_MAX_PV + 1];
+ u32 lv[ABS_MAX_LV + 1];
+} vg32_t;
+
+typedef struct {
+ uint8_t id[2];
+ uint16_t version;
+ lvm_disk_data_t pv_on_disk;
+ lvm_disk_data_t vg_on_disk;
+ lvm_disk_data_t pv_namelist_on_disk;
+ lvm_disk_data_t lv_on_disk;
+ lvm_disk_data_t pe_on_disk;
+ uint8_t pv_name[NAME_LEN];
+ uint8_t vg_name[NAME_LEN];
+ uint8_t system_id[NAME_LEN];
+ kdev_t pv_dev;
+ uint32_t pv_number;
+ uint32_t pv_status;
+ uint32_t pv_allocatable;
+ uint32_t pv_size;
+ uint32_t lv_cur;
+ uint32_t pe_size;
+ uint32_t pe_total;
+ uint32_t pe_allocated;
+ uint32_t pe_stale;
+ u32 pe;
+ u32 inode;
+} pv32_t;
+
+typedef struct {
+ char lv_name[NAME_LEN];
+ u32 lv;
+} lv_req32_t;
+
+typedef struct {
+ u32 lv_index;
+ u32 lv;
+} lv_status_byindex_req32_t;
+
+typedef struct {
+ uint8_t lv_name[NAME_LEN];
+ kdev_t old_dev;
+ kdev_t new_dev;
+ u32 old_pe;
+ u32 new_pe;
+} le_remap_req32_t;
+
+typedef struct {
+ char pv_name[NAME_LEN];
+ u32 pv;
+} pv_status_req32_t;
+
+typedef struct {
+ uint8_t lv_name[NAME_LEN];
+ uint8_t vg_name[NAME_LEN];
+ uint32_t lv_access;
+ uint32_t lv_status;
+ uint32_t lv_open;
+ kdev_t lv_dev;
+ uint32_t lv_number;
+ uint32_t lv_mirror_copies;
+ uint32_t lv_recovery;
+ uint32_t lv_schedule;
+ uint32_t lv_size;
+ u32 lv_current_pe;
+ uint32_t lv_current_le;
+ uint32_t lv_allocated_le;
+ uint32_t lv_stripes;
+ uint32_t lv_stripesize;
+ uint32_t lv_badblock;
+ uint32_t lv_allocation;
+ uint32_t lv_io_timeout;
+ uint32_t lv_read_ahead;
+ /* delta to version 1 starts here */
+ u32 lv_snapshot_org;
+ u32 lv_snapshot_prev;
+ u32 lv_snapshot_next;
+ u32 lv_block_exception;
+ uint32_t lv_remap_ptr;
+ uint32_t lv_remap_end;
+ uint32_t lv_chunk_size;
+ uint32_t lv_snapshot_minor;
+ char dummy[200];
+} lv32_t;
+
+typedef struct {
+ u32 hash[2];
+ u32 rsector_org;
+ kdev_t rdev_org;
+ u32 rsector_new;
+ kdev_t rdev_new;
+} lv_block_exception32_t;
+
+static void put_lv_t(lv_t *l)
+{
+ if (l->lv_current_pe) vfree(l->lv_current_pe);
+ if (l->lv_block_exception) vfree(l->lv_block_exception);
+ kfree(l);
+}
+
+static lv_t *get_lv_t(u32 p, int *errp)
+{
+ int err, i;
+ u32 ptr1, ptr2;
+ size_t size;
+ lv_block_exception32_t *lbe32;
+ lv_block_exception_t *lbe;
+ lv32_t *ul = (lv32_t *)A(p);
+ lv_t *l = (lv_t *)kmalloc(sizeof(lv_t), GFP_KERNEL);
+ if (!l) {
+ *errp = -ENOMEM;
+ return NULL;
+ }
+ memset(l, 0, sizeof(lv_t));
+ err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe);
+ err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le,
+ ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le));
+ err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr,
+ ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr));
+ err |= __get_user(ptr1, &ul->lv_current_pe);
+ err |= __get_user(ptr2, &ul->lv_block_exception);
+ if (err) {
+ kfree(l);
+ *errp = -EFAULT;
+ return NULL;
+ }
+ if (ptr1) {
+ size = l->lv_allocated_le * sizeof(pe_t);
+ l->lv_current_pe = vmalloc(size);
+ if (l->lv_current_pe)
+ err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size);
+ }
+ if (!err && ptr2) {
+ size = l->lv_remap_end * sizeof(lv_block_exception_t);
+ l->lv_block_exception = lbe = vmalloc(size);
+ if (l->lv_block_exception) {
+ lbe32 = (lv_block_exception32_t *)A(ptr2);
+ memset(lbe, 0, size);
+ for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) {
+ err |= get_user(lbe->rsector_org, &lbe32->rsector_org);
+ err |= __get_user(lbe->rdev_org, &lbe32->rdev_org);
+ err |= __get_user(lbe->rsector_new, &lbe32->rsector_new);
+ err |= __get_user(lbe->rdev_new, &lbe32->rdev_new);
+ }
+ }
+ }
+ if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) {
+ if (!err)
+ *errp = -ENOMEM;
+ else
+ *errp = -EFAULT;
+ put_lv_t(l);
+ return NULL;
+ }
+ return l;
+}
+
+static int copy_lv_t(u32 ptr, lv_t *l)
+{
+ int err;
+ lv32_t *ul = (lv32_t *)A(ptr);
+ u32 ptr1;
+ size_t size;
+
+ err = get_user(ptr1, &ul->lv_current_pe);
+ if (err)
+ return -EFAULT;
+ err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe);
+ err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le,
+ ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le));
+ err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr,
+ ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr));
+ size = l->lv_allocated_le * sizeof(pe_t);
+ err |= __copy_to_user((void *)A(ptr1), l->lv_current_pe, size);
+ return -EFAULT;
+}
+
+static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ vg_t *v;
+ union {
+ lv_req_t lv_req;
+ le_remap_req_t le_remap;
+ lv_status_byindex_req_t lv_byindex;
+ pv_status_req32_t pv_status;
+ } u;
+ pv_t p;
+ int err;
+ u32 ptr = 0;
+ int i;
+ mm_segment_t old_fs;
+ void *karg = &u;
+
+ switch (cmd) {
+ case VG_STATUS:
+ v = kmalloc(sizeof(vg_t), GFP_KERNEL);
+ if (!v) return -ENOMEM;
+ karg = v;
+ break;
+ case VG_CREATE:
+ v = kmalloc(sizeof(vg_t), GFP_KERNEL);
+ if (!v) return -ENOMEM;
+ if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc) ||
+ __get_user(v->proc, &((vg32_t *)arg)->proc)) {
+ kfree(v);
+ return -EFAULT;
+ }
+ karg = v;
+ memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv));
+ if (v->pv_max > ABS_MAX_PV || v->lv_max == ABS_MAX_LV) return -EPERM;
+ for (i = 0; i < v->pv_max; i++) {
+ err = __get_user(ptr, &((vg32_t *)arg)->pv[i]);
+ if (err) break;
+ if (ptr) {
+ v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL);
+ if (!v->pv[i]) {
+ err = -ENOMEM;
+ break;
+ }
+ err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8);
+ if (err) {
+ err = -EFAULT;
+ break;
+ }
+ v->pv[i]->pe = NULL; v->pv[i]->inode = NULL;
+ }
+ }
+ if (!err) {
+ for (i = 0; i < v->lv_max; i++) {
+ err = __get_user(ptr, &((vg32_t *)arg)->lv[i]);
+ if (err) break;
+ if (ptr) {
+ v->lv[i] = get_lv_t(ptr, &err);
+ if (err) break;
+ }
+ }
+ }
+ break;
+ case LV_CREATE:
+ case LV_EXTEND:
+ case LV_REDUCE:
+ case LV_REMOVE:
+ case LV_STATUS_BYNAME:
+ err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name));
+ if (err) return -EFAULT;
+ if (cmd != LV_REMOVE) {
+ err = __get_user(ptr, &((lv_req32_t *)arg)->lv);
+ if (err) return err;
+ u.lv_req.lv = get_lv_t(ptr, &err);
+ } else
+ u.lv_req.lv = NULL;
+ break;
+ case LV_STATUS_BYINDEX:
+ err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index);
+ err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv);
+ if (err) return err;
+ u.lv_byindex.lv = get_lv_t(ptr, &err);
+ break;
+ case VG_EXTEND:
+ err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8);
+ if (err) return -EFAULT;
+ p.pe = NULL; p.inode = NULL;
+ karg = &p;
+ break;
+ case LE_REMAP:
+ err = copy_from_user(&u.le_remap, (void *)arg, sizeof(le_remap_req32_t));
+ if (err) return -EFAULT;
+ u.le_remap.new_pe = ((le_remap_req32_t *)&u.le_remap)->new_pe;
+ u.le_remap.old_pe = ((le_remap_req32_t *)&u.le_remap)->old_pe;
+ break;
+ case PV_CHANGE:
+ case PV_STATUS:
+ err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name));
+ if (err) return -EFAULT;
+ err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv);
+ if (err) return err;
+ u.pv_status.pv = &p;
+ if (cmd == PV_CHANGE) {
+ err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8);
+ if (err) return -EFAULT;
+ p.pe = NULL; p.inode = NULL;
+ }
+ break;
+ }
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)karg);
+ set_fs (old_fs);
+ switch (cmd) {
+ case VG_STATUS:
+ if (!err) {
+ if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) ||
+ clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc))
+ err = -EFAULT;
+ }
+ kfree(v);
+ break;
+ case VG_CREATE:
+ for (i = 0; i < v->pv_max; i++)
+ if (v->pv[i]) kfree(v->pv[i]);
+ for (i = 0; i < v->lv_max; i++)
+ if (v->lv[i]) put_lv_t(v->lv[i]);
+ kfree(v);
+ break;
+ case LV_STATUS_BYNAME:
+ if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv);
+ /* Fall through */
+ case LV_CREATE:
+ case LV_EXTEND:
+ case LV_REDUCE:
+ if (u.lv_req.lv) put_lv_t(u.lv_req.lv);
+ break;
+ case LV_STATUS_BYINDEX:
+ if (u.lv_byindex.lv) {
+ if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv);
+ put_lv_t(u.lv_byindex.lv);
+ }
+ case PV_STATUS:
+ if (!err) {
+ err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8);
+ if (err) return -EFAULT;
+ }
+ break;
+ }
+ return err;
+}
+#endif
+
static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
{
return -EINVAL;
@@ -2027,6 +2383,39 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioc
return err;
}
+typedef struct blkelv_ioctl32_arg_s {
+ u32 queue_ID;
+ int read_latency;
+ int write_latency;
+ int max_bomb_segments;
+} blkelv_ioctl32_arg_t;
+
+static int do_blkelv_ioctl(unsigned int fd, unsigned int cmd, blkelv_ioctl32_arg_t *arg)
+{
+ blkelv_ioctl_arg_t b;
+ int err;
+ mm_segment_t old_fs = get_fs();
+
+ if (cmd == BLKELVSET) {
+ err = get_user((long)b.queue_ID, &arg->queue_ID);
+ err |= __get_user(b.read_latency, &arg->read_latency);
+ err |= __get_user(b.write_latency, &arg->write_latency);
+ err |= __get_user(b.max_bomb_segments, &arg->max_bomb_segments);
+ if (err) return err;
+ }
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&b);
+ set_fs (old_fs);
+ if (cmd == BLKELVGET && !err) {
+ err = put_user((long)b.queue_ID, &arg->queue_ID);
+ err |= __put_user(b.read_latency, &arg->read_latency);
+ err |= __put_user(b.write_latency, &arg->write_latency);
+ err |= __put_user(b.max_bomb_segments, &arg->max_bomb_segments);
+ if (err) return err;
+ }
+ return err;
+}
+
static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
{
return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
@@ -2548,6 +2937,24 @@ COMPATIBLE_IOCTL(ATMTCP_CREATE)
COMPATIBLE_IOCTL(ATMTCP_REMOVE)
COMPATIBLE_IOCTL(ATMMPC_CTRL)
COMPATIBLE_IOCTL(ATMMPC_DATA)
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* 0xfe - lvm */
+COMPATIBLE_IOCTL(VG_SET_EXTENDABLE)
+COMPATIBLE_IOCTL(VG_STATUS_GET_COUNT)
+COMPATIBLE_IOCTL(VG_STATUS_GET_NAMELIST)
+COMPATIBLE_IOCTL(VG_REMOVE)
+COMPATIBLE_IOCTL(VG_REDUCE)
+COMPATIBLE_IOCTL(PE_LOCK_UNLOCK)
+COMPATIBLE_IOCTL(PV_FLUSH)
+COMPATIBLE_IOCTL(LVM_LOCK_LVM)
+COMPATIBLE_IOCTL(LVM_GET_IOP_VERSION)
+#ifdef LVM_TOTAL_RESET
+COMPATIBLE_IOCTL(LVM_RESET)
+#endif
+COMPATIBLE_IOCTL(LV_SET_ACCESS)
+COMPATIBLE_IOCTL(LV_SET_STATUS)
+COMPATIBLE_IOCTL(LV_SET_ALLOCATION)
+#endif /* LVM */
/* And these ioctls need translation */
HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
@@ -2594,6 +3001,8 @@ HANDLE_IOCTL(0x1260, broken_blkgetsize)
HANDLE_IOCTL(BLKFRAGET, w_long)
HANDLE_IOCTL(BLKSECTGET, w_long)
HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
+HANDLE_IOCTL(BLKELVGET, do_blkelv_ioctl)
+HANDLE_IOCTL(BLKELVSET, do_blkelv_ioctl)
HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap)
HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap)
HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor)
@@ -2677,6 +3086,20 @@ HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl)
+HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl)
+HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl)
+HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_REMOVE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_EXTEND, do_lvm_ioctl)
+HANDLE_IOCTL(LV_REDUCE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl)
+HANDLE_IOCTL(LE_REMAP, do_lvm_ioctl)
+HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl)
+HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl)
+#endif /* LVM */
IOCTL_TABLE_END
unsigned int ioctl32_hash_table[1024];
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 0d1b968fa..f0c9460fa 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.52 2000/03/03 23:48:41 davem Exp $
+/* $Id: setup.c,v 1.53 2000/03/15 14:42:52 jj Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -431,8 +431,6 @@ extern void panic_setup(char *, int *);
extern unsigned short root_flags;
extern unsigned short root_dev;
extern unsigned short ram_flags;
-extern unsigned int sparc_ramdisk_image;
-extern unsigned int sparc_ramdisk_size;
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
@@ -512,29 +510,6 @@ void __init setup_arch(char **cmdline_p)
rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-// FIXME needs to do the new bootmem alloc stuff
- if (sparc_ramdisk_image) {
- unsigned long start = 0;
-
- if (sparc_ramdisk_image >= (unsigned long)&end - 2 * PAGE_SIZE)
- sparc_ramdisk_image -= KERNBASE;
- initrd_start = sparc_ramdisk_image + phys_base + PAGE_OFFSET;
- initrd_end = initrd_start + sparc_ramdisk_size;
- if (initrd_end > *memory_end_p) {
- printk(KERN_CRIT "initrd extends beyond end of memory "
- "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
- initrd_end,*memory_end_p);
- initrd_start = 0;
- }
- if (initrd_start)
- start = sparc_ramdisk_image + KERNBASE;
- if (start >= *memory_start_p && start < *memory_start_p + 2 * PAGE_SIZE) {
- initrd_below_start_ok = 1;
- *memory_start_p = PAGE_ALIGN (start + sparc_ramdisk_size);
- }
- }
-#endif
/* Due to stack alignment restrictions and assumptions... */
init_mm.mmap->vm_page_prot = PAGE_SHARED;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b4ee5625e..0d5f615cf 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -528,7 +528,7 @@ static unsigned long penguins_are_doing_time = 0;
void smp_capture(void)
{
if (smp_processors_ready) {
- int result = atomic_add_return(1, &smp_capture_depth);
+ int result = __atomic_add(1, &smp_capture_depth);
membar("#StoreStore | #LoadStore");
if(result == 1) {
@@ -596,18 +596,21 @@ void smp_promstop_others(void)
smp_cross_call(&xcall_promstop, 0, 0, 0);
}
-static inline void sparc64_do_profile(unsigned long pc, unsigned long g3)
+static inline void sparc64_do_profile(unsigned long pc, unsigned long o7)
{
if (prof_buffer && current->pid) {
extern int _stext;
extern int rwlock_impl_begin, rwlock_impl_end;
extern int atomic_impl_begin, atomic_impl_end;
+ extern int __memcpy_begin, __memcpy_end;
- if ((pc >= (unsigned long) &rwlock_impl_begin &&
+ if ((pc >= (unsigned long) &atomic_impl_begin &&
+ pc < (unsigned long) &atomic_impl_end) ||
+ (pc >= (unsigned long) &rwlock_impl_begin &&
pc < (unsigned long) &rwlock_impl_end) ||
- (pc >= (unsigned long) &atomic_impl_begin &&
- pc < (unsigned long) &atomic_impl_end))
- pc = g3;
+ (pc >= (unsigned long) &__memcpy_begin &&
+ pc < (unsigned long) &__memcpy_end))
+ pc = o7;
pc -= (unsigned long) &_stext;
pc >>= prof_shift;
@@ -646,7 +649,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
clear_softint((1UL << 0));
do {
if(!user)
- sparc64_do_profile(regs->tpc, regs->u_regs[UREG_G3]);
+ sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]);
if(!--prof_counter(cpu))
{
if (cpu == boot_cpu_id) {
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index f798358ce..26e11085d 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.75 2000/02/21 15:50:08 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.79 2000/03/17 14:41:18 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -109,10 +109,10 @@ extern unsigned long phys_base;
*/
#define EXPORT_SYMBOL_PRIVATE(sym) \
-extern int __sparc_priv_ ## sym (int) __asm__("__" ## #sym); \
+extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \
const struct module_symbol __export_priv_##sym \
__attribute__((section("__ksymtab"))) = \
-{ (unsigned long) &__sparc_priv_ ## sym, "__" ## #sym }
+{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym }
/* used by various drivers */
#ifdef __SMP__
@@ -142,6 +142,8 @@ EXPORT_SYMBOL(cpu_data);
/* Misc SMP information */
EXPORT_SYMBOL(smp_num_cpus);
+EXPORT_SYMBOL(__cpu_number_map);
+EXPORT_SYMBOL(__cpu_logical_map);
/* Spinlock debugging library, optional. */
#ifdef SPIN_LOCK_DEBUG
@@ -207,6 +209,7 @@ EXPORT_SYMBOL(pci_map_sg);
EXPORT_SYMBOL(pci_unmap_sg);
EXPORT_SYMBOL(pci_dma_sync_single);
EXPORT_SYMBOL(pci_dma_sync_sg);
+EXPORT_SYMBOL(pci_dma_supported);
#endif
/* Solaris/SunOS binary compatibility */
@@ -288,6 +291,9 @@ EXPORT_SYMBOL(move_addr_to_user);
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(__memset);
EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_user_page);
+EXPORT_SYMBOL(copy_user_page);
EXPORT_SYMBOL(__bzero);
EXPORT_SYMBOL(__memscan_zero);
EXPORT_SYMBOL(__memscan_generic);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 81b4c4de1..82aedbb08 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.36 2000/02/16 07:31:35 davem Exp $
+/* $Id: sys_sparc.c,v 1.37 2000/03/17 05:48:46 anton Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -348,9 +348,10 @@ asmlinkage int solaris_syscall(struct pt_regs *regs)
lock_kernel();
regs->tpc = regs->tnpc;
regs->tnpc += 4;
- if(++count <= 20)
+ if(++count <= 5) {
printk ("For Solaris binary emulation you need solaris module loaded\n");
- show_regs (regs);
+ show_regs (regs);
+ }
send_sig(SIGSEGV, current, 1);
unlock_kernel();
return -ENOSYS;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index d4ecb0f4f..763acdc0f 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.136 2000/03/13 21:57:29 davem Exp $
+/* $Id: sys_sparc32.c,v 1.139 2000/03/16 20:37:57 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1746,70 +1746,58 @@ static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
return 0;
}
-extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
- unsigned long new_flags, void *data);
+extern long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page,
+ unsigned long new_flags, unsigned long data_page);
#define SMBFS_NAME "smbfs"
#define NCPFS_NAME "ncpfs"
asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
{
- unsigned long type_page;
+ unsigned long type_page = 0;
+ unsigned long data_page = 0;
int err, is_smb, is_ncp;
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
is_smb = is_ncp = 0;
+
+ lock_kernel();
err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
- if(err)
- return err;
- if(type_page) {
- is_smb = !strcmp((char *)type_page, SMBFS_NAME);
- is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+ if (err)
+ goto out;
+
+ if (!type_page) {
+ err = -EINVAL;
+ goto out;
}
- if(!is_smb && !is_ncp) {
- if(type_page)
- free_page(type_page);
- return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data));
- } else {
- unsigned long dev_page, dir_page, data_page;
- mm_segment_t old_fs;
- err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page);
- if(err)
- goto out;
- err = copy_mount_stuff_to_kernel((const void *)dir_name, &dir_page);
- if(err)
- goto dev_out;
- err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
- if(err)
- goto dir_out;
- if(is_ncp)
+ is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+ is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+
+ err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
+ if (err)
+ goto type_out;
+
+ if (!is_smb && !is_ncp) {
+ err = do_sys_mount(dev_name, dir_name, type_page, new_flags,
+ data_page);
+ } else {
+ if (is_ncp)
do_ncp_super_data_conv((void *)data_page);
- else if(is_smb)
- do_smb_super_data_conv((void *)data_page);
else
- panic("The problem is here...");
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_mount((char *)dev_page, (char *)dir_page,
- (char *)type_page, new_flags,
- (void *)data_page);
- set_fs(old_fs);
+ do_smb_super_data_conv((void *)data_page);
- if(data_page)
- free_page(data_page);
- dir_out:
- if(dir_page)
- free_page(dir_page);
- dev_out:
- if(dev_page)
- free_page(dev_page);
- out:
- if(type_page)
- free_page(type_page);
- return err;
+ err = do_sys_mount(dev_name, dir_name, type_page, new_flags,
+ data_page);
}
+
+ free_page(data_page);
+
+type_out:
+ free_page(type_page);
+
+out:
+ unlock_kernel();
+ return err;
}
struct rusage32 {
@@ -3071,7 +3059,7 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
lock_kernel();
- dentry = open_namei(filename, 0, 0);
+ dentry = open_namei(filename);
unlock_kernel();
retval = PTR_ERR(dentry);
@@ -4166,7 +4154,7 @@ asmlinkage long sparc32_open(const char * filename, int flags, int mode)
if (fd >= 0) {
struct file * f;
lock_kernel();
- f = filp_open(tmp, flags, mode);
+ f = filp_open(tmp, flags, mode, NULL);
unlock_kernel();
error = PTR_ERR(f);
if (IS_ERR(f))
@@ -4218,12 +4206,3 @@ out_sem:
out:
return ret;
}
-
-extern asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char *vec);
-
-asmlinkage long sys32_mincore(unsigned long start, u32 __len, unsigned char *vec)
-{
- size_t len = (size_t) __len;
-
- return sys_mincore(start, len, vec);
-}
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index f7f5964e9..a572e4976 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.41 2000/03/13 21:57:31 davem Exp $
+/* $Id: sys_sunos32.c,v 1.42 2000/03/15 02:43:35 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -225,33 +225,6 @@ asmlinkage void sunos_vadvise(u32 strategy)
unlock_kernel();
}
-/* Same as vadvise, and just as bogus, but for a range of virtual
- * process address space.
- */
-#define MADV_NORMAL 0 /* Nothing special... */
-#define MADV_RANDOM 1 /* I am emacs... */
-#define MADV_SEQUENTIAL 2 /* I am researcher code... */
-#define MADV_WILLNEED 3 /* Pages in this range will be needed */
-#define MADV_DONTNEED 4 /* Pages in this range won't be needed */
-
-static char *mstrings[] = {
- "MADV_NORMAL",
- "MADV_RANDOM",
- "MADV_SEQUENTIAL",
- "MADV_WILLNEED",
- "MADV_DONTNEED",
-};
-
-asmlinkage void sunos_madvise(u32 address, u32 len, u32 strategy)
-{
- /* I wanna see who uses this... */
- lock_kernel();
- printk("%s: Advises us to use %s paging strategy for addr<%08x> len<%08x>\n",
- current->comm, strategy <= 4 ? mstrings[strategy] : "BOGUS",
- address, len);
- unlock_kernel();
-}
-
/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
* resource limit and is for backwards compatibility with older sunos
* revs.
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 0a0edbf82..d86649bf7 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.69 2000/03/13 21:57:28 davem Exp $
+/* $Id: systbls.S,v 1.71 2000/03/15 02:43:36 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -34,7 +34,7 @@ sys_call_table32:
/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid
/*70*/ .word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect
- .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys32_mincore, sys32_getgroups16
+ .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16
/*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64
.word sys_swapon, sys32_getitimer, sys_setuid, sys_sethostname, sys_setgid
/*90*/ .word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid
@@ -93,7 +93,7 @@ sys_call_table:
/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize
.word sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect
- .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups
+ .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups
/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
.word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
/*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
@@ -163,8 +163,8 @@ sunos_sys_table:
.word sys_msync, sys_vfork, sunos_nosys
.word sunos_nosys, sunos_sbrk, sunos_sstk
.word sunos_mmap, sunos_vadvise, sys_munmap
- .word sys_mprotect, sunos_madvise, sys_vhangup
- .word sunos_nosys, sys32_mincore, sys32_getgroups16
+ .word sys_mprotect, sys_madvise, sys_vhangup
+ .word sunos_nosys, sys_mincore, sys32_getgroups16
.word sys32_setgroups16, sys_getpgrp, sunos_setpgrp
.word sys32_setitimer, sunos_nosys, sys_swapon
.word sys32_getitimer, sys_gethostname, sys_sethostname
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 792334336..989e965a9 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.18 1999/08/02 08:39:44 davem Exp $
+/* $Id: unaligned.c,v 1.19 2000/03/16 11:53:05 jj Exp $
* unaligned.c: Unaligned load/store trap handling with special
* cases for the kernel to do them more quickly.
*
@@ -590,9 +590,19 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
maybe_flush_windows(0, 0, rd, from_kernel);
reg = fetch_reg_addr(rd, regs);
- if ((insn & 0x780000) == 0x180000)
- reg[1] = 0;
- reg[0] = 0;
+ if (from_kernel || rd < 16) {
+ reg[0] = 0;
+ if ((insn & 0x780000) == 0x180000)
+ reg[1] = 0;
+ } else if (current->thread.flags & SPARC_FLAG_32BIT) {
+ put_user(0, (int *)reg);
+ if ((insn & 0x780000) == 0x180000)
+ put_user(0, ((int *)reg) + 1);
+ } else {
+ put_user(0, reg);
+ if ((insn & 0x780000) == 0x180000)
+ put_user(0, reg + 1);
+ }
advance(regs);
}
diff --git a/arch/sparc64/lib/VIScopy.S b/arch/sparc64/lib/VIScopy.S
index 57cf6b0f1..e20118648 100644
--- a/arch/sparc64/lib/VIScopy.S
+++ b/arch/sparc64/lib/VIScopy.S
@@ -1,4 +1,4 @@
-/* $Id: VIScopy.S,v 1.21 1999/07/30 09:35:35 davem Exp $
+/* $Id: VIScopy.S,v 1.22 2000/03/16 16:44:38 davem Exp $
* VIScopy.S: High speed copy operations utilizing the UltraSparc
* Visual Instruction Set.
*
@@ -304,6 +304,9 @@
.type bcopy,@function
#ifdef __KERNEL__
+ .globl __memcpy_begin
+__memcpy_begin:
+
.globl __memcpy
.type __memcpy,@function
@@ -1001,6 +1004,9 @@ fpu_retl:
FPU_RETL
#ifdef __KERNEL__
+ .globl __memcpy_end
+__memcpy_end:
+
.section .fixup
.align 4
VIScopyfixup_reto2:
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index cac9d15dd..35a34ebbf 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -1,4 +1,4 @@
-/* $Id: atomic.S,v 1.2 1999/08/23 05:15:58 davem Exp $
+/* $Id: atomic.S,v 1.3 2000/03/16 16:44:37 davem Exp $
* atomic.S: These things are too big to do inline.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -13,24 +13,24 @@
.globl __atomic_add
atomic_impl_begin:
-__atomic_add:
- lduw [%g1], %g5
- add %g5, %g2, %g7
- cas [%g1], %g5, %g7
+__atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
+ lduw [%o1], %g5
+ add %g5, %o0, %g7
+ cas [%o1], %g5, %g7
cmp %g5, %g7
bne,pn %icc, __atomic_add
nop
- jmpl %g3 + 8, %g0
- add %g7, %g2, %g2
+ retl
+ add %g7, %o0, %o0
.globl __atomic_sub
-__atomic_sub:
- lduw [%g1], %g5
- sub %g5, %g2, %g7
- cas [%g1], %g5, %g7
+__atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
+ lduw [%o1], %g5
+ sub %g5, %o0, %g7
+ cas [%o1], %g5, %g7
cmp %g5, %g7
bne,pn %icc, __atomic_sub
nop
- jmpl %g3 + 8, %g0
- sub %g7, %g2, %g2
+ retl
+ sub %g7, %o0, %o0
atomic_impl_end:
diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
index 1cdbf09da..b4a91b97c 100644
--- a/arch/sparc64/lib/blockops.S
+++ b/arch/sparc64/lib/blockops.S
@@ -1,8 +1,8 @@
-/* $Id: blockops.S,v 1.20 2000/03/03 23:48:38 davem Exp $
+/* $Id: blockops.S,v 1.22 2000/03/15 07:18:55 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
- * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com)
*/
#include "VIS.h"
@@ -24,23 +24,63 @@
#define TLBTEMP_ENTSZ (1 << 3)
.text
+
.align 32
.globl copy_page
.type copy_page,@function
copy_page: /* %o0=dest, %o1=src */
VISEntry
- ldx [%g6 + AOFF_task_active_mm], %o2
+ membar #LoadStore | #StoreStore | #StoreLoad
+ ldda [%o1] ASI_BLK_P, %f0
+ add %o1, 0x40, %o1
+ ldda [%o1] ASI_BLK_P, %f16
+ add %o1, 0x40, %o1
+ sethi %hi(8192), %o2
+1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
+ ldda [%o1] ASI_BLK_P, %f32
+ add %o1, 0x40, %o1
+ sub %o2, 0x40, %o2
+ stda %f48, [%o0] ASI_BLK_P
+ add %o0, 0x40, %o0
+ TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
+ ldda [%o1] ASI_BLK_P, %f0
+ add %o1, 0x40, %o1
+ sub %o2, 0x40, %o2
+ stda %f48, [%o0] ASI_BLK_P
+ add %o0, 0x40, %o0
+ TOUCH(f32, f34, f36, f38, f40, f42, f44, f46)
+ ldda [%o1] ASI_BLK_P, %f16
+ add %o1, 0x40, %o1
+ sub %o2, 0x40, %o2
+ stda %f48, [%o0] ASI_BLK_P
+ cmp %o2, 0x80
+ bne,pt %xcc, 1b
+ add %o0, 0x40, %o0
+ membar #Sync
+ stda %f0, [%o0] ASI_BLK_P
+ add %o0, 0x40, %o0
+ stda %f16, [%o0] ASI_BLK_P
+ membar #Sync
+ VISExit
+ retl
+ nop
+
+ .globl copy_user_page
+ .type copy_user_page,@function
+copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
+ VISEntry
+ sethi %hi(PAGE_SIZE), %g3
sub %o0, %g4, %g1
+ and %o2, %g3, %o0
+ sethi %hi(TLBTEMP_BASE), %o3
sethi %uhi(_PAGE_VALID), %g3
sub %o1, %g4, %g2
sllx %g3, 32, %g3
- ldx [%o2 + AOFF_mm_segments], %o0
+ mov TLB_TAG_ACCESS, %o2
or %g3, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), %g3
+ sethi %hi(DCACHE_SIZE), %o1
or %g1, %g3, %g1
or %g2, %g3, %g2
- mov TLB_TAG_ACCESS, %o2
- sethi %hi(TLBTEMP_BASE), %o3
- sethi %hi(DCACHE_SIZE), %o1
add %o0, %o3, %o0
add %o0, %o1, %o1
sethi %hi(TLBTEMP_ENT1), %o3
@@ -129,17 +169,25 @@ copy_page: /* %o0=dest, %o1=src */
.align 32
.globl clear_page
.type clear_page,@function
-clear_page: /* %o0=dest */
+clear_page: /* %o0=dest */
VISEntryHalf
- ldx [%g6 + AOFF_task_active_mm], %o2
+ ba,pt %xcc, clear_page_common
+ clr %o4
+
+ .align 32
+ .globl clear_user_page
+ .type clear_user_page,@function
+clear_user_page: /* %o0=dest, %o1=vaddr */
+ VISEntryHalf
+ sethi %hi(PAGE_SIZE), %g3
sub %o0, %g4, %g1
+ and %o1, %g3, %o0
+ mov TLB_TAG_ACCESS, %o2
sethi %uhi(_PAGE_VALID), %g3
+ sethi %hi(TLBTEMP_BASE), %o3
sllx %g3, 32, %g3
or %g3, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), %g3
- ldx [%o2 + AOFF_mm_segments], %o0
or %g1, %g3, %g1
- mov TLB_TAG_ACCESS, %o2
- sethi %hi(TLBTEMP_BASE), %o3
add %o0, %o3, %o0
sethi %hi(TLBTEMP_ENT2), %o3
rdpr %pstate, %g3
@@ -162,6 +210,9 @@ clear_page: /* %o0=dest */
stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS
membar #Sync
+ mov 1, %o4
+
+clear_page_common:
fzero %f0 ! FPA Group
mov 32, %o1 ! IEU0
fzero %f2 ! FPA Group
@@ -187,7 +238,13 @@ clear_page: /* %o0=dest */
membar #Sync ! LSU Group
VISExitHalf
- stxa %g5, [%o2] ASI_DMMU
+ brnz,pt %o4, 1f
+ nop
+
+ retl
+ nop
+
+1: stxa %g5, [%o2] ASI_DMMU
stxa %g7, [%o3] ASI_DTLB_DATA_ACCESS
membar #Sync
jmpl %o7 + 0x8, %g0
diff --git a/arch/sparc64/lib/rwlock.S b/arch/sparc64/lib/rwlock.S
index 74360bf68..03f3bfe59 100644
--- a/arch/sparc64/lib/rwlock.S
+++ b/arch/sparc64/lib/rwlock.S
@@ -1,4 +1,4 @@
-/* $Id: rwlock.S,v 1.2 1999/08/23 05:15:58 davem Exp $
+/* $Id: rwlock.S,v 1.3 2000/03/16 16:44:38 davem Exp $
* rwlocks.S: These things are too big to do inline.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -12,34 +12,33 @@
/* The non-contention read lock usage is 2 cache lines. */
.globl __read_lock, __read_unlock
- /* g1=lock, g3=retpc, g5/g7=scratch */
rwlock_impl_begin:
-__read_lock:
- ldsw [%g1], %g5
+__read_lock: /* %o0 = lock_ptr */
+ ldsw [%o0], %g5
brlz,pn %g5, __read_wait_for_writer
4: add %g5, 1, %g7
- cas [%g1], %g5, %g7
+ cas [%o0], %g5, %g7
cmp %g5, %g7
bne,pn %icc, __read_lock
membar #StoreLoad | #StoreStore
-99: jmpl %g3 + 8, %g0
+99: retl
nop
-__read_unlock:
- lduw [%g1], %g5
+__read_unlock: /* %o0 = lock_ptr */
+ lduw [%o0], %g5
sub %g5, 1, %g7
- cas [%g1], %g5, %g7
+ cas [%o0], %g5, %g7
cmp %g5, %g7
be,pt %xcc, 99b
membar #StoreLoad | #StoreStore
b,a,pt %xcc, __read_unlock
__read_wait_for_writer:
- ldsw [%g1], %g5
+ ldsw [%o0], %g5
brlz,pt %g5, __read_wait_for_writer
membar #LoadLoad
b,a,pt %xcc, 4b
__write_wait_for_writer:
- ldsw [%g1], %g5
+ ldsw [%o0], %g5
brlz,pt %g5, __write_wait_for_writer
membar #LoadLoad
b,a,pt %xcc, 4f
@@ -48,24 +47,23 @@ __write_wait_for_writer:
.align 64
.globl __write_unlock
- /* g1=lock, g3=retpc, g2/g5/g7=scratch */
-__write_unlock:
+__write_unlock: /* %o0 = lock_ptr */
sethi %hi(0x80000000), %g2
-1: lduw [%g1], %g5
+1: lduw [%o0], %g5
andn %g5, %g2, %g7
- cas [%g1], %g5, %g7
+ cas [%o0], %g5, %g7
cmp %g5, %g7
be,pt %icc, 99b
membar #StoreLoad | #StoreStore
b,a,pt %xcc, 1b
.globl __write_lock
-__write_lock:
+__write_lock: /* %o0 = lock_ptr */
sethi %hi(0x80000000), %g2
-1: ldsw [%g1], %g5
+1: ldsw [%o0], %g5
4: brnz,pn %g5, 5f
or %g5, %g2, %g7
- cas [%g1], %g5, %g7
+ cas [%o0], %g5, %g7
cmp %g5, %g7
be,pt %icc, 99b
membar #StoreLoad | #StoreStore
@@ -73,10 +71,10 @@ __write_lock:
b,a,pt %xcc, 1b
5: brlz %g5, __write_wait_for_writer
or %g5, %g2, %g7
- cas [%g1], %g5, %g7
+ cas [%o0], %g5, %g7
cmp %g5, %g7
bne,pn %icc, 5b
-8: ldsw [%g1], %g5
+8: ldsw [%o0], %g5
cmp %g5, %g2
be,pn %icc, 99b
membar #LoadLoad
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 226246980..6063d002e 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.42 2000/01/21 11:39:13 jj Exp $
+/* $Id: fault.c,v 1.43 2000/03/14 03:59:46 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -245,7 +245,7 @@ good_area:
if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
- current->mm->segments = (void *) (address & PAGE_SIZE);
+
{
int fault = handle_mm_fault(current, vma, address, write);
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index d09ac451b..1d2049b5f 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.148 2000/03/07 07:08:31 anton Exp $
+/* $Id: init.c,v 1.149 2000/03/15 14:42:58 jj Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -48,6 +48,10 @@ unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
/* References to section boundaries */
extern char __init_begin, __init_end, _start, _end, etext, edata;
+/* Initial ramdisk setup */
+extern unsigned int sparc_ramdisk_image;
+extern unsigned int sparc_ramdisk_size;
+
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
@@ -808,6 +812,7 @@ unsigned long __init bootmem_init(void)
{
unsigned long bootmap_size, start_pfn, end_pfn;
unsigned long end_of_phys_memory = 0UL;
+ unsigned long bootmap_pfn;
int i;
/* XXX It is a bit ambiguous here, whether we should
@@ -855,15 +860,37 @@ unsigned long __init bootmem_init(void)
/* Now shift down to get the real physical page frame number. */
start_pfn >>= PAGE_SHIFT;
+
+ bootmap_pfn = start_pfn;
end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
+ if (sparc_ramdisk_image) {
+ if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+ sparc_ramdisk_image -= KERNBASE;
+ initrd_start = sparc_ramdisk_image + phys_base;
+ initrd_end = initrd_start + sparc_ramdisk_size;
+ if (initrd_end > end_of_phys_memory) {
+ printk(KERN_CRIT "initrd extends beyond end of memory "
+ "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
+ initrd_end, end_of_phys_memory);
+ initrd_start = 0;
+ }
+ if (initrd_start) {
+ if (initrd_start >= (start_pfn << PAGE_SHIFT) &&
+ initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE)
+ bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT;
+ }
+ }
+#endif
/* Initialize the boot-time allocator. */
#ifdef DEBUG_BOOTMEM
- prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n",
- start_pfn, end_pfn);
+ prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n",
+ start_pfn, bootmap_pfn, end_pfn);
#endif
- bootmap_size = init_bootmem(start_pfn, end_pfn);
+ bootmap_size = init_bootmem(bootmap_pfn, end_pfn);
/* Now register the available physical memory with the
* allocator.
@@ -878,15 +905,27 @@ unsigned long __init bootmem_init(void)
sp_banks[i].num_bytes);
}
- /* Reserve the kernel text/data/bss and the bootmem bitmap. */
+ /* Reserve the kernel text/data/bss, the bootmem bootmap and initrd. */
#ifdef DEBUG_BOOTMEM
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+ initrd_start, initrd_end - initrd_start);
+#endif
+ prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+ phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
- phys_base,
- (((start_pfn << PAGE_SHIFT) +
- bootmap_size) - phys_base));
+ (bootmap_pfn << PAGE_SHIFT), bootmap_size);
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ reserve_bootmem(initrd_start, initrd_end - initrd_start);
+ initrd_start += PAGE_OFFSET;
+ initrd_end += PAGE_OFFSET;
+ }
#endif
- reserve_bootmem(phys_base, (((start_pfn << PAGE_SHIFT) +
- bootmap_size) - phys_base));
+ reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
+ reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
#ifdef DEBUG_BOOTMEM
prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
@@ -1234,11 +1273,6 @@ void __init mem_init(void)
((unsigned long) &empty_zero_page);
last += PAGE_OFFSET + phys_base;
while (addr < last) {
-#ifdef CONFIG_BLK_DEV_INITRD
-// FIXME to use bootmem scheme...
- if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end)
- mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
-#endif
set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
addr += PAGE_SIZE;
}
@@ -1319,6 +1353,22 @@ void free_initmem (void)
}
}
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ if (start < end)
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ for (; start < end; start += PAGE_SIZE) {
+ struct page *p = mem_map + MAP_NR(start);
+
+ ClearPageReserved(p);
+ set_page_count(p, 1);
+ __free_page(p);
+ num_physpages++;
+ }
+}
+#endif
+
void si_meminfo(struct sysinfo *val)
{
val->totalram = num_physpages;