summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/Makefile44
-rw-r--r--arch/alpha/kernel/core_apecs.c2
-rw-r--r--arch/alpha/kernel/core_cia.c10
-rw-r--r--arch/alpha/kernel/core_lca.c2
-rw-r--r--arch/alpha/kernel/core_mcpcia.c4
-rw-r--r--arch/alpha/kernel/core_pyxis.c130
-rw-r--r--arch/alpha/kernel/core_tsunami.c8
-rw-r--r--arch/alpha/kernel/irq.c1076
-rw-r--r--arch/alpha/kernel/irq_impl.h41
-rw-r--r--arch/alpha/kernel/machvec_impl.h3
-rw-r--r--arch/alpha/kernel/pci_impl.h23
-rw-r--r--arch/alpha/kernel/pci_iommu.c149
-rw-r--r--arch/alpha/kernel/proto.h4
-rw-r--r--arch/alpha/kernel/setup.c1
-rw-r--r--arch/alpha/kernel/signal.c4
-rw-r--r--arch/alpha/kernel/smp.c27
-rw-r--r--arch/alpha/kernel/sys_alcor.c14
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c12
-rw-r--r--arch/alpha/kernel/sys_dp264.c96
-rw-r--r--arch/alpha/kernel/sys_eb64p.c14
-rw-r--r--arch/alpha/kernel/sys_eiger.c12
-rw-r--r--arch/alpha/kernel/sys_jensen.c3
-rw-r--r--arch/alpha/kernel/sys_miata.c1
-rw-r--r--arch/alpha/kernel/sys_mikasa.c14
-rw-r--r--arch/alpha/kernel/sys_nautilus.c1
-rw-r--r--arch/alpha/kernel/sys_noritake.c7
-rw-r--r--arch/alpha/kernel/sys_rawhide.c19
-rw-r--r--arch/alpha/kernel/sys_ruffian.c4
-rw-r--r--arch/alpha/kernel/sys_rx164.c12
-rw-r--r--arch/alpha/kernel/sys_sable.c19
-rw-r--r--arch/alpha/kernel/sys_sio.c1
-rw-r--r--arch/alpha/kernel/sys_sx164.c1
-rw-r--r--arch/alpha/kernel/sys_takara.c12
-rw-r--r--arch/alpha/kernel/time.c14
-rw-r--r--arch/alpha/mm/fault.c13
-rw-r--r--arch/arm/boot/compressed/Makefile9
-rw-r--r--arch/arm/boot/compressed/head-sa1100.S61
-rw-r--r--arch/arm/config.in12
-rw-r--r--arch/arm/kernel/arthur.c60
-rw-r--r--arch/arm/kernel/entry-armo.S20
-rw-r--r--arch/arm/kernel/entry-armv.S20
-rw-r--r--arch/arm/kernel/entry-common.S47
-rw-r--r--arch/arm/kernel/hw-footbridge.c16
-rw-r--r--arch/arm/kernel/irq.c4
-rw-r--r--arch/arm/kernel/leds-footbridge.c4
-rw-r--r--arch/arm/kernel/setup.c2
-rw-r--r--arch/arm/kernel/sys_arm.c23
-rw-r--r--arch/arm/lib/findbit.S4
-rw-r--r--arch/arm/lib/getconsdata.c2
-rw-r--r--arch/arm/lib/strrchr.S2
-rw-r--r--arch/arm/mm/consistent.c19
-rw-r--r--arch/arm/mm/fault-armv.c4
-rw-r--r--arch/arm/mm/fault-common.c2
-rw-r--r--arch/arm/mm/mm-armv.c8
-rw-r--r--arch/arm/mm/mm-nexuspci.c20
-rw-r--r--arch/arm/vmlinux-armo.lds.in5
-rw-r--r--arch/arm/vmlinux-armv.lds.in35
-rw-r--r--arch/i386/config.in31
-rw-r--r--arch/i386/defconfig6
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/acpi.c25
-rw-r--r--arch/i386/kernel/i8259.c2
-rw-r--r--arch/i386/kernel/io_apic.c3
-rw-r--r--arch/i386/kernel/irq.c50
-rw-r--r--arch/i386/kernel/microcode.c97
-rw-r--r--arch/i386/kernel/pci-pc.c43
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/signal.c10
-rw-r--r--arch/i386/kernel/traps.c1
-rw-r--r--arch/i386/mm/init.c3
-rw-r--r--arch/mips/arc/console.c3
-rw-r--r--arch/mips/arc/init.c3
-rw-r--r--arch/mips/arc/memory.c3
-rw-r--r--arch/mips/arc/printf.c3
-rw-r--r--arch/mips/baget/balo_supp.S3
-rw-r--r--arch/mips/baget/prom/init.c3
-rw-r--r--arch/mips/baget/setup.c3
-rw-r--r--arch/mips/ddb5074/irq.c3
-rw-r--r--arch/mips/ddb5074/pci.c4
-rw-r--r--arch/mips/dec/prom/cmdline.c3
-rw-r--r--arch/mips/dec/prom/identify.c3
-rw-r--r--arch/mips/kernel/irixelf.c25
-rw-r--r--arch/mips/kernel/r2300_misc.S4
-rw-r--r--arch/mips/kernel/syscall.c4
-rw-r--r--arch/mips/kernel/sysirix.c4
-rw-r--r--arch/mips/kernel/time.c3
-rw-r--r--arch/mips/mm/loadmmu.c3
-rw-r--r--arch/mips/sgi/kernel/indy_int.c3
-rw-r--r--arch/mips64/arc/init.c3
-rw-r--r--arch/mips64/arc/memory.c4
-rw-r--r--arch/mips64/defconfig-ip221
-rw-r--r--arch/mips64/kernel/signal32.c3
-rw-r--r--arch/mips64/kernel/syscall.c5
-rw-r--r--arch/mips64/sgi-ip27/ip27-init.c1
-rw-r--r--arch/mips64/sgi-ip27/ip27-irq.c3
-rw-r--r--arch/mips64/sgi-ip27/ip27-rtc.c13
-rw-r--r--arch/mips64/sgi-ip27/ip27-setup.c3
-rw-r--r--arch/mips64/sgi-ip27/ip27-timer.c5
-rw-r--r--arch/sparc/config.in3
-rw-r--r--arch/sparc/defconfig3
-rw-r--r--arch/sparc/kernel/ioport.c2
-rw-r--r--arch/sparc/kernel/pcic.c9
-rw-r--r--arch/sparc/kernel/process.c4
-rw-r--r--arch/sparc64/config.in4
-rw-r--r--arch/sparc64/defconfig2
-rw-r--r--arch/sparc64/kernel/irq.c46
-rw-r--r--arch/sparc64/kernel/pci.c7
-rw-r--r--arch/sparc64/kernel/process.c10
-rw-r--r--arch/sparc64/kernel/smp.c106
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c16
-rw-r--r--arch/sparc64/kernel/time.c43
111 files changed, 1426 insertions, 1401 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index fa9e06371..309a308a4 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -13,10 +13,21 @@
$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
O_TARGET := kernel.o
-O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- ptrace.o time.o semaphore.o i8259.o
+O_OBJS := entry.o traps.o process.o osf_sys.o irq.o irq_alpha.o \
+ signal.o setup.o ptrace.o time.o semaphore.o
OX_OBJS := alpha_ksyms.o
+L_TARGET := rest.a
+L_OBJS := irq_i8259.o irq_srm.o \
+ es1888.o smc37c669.o smc37c93x.o ns87312.o
+
+ifdef CONFIG_SMP
+O_OBJS += smp.o irq_smp.o
+endif
+
+ifdef CONFIG_PCI
+L_OBJS += pci.o pci_iommu.o
+endif
ifdef CONFIG_ALPHA_GENERIC
@@ -25,13 +36,9 @@ O_OBJS += core_apecs.o core_cia.o core_irongate.o core_lca.o core_mcpcia.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 \
- sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \
- es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o pci_iommu.o
-else
+ sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o
-ifdef CONFIG_PCI
-O_OBJS += pci.o pci_iommu.o
-endif
+else
# Core logic support
ifdef CONFIG_ALPHA_APECS
@@ -67,10 +74,10 @@ ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
O_OBJS += sys_alcor.o
endif
ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
-O_OBJS += sys_cabriolet.o ns87312.o
+O_OBJS += sys_cabriolet.o
endif
ifdef CONFIG_ALPHA_DP264
-O_OBJS += sys_dp264.o es1888.o smc37c669.o
+O_OBJS += sys_dp264.o
endif
ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
O_OBJS += sys_eb64p.o
@@ -82,7 +89,7 @@ ifdef CONFIG_ALPHA_JENSEN
O_OBJS += sys_jensen.o
endif
ifdef CONFIG_ALPHA_MIATA
-O_OBJS += sys_miata.o es1888.o smc37c669.o
+O_OBJS += sys_miata.o
endif
ifdef CONFIG_ALPHA_MIKASA
O_OBJS += sys_mikasa.o
@@ -106,25 +113,18 @@ ifdef CONFIG_ALPHA_SABLE
O_OBJS += sys_sable.o
endif
ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),)
-O_OBJS += sys_sio.o ns87312.o
+O_OBJS += sys_sio.o
endif
ifdef CONFIG_ALPHA_SX164
-O_OBJS += sys_sx164.o smc37c669.o
+O_OBJS += sys_sx164.o
endif
ifdef CONFIG_ALPHA_TAKARA
-O_OBJS += sys_takara.o ns87312.o
-endif
-
-# Device support
-ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),)
-O_OBJS += smc37c93x.o
+O_OBJS += sys_takara.o
endif
endif # GENERIC
-ifdef CONFIG_SMP
-O_OBJS += smp.o
-endif
+O_OBJS += $(L_TARGET)
all: kernel.o head.o
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
index 9ea4f53e9..51e5b1174 100644
--- a/arch/alpha/kernel/core_apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -385,7 +385,7 @@ apecs_init_arch(void)
* Window 1 is direct access 1GB at 1GB
* Window 2 is scatter-gather 8MB at 8MB (for isa)
*/
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
hose->sg_pci = NULL;
__direct_map_base = 0x40000000;
__direct_map_size = 0x40000000;
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index 36b9a1fa9..b8a7f18ee 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -405,10 +405,12 @@ cia_init_arch(void)
* ??? We ought to scale window 1 with memory.
*/
- /* NetBSD hints that page tables must be aligned to 32K due
- to a hardware bug. No description of what models affected. */
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, 32768);
- hose->sg_pci = iommu_arena_new(0x40000000, 0x08000000, 32768);
+ /* ??? 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;
__direct_map_size = 0x80000000;
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
index 2bee78a1b..8039c0d14 100644
--- a/arch/alpha/kernel/core_lca.c
+++ b/arch/alpha/kernel/core_lca.c
@@ -307,7 +307,7 @@ lca_init_arch(void)
* Window 0 is direct access 1GB at 1GB
* Window 1 is scatter-gather 8MB at 8MB (for isa)
*/
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
hose->sg_pci = NULL;
__direct_map_base = 0x40000000;
__direct_map_size = 0x40000000;
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index ac97ce1fe..7564d83e9 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -404,8 +404,8 @@ mcpcia_startup_hose(struct pci_controler *hose)
* ??? We ought to scale window 1 with memory.
*/
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
- hose->sg_pci = iommu_arena_new(0x40000000, 0x08000000, PAGE_SIZE);
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+ hose->sg_pci = iommu_arena_new(hose, 0x40000000, 0x08000000, 0);
__direct_map_base = 0x80000000;
__direct_map_size = 0x80000000;
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
index 80ee8ba7f..f6106c475 100644
--- a/arch/alpha/kernel/core_pyxis.c
+++ b/arch/alpha/kernel/core_pyxis.c
@@ -36,7 +36,6 @@
*/
#define DEBUG_CONFIG 0
-
#if DEBUG_CONFIG
# define DBG_CNF(args) printk args
#else
@@ -304,7 +303,7 @@ pyxis_enable_irq(unsigned int irq)
pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
}
-static inline void
+static void
pyxis_disable_irq(unsigned int irq)
{
pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
@@ -318,6 +317,13 @@ pyxis_startup_irq(unsigned int irq)
}
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);
@@ -340,7 +346,7 @@ static struct hw_interrupt_type pyxis_irq_type = {
enable: pyxis_enable_irq,
disable: pyxis_disable_irq,
ack: pyxis_mask_and_ack_irq,
- end: pyxis_enable_irq,
+ end: pyxis_end_irq,
};
void
@@ -382,7 +388,7 @@ init_pyxis_irqs(unsigned long ignore_mask)
for (i = 16; i < 48; ++i) {
if ((ignore_mask >> i) & 1)
continue;
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &pyxis_irq_type;
}
@@ -427,6 +433,8 @@ pyxis_broken_pci_tbi(struct pci_controler *hose,
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
@@ -441,6 +449,8 @@ pyxis_broken_pci_tbi(struct pci_controler *hose,
mb();
*(vuip)PYXIS_CTRL = ctrl;
mb();
+ *(vuip)PYXIS_CTRL;
+ mb();
__restore_flags(flags);
}
@@ -473,31 +483,31 @@ pyxis_init_arch(void)
struct pci_controler *hose;
unsigned int temp;
-#if 0
- printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
- printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR);
- printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ);
- printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK);
- printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE);
- printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO);
- printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG);
- printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT);
-#endif
-
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
+ /* Set up error reporting. Make sure CPU_PE is OFF in the mask. */
temp = *(vuip)PYXIS_ERR_MASK;
- temp &= ~4;
- *(vuip)PYXIS_ERR_MASK = temp;
- mb();
- *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
+ *(vuip)PYXIS_ERR_MASK = temp & ~4;
+ /* Enable master/target abort. */
temp = *(vuip)PYXIS_ERR;
- temp |= 0x180; /* master/target abort */
- *(vuip)PYXIS_ERR = temp;
+ *(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_ERR; /* re-read to force write */
+ *(vuip)PYXIS_REV;
/*
* Create our single hose.
@@ -524,10 +534,41 @@ pyxis_init_arch(void)
* address range.
*/
- /* NetBSD hints that page tables must be aligned to 32K due
- to a hardware bug. No description of what models affected. */
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, 32768);
- hose->sg_pci = iommu_arena_new(0xc0000000, 0x08000000, 32768);
+#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;
@@ -553,36 +594,7 @@ pyxis_init_arch(void)
pyxis_enable_broken_tbi(hose->sg_pci);
alpha_mv.mv_pci_tbi(hose, 0, -1);
-
- /*
- * Next, 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...
- */
- temp = *(vuip)PYXIS_CFG;
- if (temp != 0) {
- *(vuip)PYXIS_CFG = 0;
- mb();
- *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- /* Zero the HAE. */
- *(vuip)PYXIS_HAE_MEM = 0U; mb();
- *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
- *(vuip)PYXIS_HAE_IO = 0; mb();
- *(vuip)PYXIS_HAE_IO; /* re-read to force write */
-
- /*
- * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
- * enabling byte/word PCI bus space(s) access.
- */
- temp = *(vuip) PYXIS_CTRL1;
- if (!(temp & 1)) {
- *(vuip)PYXIS_CTRL1 = temp | 1;
- mb();
- *(vuip)PYXIS_CTRL1; /* re-read */
- }
+#endif
}
static inline void
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 1452b6336..1fa5a8088 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -343,13 +343,9 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
* 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.
- *
- * Note that the TLB lookup logic uses bitwise concatenation,
- * not addition, so the required arena alignment is based on
- * the size of the window.
*/
- hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, 0x00800000>>10);
- hose->sg_pci = iommu_arena_new(0xc0000000, 0x08000000, 0x08000000>>10);
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+ hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0);
__direct_map_base = 0x40000000;
__direct_map_size = 0x80000000;
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index 613a633ba..bc8ca101a 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -17,304 +17,85 @@
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/init.h>
-#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/dma.h>
#include <asm/bitops.h>
-#include <asm/machvec.h>
-
-#include "proto.h"
-#include "irq_impl.h"
-
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
-/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives
- in the per-cpu structure for cache reasons. */
-#ifndef CONFIG_SMP
-int __local_irq_count;
-int __local_bh_count;
-unsigned long __irq_attempt[NR_IRQS];
-#endif
-
-#ifdef CONFIG_ALPHA_GENERIC
-#define ACTUAL_NR_IRQS alpha_mv.nr_irqs
-#else
-#define ACTUAL_NR_IRQS NR_IRQS
-#endif
-
-/* Hack minimum IPL during interupt processing for broken hardware. */
-
-#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
-int __min_ipl;
-#endif
+#include <asm/uaccess.h>
/*
- * Performance counter hook. A module can override this to
- * do something useful.
+ * Controller mappings for all interrupt sources:
*/
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
+ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}
+};
-static void
-dummy_perf(unsigned long vector, struct pt_regs *regs)
-{
- printk(KERN_CRIT "Performance counter interrupt!\n");
-}
-
-void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
-
-/*
- * Dispatch device interrupts.
- */
-
-/*
- * Handle ISA interrupt via the PICs.
- */
-
-#if defined(CONFIG_ALPHA_GENERIC)
-# define IACK_SC alpha_mv.iack_sc
-#elif defined(CONFIG_ALPHA_APECS)
-# define IACK_SC APECS_IACK_SC
-#elif defined(CONFIG_ALPHA_LCA)
-# define IACK_SC LCA_IACK_SC
-#elif defined(CONFIG_ALPHA_CIA)
-# define IACK_SC CIA_IACK_SC
-#elif defined(CONFIG_ALPHA_PYXIS)
-# define IACK_SC PYXIS_IACK_SC
-#elif defined(CONFIG_ALPHA_TSUNAMI)
-# define IACK_SC TSUNAMI_IACK_SC
-#elif defined(CONFIG_ALPHA_POLARIS)
-# define IACK_SC POLARIS_IACK_SC
-#elif defined(CONFIG_ALPHA_IRONGATE)
-# define IACK_SC IRONGATE_IACK_SC
-#endif
-
-#if defined(IACK_SC)
-void
-isa_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- /*
- * Generate a PCI interrupt acknowledge cycle. The PIC will
- * respond with the interrupt vector of the highest priority
- * interrupt that is pending. The PALcode sets up the
- * interrupts vectors such that irq level L generates vector L.
- */
- int j = *(vuip) IACK_SC;
- j &= 0xff;
- if (j == 7) {
- if (!(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- return;
- }
- }
- handle_irq(j, regs);
-}
-#endif
-#if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC)
-void
-isa_no_iack_sc_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pic;
-
- /*
- * It seems to me that the probability of two or more *device*
- * interrupts occurring at almost exactly the same time is
- * pretty low. So why pay the price of checking for
- * additional interrupts here if the common case can be
- * handled so much easier?
- */
- /*
- * The first read of gives you *all* interrupting lines.
- * Therefore, read the mask register and and out those lines
- * not enabled. Note that some documentation has 21 and a1
- * write only. This is not true.
- */
- pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= 0xFFFB; /* mask out cascade & hibits */
+static void register_irq_proc(unsigned int irq);
- while (pic) {
- int j = ffz(~pic);
- pic &= pic - 1;
- handle_irq(j, regs);
- }
-}
-#endif
+unsigned long irq_err_count;
/*
- * Handle interrupts from the SRM, assuming no additional weirdness.
+ * Special irq handlers.
*/
-static inline void
-srm_enable_irq(unsigned int irq)
-{
- cserve_ena(irq - 16);
-}
-
-static void
-srm_disable_irq(unsigned int irq)
-{
- cserve_dis(irq - 16);
-}
-
-static unsigned int
-srm_startup_irq(unsigned int irq)
-{
- srm_enable_irq(irq);
- return 0;
-}
-
-static struct hw_interrupt_type srm_irq_type = {
- typename: "SRM",
- startup: srm_startup_irq,
- shutdown: srm_disable_irq,
- enable: srm_enable_irq,
- disable: srm_disable_irq,
- ack: srm_disable_irq,
- end: srm_enable_irq,
-};
-
-void
-srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
-{
- int irq = (vector - 0x800) >> 4;
- handle_irq(irq, regs);
-}
-
-void __init
-init_srm_irqs(long max, unsigned long ignore_mask)
-{
- long i;
-
- for (i = 16; i < max; ++i) {
- if (i < 64 && ((ignore_mask >> i) & 1))
- continue;
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].handler = &srm_irq_type;
- }
-}
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
/*
- * The not-handled irq handler.
+ * Generic no controller code
*/
-static void
-noirq_enable_disable(unsigned int irq)
-{
-}
-
-static unsigned int
-noirq_startup(unsigned int irq)
-{
- return 0;
-}
+static void no_irq_enable_disable(unsigned int irq) { }
+static unsigned int no_irq_startup(unsigned int irq) { return 0; }
static void
-noirq_ack(unsigned int irq)
+no_irq_ack(unsigned int irq)
{
- printk(KERN_CRIT "Unexpected IRQ %u\n", irq);
+ irq_err_count++;
+ printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
}
-static struct hw_interrupt_type no_irq_type = {
+struct hw_interrupt_type no_irq_type = {
typename: "none",
- startup: noirq_startup,
- shutdown: noirq_enable_disable,
- enable: noirq_enable_disable,
- disable: noirq_enable_disable,
- ack: noirq_ack,
- end: noirq_enable_disable,
-};
-
-/*
- * The special RTC interrupt type. The interrupt itself was
- * processed by PALcode, and comes in via entInt vector 1.
- */
-
-static struct hw_interrupt_type rtc_irq_type = {
- typename: "RTC",
- startup: noirq_startup,
- shutdown: noirq_enable_disable,
- enable: noirq_enable_disable,
- disable: noirq_enable_disable,
- ack: noirq_enable_disable,
- end: noirq_enable_disable,
-};
-
-void __init
-init_rtc_irq(void)
-{
- irq_desc[RTC_IRQ].status = IRQ_DISABLED;
- irq_desc[RTC_IRQ].handler = &rtc_irq_type;
-}
-
-/*
- * Special irq handlers.
- */
-
-void
-no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-}
-
-/*
- * Common irq handlers.
- */
-
-struct irqaction isa_cascade_irqaction = {
- handler: no_action,
- name: "isa-cascade"
-};
-
-struct irqaction timer_cascade_irqaction = {
- handler: no_action,
- name: "timer-cascade"
-};
-
-struct irqaction halt_switch_irqaction = {
- handler: no_action,
- name: "halt-switch"
-};
-
-
-spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
- [0 ... NR_IRQS-1] = { 0, &no_irq_type, }
+ startup: no_irq_startup,
+ shutdown: no_irq_enable_disable,
+ enable: no_irq_enable_disable,
+ disable: no_irq_enable_disable,
+ ack: no_irq_ack,
+ end: no_irq_enable_disable,
};
int
handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
struct irqaction *action)
{
- int status, cpu = smp_processor_id();
- int old_ipl, ipl;
+ int status;
+ int cpu = smp_processor_id();
kstat.irqs[cpu][irq]++;
irq_enter(cpu, irq);
status = 1; /* Force the "do bottom halves" bit */
- old_ipl = ipl = getipl();
do {
- int new_ipl = IPL_MIN;
- if (action->flags & SA_INTERRUPT)
- new_ipl = IPL_MAX;
- if (new_ipl != ipl) {
- setipl(new_ipl);
- ipl = new_ipl;
- }
+ if (!(action->flags & SA_INTERRUPT))
+ __sti();
+ else
+ __cli();
status |= action->flags;
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- if (ipl != old_ipl)
- setipl(old_ipl);
-
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
+ __cli();
+
irq_exit(cpu, irq);
return status;
@@ -326,17 +107,18 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
* hardware disable after having gotten the irq
* controller lock.
*/
-void
+void inline
disable_irq_nosync(unsigned int irq)
{
+ irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
- spin_lock_irqsave(&irq_controller_lock, flags);
- if (!irq_desc[irq].depth++) {
- irq_desc[irq].status |= IRQ_DISABLED | IRQ_MASKED;
- irq_desc[irq].handler->disable(irq);
+ spin_lock_irqsave(&desc->lock, flags);
+ if (!desc->depth++) {
+ desc->status |= IRQ_DISABLED;
+ desc->handler->disable(irq);
}
- spin_unlock_irqrestore(&irq_controller_lock, flags);
+ spin_unlock_irqrestore(&desc->lock, flags);
}
/*
@@ -358,32 +140,29 @@ disable_irq(unsigned int irq)
void
enable_irq(unsigned int irq)
{
+ irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
- spin_lock_irqsave(&irq_controller_lock, flags);
- switch (irq_desc[irq].depth) {
- case 1:
- {
- unsigned int status = irq_desc[irq].status;
-
- status &= ~(IRQ_DISABLED | IRQ_MASKED);
+ spin_lock_irqsave(&desc->lock, flags);
+ switch (desc->depth) {
+ case 1: {
+ unsigned int status = desc->status & ~IRQ_DISABLED;
+ desc->status = status;
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
- status |= IRQ_REPLAY;
- /* ??? We can't re-send on (most?) alpha hw.
- hw_resend_irq(irq_desc[irq].handler,irq); */
+ desc->status = status | IRQ_REPLAY;
+ hw_resend_irq(desc->handler,irq);
}
- irq_desc[irq].status = status;
- irq_desc[irq].handler->enable(irq);
+ desc->handler->enable(irq);
/* fall-through */
- }
+ }
default:
- irq_desc[irq].depth--;
+ desc->depth--;
break;
case 0:
printk(KERN_ERR "enable_irq() unbalanced from %p\n",
__builtin_return_address(0));
}
- spin_unlock_irqrestore(&irq_controller_lock, flags);
+ spin_unlock_irqrestore(&desc->lock, flags);
}
int
@@ -392,6 +171,7 @@ setup_irq(unsigned int irq, struct irqaction * new)
int shared = 0;
struct irqaction *old, **p;
unsigned long flags;
+ irq_desc_t *desc = irq_desc + irq;
/*
* Some drivers like serial.c use request_irq() heavily,
@@ -413,12 +193,12 @@ setup_irq(unsigned int irq, struct irqaction * new)
/*
* The following block of code has to be executed atomically
*/
- spin_lock_irqsave(&irq_controller_lock,flags);
- p = &irq_desc[irq].action;
+ spin_lock_irqsave(&desc->lock,flags);
+ p = &desc->action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
if (!(old->flags & new->flags & SA_SHIRQ)) {
- spin_unlock_irqrestore(&irq_controller_lock,flags);
+ spin_unlock_irqrestore(&desc->lock,flags);
return -EBUSY;
}
@@ -433,14 +213,181 @@ setup_irq(unsigned int irq, struct irqaction * new)
*p = new;
if (!shared) {
- irq_desc[irq].depth = 0;
- irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_MASKED);
- irq_desc[irq].handler->startup(irq);
+ desc->depth = 0;
+ desc->status &= ~IRQ_DISABLED;
+ desc->handler->startup(irq);
}
- spin_unlock_irqrestore(&irq_controller_lock,flags);
+ 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 unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+
+#define HEX_DIGITS 16
+
+static int
+irq_affinity_read_proc (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ if (count < HEX_DIGITS+1)
+ return -EINVAL;
+ return sprintf (page, "%016lx\n", irq_affinity[(long)data]);
+}
+
+static unsigned int
+parse_hex_value (const char *buffer,
+ unsigned long count, unsigned long *ret)
+{
+ unsigned char hexnum [HEX_DIGITS];
+ unsigned long value;
+ int i;
+
+ if (!count)
+ return -EINVAL;
+ if (count > HEX_DIGITS)
+ count = HEX_DIGITS;
+ if (copy_from_user(hexnum, buffer, count))
+ return -EFAULT;
+
+ /*
+ * Parse the first 8 characters as a hex string, any non-hex char
+ * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
+ */
+ value = 0;
+
+ for (i = 0; i < count; i++) {
+ unsigned int c = hexnum[i];
+
+ switch (c) {
+ case '0' ... '9': c -= '0'; break;
+ case 'a' ... 'f': c -= 'a'-10; break;
+ case 'A' ... 'F': c -= 'A'-10; break;
+ default:
+ goto out;
+ }
+ value = (value << 4) | c;
+ }
+out:
+ *ret = value;
+ return 0;
+}
+
+static int
+irq_affinity_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int irq = (long) data, full_count = count, err;
+ unsigned long new_value;
+
+ if (!irq_desc[irq].handler->set_affinity)
+ return -EIO;
+
+ 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))
+ return -EINVAL;
+#endif
+
+ irq_affinity[irq] = new_value;
+ irq_desc[irq].handler->set_affinity(irq, new_value);
+
+ return full_count;
+}
+
+static int
+prof_cpu_mask_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ unsigned long *mask = (unsigned long *) data;
+ if (count < HEX_DIGITS+1)
+ return -EINVAL;
+ return sprintf (page, "%08lx\n", *mask);
+}
+
+static int
+prof_cpu_mask_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ unsigned long *mask = (unsigned long *) data, full_count = count, err;
+ unsigned long new_value;
+
+ err = parse_hex_value(buffer, count, &new_value);
+ if (err)
+ return err;
+
+ *mask = new_value;
+ return full_count;
+}
+
+#define MAX_NAMELEN 10
+
+static void
+register_irq_proc (unsigned int irq)
+{
+ struct proc_dir_entry *entry;
+ char name [MAX_NAMELEN];
+
+ if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
+ return;
+
+ memset(name, 0, MAX_NAMELEN);
+ sprintf(name, "%d", irq);
+
+ /* create /proc/irq/1234 */
+ irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+
+ /* create /proc/irq/1234/smp_affinity */
+ entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
+
+ entry->nlink = 1;
+ entry->data = (void *)(long)irq;
+ entry->read_proc = irq_affinity_read_proc;
+ entry->write_proc = irq_affinity_write_proc;
+
+ smp_affinity_entry[irq] = entry;
+}
+
+unsigned long prof_cpu_mask = ~0UL;
+
+void
+init_irq_proc (void)
+{
+ struct proc_dir_entry *entry;
+ int i;
+
+ /* create /proc/irq */
+ root_irq_dir = proc_mkdir("irq", 0);
+
+ /* create /proc/irq/prof_cpu_mask */
+ entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
+
+ entry->nlink = 1;
+ entry->data = (void *)&prof_cpu_mask;
+ entry->read_proc = prof_cpu_mask_read_proc;
+ entry->write_proc = prof_cpu_mask_write_proc;
+
+ /*
+ * Create entries for all existing IRQs.
+ */
+ for (i = 0; i < NR_IRQS; i++) {
+ if (irq_desc[i].handler == &no_irq_type)
+ continue;
+ register_irq_proc(i);
+ }
+}
+
int
request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
@@ -488,6 +435,7 @@ request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
void
free_irq(unsigned int irq, void *dev_id)
{
+ irq_desc_t *desc;
struct irqaction **p;
unsigned long flags;
@@ -496,8 +444,9 @@ free_irq(unsigned int irq, void *dev_id)
return;
}
- spin_lock_irqsave(&irq_controller_lock,flags);
- p = &irq_desc[irq].action;
+ desc = irq_desc + irq;
+ spin_lock_irqsave(&desc->lock,flags);
+ p = &desc->action;
for (;;) {
struct irqaction * action = *p;
if (action) {
@@ -508,26 +457,29 @@ free_irq(unsigned int irq, void *dev_id)
/* Found - now remove it from the list of entries. */
*pp = action->next;
- if (!irq_desc[irq].action) {
- irq_desc[irq].status |= IRQ_DISABLED|IRQ_MASKED;
- irq_desc[irq].handler->shutdown(irq);
+ if (!desc->action) {
+ desc->status |= IRQ_DISABLED;
+ desc->handler->shutdown(irq);
}
- spin_unlock_irqrestore(&irq_controller_lock,flags);
+ spin_unlock_irqrestore(&desc->lock,flags);
+#ifdef CONFIG_SMP
/* Wait to make sure it's not being used on
another CPU. */
- while (irq_desc[irq].status & IRQ_INPROGRESS)
+ while (desc->status & IRQ_INPROGRESS)
barrier();
+#endif
kfree(action);
return;
}
printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
- spin_unlock_irqrestore(&irq_controller_lock,flags);
+ spin_unlock_irqrestore(&desc->lock,flags);
return;
}
}
-int get_irq_list(char *buf)
+int
+get_irq_list(char *buf)
{
int i, j;
struct irqaction * action;
@@ -576,246 +528,10 @@ int get_irq_list(char *buf)
cpu_data[cpu_logical_map(j)].smp_local_irq_count);
p += sprintf(p, "\n");
#endif
+ p += sprintf(p, "ERR: %10lu\n", irq_err_count);
return p - buf;
}
-#ifdef CONFIG_SMP
-/* Who has global_irq_lock. */
-int global_irq_holder = NO_PROC_ID;
-
-/* This protects IRQ's. */
-spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
-
-/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT(0);
-
-static void *previous_irqholder = NULL;
-
-#define MAXCOUNT 100000000
-
-static void show(char * str, void *where);
-
-static inline void
-wait_on_irq(int cpu, void *where)
-{
- int count = MAXCOUNT;
-
- for (;;) {
-
- /*
- * Wait until all interrupts are gone. Wait
- * for bottom half handlers unless we're
- * already executing in one..
- */
- if (!atomic_read(&global_irq_count)) {
- if (local_bh_count(cpu)
- || !spin_is_locked(&global_bh_lock))
- break;
- }
-
- /* Duh, we have to loop. Release the lock to avoid deadlocks */
- spin_unlock(&global_irq_lock);
-
- for (;;) {
- if (!--count) {
- show("wait_on_irq", where);
- count = MAXCOUNT;
- }
- __sti();
- udelay(1); /* make sure to run pending irqs */
- __cli();
-
- if (atomic_read(&global_irq_count))
- continue;
- if (spin_is_locked(&global_irq_lock))
- continue;
- if (!local_bh_count(cpu)
- && spin_is_locked(&global_bh_lock))
- continue;
- if (spin_trylock(&global_irq_lock))
- break;
- }
- }
-}
-
-static inline void
-get_irqlock(int cpu, void* where)
-{
- if (!spin_trylock(&global_irq_lock)) {
- /* Do we already hold the lock? */
- if (cpu == global_irq_holder)
- return;
- /* Uhhuh.. Somebody else got it. Wait. */
- spin_lock(&global_irq_lock);
- }
-
- /*
- * Ok, we got the lock bit.
- * But that's actually just the easy part.. Now
- * we need to make sure that nobody else is running
- * in an interrupt context.
- */
- wait_on_irq(cpu, where);
-
- /*
- * Finally.
- */
-#if DEBUG_SPINLOCK
- global_irq_lock.task = current;
- global_irq_lock.previous = where;
-#endif
- global_irq_holder = cpu;
- previous_irqholder = where;
-}
-
-void
-__global_cli(void)
-{
- int cpu = smp_processor_id();
- void *where = __builtin_return_address(0);
-
- /*
- * Maximize ipl. If ipl was previously 0 and if this thread
- * is not in an irq, then take global_irq_lock.
- */
- if (swpipl(IPL_MAX) == IPL_MIN && !local_irq_count(cpu))
- get_irqlock(cpu, where);
-}
-
-void
-__global_sti(void)
-{
- int cpu = smp_processor_id();
-
- if (!local_irq_count(cpu))
- release_irqlock(cpu);
- __sti();
-}
-
-/*
- * SMP flags value to restore to:
- * 0 - global cli
- * 1 - global sti
- * 2 - local cli
- * 3 - local sti
- */
-unsigned long
-__global_save_flags(void)
-{
- int retval;
- int local_enabled;
- unsigned long flags;
- int cpu = smp_processor_id();
-
- __save_flags(flags);
- local_enabled = (!(flags & 7));
- /* default to local */
- retval = 2 + local_enabled;
-
- /* Check for global flags if we're not in an interrupt. */
- if (!local_irq_count(cpu)) {
- if (local_enabled)
- retval = 1;
- if (global_irq_holder == cpu)
- retval = 0;
- }
- return retval;
-}
-
-void
-__global_restore_flags(unsigned long flags)
-{
- switch (flags) {
- case 0:
- __global_cli();
- break;
- case 1:
- __global_sti();
- break;
- case 2:
- __cli();
- break;
- case 3:
- __sti();
- break;
- default:
- printk(KERN_ERR "global_restore_flags: %08lx (%p)\n",
- flags, __builtin_return_address(0));
- }
-}
-
-static void
-show(char * str, void *where)
-{
-#if 0
- int i;
- unsigned long *stack;
-#endif
- int cpu = smp_processor_id();
-
- printk("\n%s, CPU %d: %p\n", str, cpu, where);
- printk("irq: %d [%d %d]\n",
- atomic_read(&global_irq_count),
- cpu_data[0].irq_count,
- cpu_data[1].irq_count);
-
- printk("bh: %d [%d %d]\n",
- spin_is_locked(&global_bh_lock) ? 1 : 0,
- cpu_data[0].bh_count,
- cpu_data[1].bh_count);
-#if 0
- stack = (unsigned long *) &str;
- for (i = 40; i ; i--) {
- unsigned long x = *++stack;
- if (x > (unsigned long) &init_task_union &&
- x < (unsigned long) &vsprintf) {
- printk("<[%08lx]> ", x);
- }
- }
-#endif
-}
-
-/*
- * From its use, I infer that synchronize_irq() stalls a thread until
- * the effects of a command to an external device are known to have
- * taken hold. Typically, the command is to stop sending interrupts.
- * The strategy here is wait until there is at most one processor
- * (this one) in an irq. The memory barrier serializes the write to
- * the device and the subsequent accesses of global_irq_count.
- * --jmartin
- */
-#define DEBUG_SYNCHRONIZE_IRQ 0
-
-void
-synchronize_irq(void)
-{
-#if 0
- /* Joe's version. */
- int cpu = smp_processor_id();
- int local_count;
- int global_count;
- int countdown = 1<<24;
- void *where = __builtin_return_address(0);
-
- mb();
- do {
- local_count = local_irq_count(cpu);
- global_count = atomic_read(&global_irq_count);
- if (DEBUG_SYNCHRONIZE_IRQ && (--countdown == 0)) {
- printk("%d:%d/%d\n", cpu, local_count, global_count);
- show("synchronize_irq", where);
- break;
- }
- } while (global_count != local_count);
-#else
- /* Jay's version. */
- if (atomic_read(&global_irq_count)) {
- cli();
- sti();
- }
-#endif
-}
-#endif /* CONFIG_SMP */
/*
* do_IRQ handles all normal device IRQ's (the special
@@ -836,39 +552,26 @@ handle_irq(int irq, struct pt_regs * regs)
* handled by some other CPU. (or is disabled)
*/
int cpu = smp_processor_id();
- irq_desc_t *desc;
+ irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
if ((unsigned) irq > ACTUAL_NR_IRQS) {
+ irq_err_count++;
printk(KERN_CRIT "device_interrupt: illegal interrupt %d\n",
irq);
return;
}
irq_attempt(cpu, irq)++;
- desc = irq_desc + irq;
- spin_lock_irq(&irq_controller_lock); /* mask also the RTC */
+ spin_lock_irq(&desc->lock); /* mask also the higher prio events */
desc->handler->ack(irq);
- status = desc->status;
-
-#ifndef CONFIG_SMP
- /* Look for broken irq masking. */
- if (status & IRQ_MASKED) {
- static unsigned long last_printed;
- if (time_after(jiffies, last_printed+HZ)) {
- printk(KERN_CRIT "Mask didn't work for irq %d!\n", irq);
- last_printed = jiffies;
- }
- }
-#endif
-
/*
* REPLAY is when Linux resends an IRQ that was dropped earlier.
* WAITING is used by probe to mark irqs that are being tested.
*/
- status &= ~(IRQ_REPLAY | IRQ_WAITING);
- status |= IRQ_PENDING | IRQ_MASKED; /* we _want_ to handle it */
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+ status |= IRQ_PENDING; /* we _want_ to handle it */
/*
* If the IRQ is disabled for whatever reason, we cannot
@@ -881,7 +584,6 @@ handle_irq(int irq, struct pt_regs * regs)
status |= IRQ_INPROGRESS; /* we are handling it */
}
desc->status = status;
- spin_unlock(&irq_controller_lock);
/*
* If there is no IRQ handler or it was disabled, exit early.
@@ -890,7 +592,7 @@ handle_irq(int irq, struct pt_regs * regs)
* will take care of it.
*/
if (!action)
- return;
+ goto out;
/*
* Edge triggered interrupts need to remember pending events.
@@ -902,22 +604,23 @@ handle_irq(int irq, struct pt_regs * regs)
* SMP environment.
*/
for (;;) {
+ spin_unlock(&desc->lock);
handle_IRQ_event(irq, regs, action);
- spin_lock(&irq_controller_lock);
+ spin_lock(&desc->lock);
if (!(desc->status & IRQ_PENDING)
|| (desc->status & IRQ_LEVEL))
break;
desc->status &= ~IRQ_PENDING;
- spin_unlock(&irq_controller_lock);
- }
- status = desc->status & ~IRQ_INPROGRESS;
- if (!(status & IRQ_DISABLED)) {
- status &= ~IRQ_MASKED;
- desc->handler->end(irq);
}
- desc->status = status;
- spin_unlock(&irq_controller_lock);
+ desc->status &= ~IRQ_INPROGRESS;
+out:
+ /*
+ * The ->end() handler has to deal with interrupts which got
+ * disabled while the handler was running.
+ */
+ desc->handler->end(irq);
+ spin_unlock(&desc->lock);
}
/*
@@ -932,17 +635,20 @@ unsigned long
probe_irq_on(void)
{
int i;
+ irq_desc_t *desc;
unsigned long delay;
unsigned long val;
/* Something may have generated an irq long ago and we want to
flush such a longstanding irq before considering it as spurious. */
- spin_lock_irq(&irq_controller_lock);
- for (i = NR_IRQS-1; i >= 0; i--)
+ for (i = NR_IRQS-1; i >= 0; i--) {
+ desc = irq_desc + i;
+
+ spin_lock_irq(&desc->lock);
if (!irq_desc[i].action)
- if(irq_desc[i].handler->startup(i))
- irq_desc[i].status |= IRQ_PENDING;
- spin_unlock_irq(&irq_controller_lock);
+ irq_desc[i].handler->startup(i);
+ spin_unlock_irq(&desc->lock);
+ }
/* Wait for longstanding interrupts to trigger. */
for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
@@ -951,15 +657,17 @@ probe_irq_on(void)
/* enable any unassigned irqs (we must startup again here because
if a longstanding irq happened in the previous stage, it may have
masked itself) first, enable any unassigned irqs. */
- spin_lock_irq(&irq_controller_lock);
for (i = NR_IRQS-1; i >= 0; i--) {
- if (!irq_desc[i].action) {
- irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
- if(irq_desc[i].handler->startup(i))
- irq_desc[i].status |= IRQ_PENDING;
+ desc = irq_desc + i;
+
+ spin_lock_irq(&desc->lock);
+ if (!desc->action) {
+ desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+ if (desc->handler->startup(i))
+ desc->status |= IRQ_PENDING;
}
+ spin_unlock_irq(&desc->lock);
}
- spin_unlock_irq(&irq_controller_lock);
/*
* Wait for spurious interrupts to trigger
@@ -971,24 +679,24 @@ probe_irq_on(void)
* Now filter out any obviously spurious interrupts
*/
val = 0;
- spin_lock_irq(&irq_controller_lock);
for (i=0; i<NR_IRQS; i++) {
- unsigned int status = irq_desc[i].status;
-
- if (!(status & IRQ_AUTODETECT))
- continue;
-
- /* It triggered already - consider it spurious. */
- if (!(status & IRQ_WAITING)) {
- irq_desc[i].status = status & ~IRQ_AUTODETECT;
- irq_desc[i].handler->shutdown(i);
- continue;
+ irq_desc_t *desc = irq_desc + i;
+ unsigned int status;
+
+ spin_lock_irq(&desc->lock);
+ status = desc->status;
+
+ if (status & IRQ_AUTODETECT) {
+ /* It triggered already - consider it spurious. */
+ if (!(status & IRQ_WAITING)) {
+ desc->status = status & ~IRQ_AUTODETECT;
+ desc->handler->shutdown(i);
+ } else
+ if (i < 32)
+ val |= 1 << i;
}
-
- if (i < 64)
- val |= 1 << i;
+ spin_unlock_irq(&desc->lock);
}
- spin_unlock_irq(&irq_controller_lock);
return val;
}
@@ -997,26 +705,29 @@ probe_irq_on(void)
* Return a mask of triggered interrupts (this
* can handle only legacy ISA interrupts).
*/
-unsigned int probe_irq_mask(unsigned long val)
+unsigned int
+probe_irq_mask(unsigned long val)
{
int i;
unsigned int mask;
mask = 0;
- spin_lock_irq(&irq_controller_lock);
for (i = 0; i < 16; i++) {
- unsigned int status = irq_desc[i].status;
+ irq_desc_t *desc = irq_desc + i;
+ unsigned int status;
- if (!(status & IRQ_AUTODETECT))
- continue;
+ spin_lock_irq(&desc->lock);
+ status = desc->status;
- if (!(status & IRQ_WAITING))
- mask |= 1 << i;
+ if (status & IRQ_AUTODETECT) {
+ if (!(status & IRQ_WAITING))
+ mask |= 1 << i;
- irq_desc[i].status = status & ~IRQ_AUTODETECT;
- irq_desc[i].handler->shutdown(i);
+ desc->status = status & ~IRQ_AUTODETECT;
+ desc->handler->shutdown(i);
+ }
+ spin_unlock_irq(&desc->lock);
}
- spin_unlock_irq(&irq_controller_lock);
return mask & val;
}
@@ -1034,183 +745,26 @@ probe_irq_off(unsigned long val)
nr_irqs = 0;
irq_found = 0;
- spin_lock_irq(&irq_controller_lock);
for (i=0; i<NR_IRQS; i++) {
- unsigned int status = irq_desc[i].status;
+ irq_desc_t *desc = irq_desc + i;
+ unsigned int status;
- if (!(status & IRQ_AUTODETECT))
- continue;
+ spin_lock_irq(&desc->lock);
+ status = desc->status;
- if (!(status & IRQ_WAITING)) {
- if (!nr_irqs)
- irq_found = i;
- nr_irqs++;
+ if (status & IRQ_AUTODETECT) {
+ if (!(status & IRQ_WAITING)) {
+ if (!nr_irqs)
+ irq_found = i;
+ nr_irqs++;
+ }
+ desc->status = status & ~IRQ_AUTODETECT;
+ desc->handler->shutdown(i);
}
- irq_desc[i].status = status & ~IRQ_AUTODETECT;
- irq_desc[i].handler->shutdown(i);
+ spin_unlock_irq(&desc->lock);
}
- spin_unlock_irq(&irq_controller_lock);
if (nr_irqs > 1)
irq_found = -irq_found;
return irq_found;
}
-
-
-/*
- * The main interrupt entry point.
- */
-
-asmlinkage void
-do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs regs)
-{
- switch (type) {
- case 0:
-#ifdef CONFIG_SMP
- handle_ipi(&regs);
- return;
-#else
- printk(KERN_CRIT "Interprocessor interrupt? "
- "You must be kidding!\n");
-#endif
- break;
- case 1:
-#ifdef CONFIG_SMP
- cpu_data[smp_processor_id()].smp_local_irq_count++;
- smp_percpu_timer_interrupt(&regs);
- if (smp_processor_id() == boot_cpuid)
-#endif
- handle_irq(RTC_IRQ, &regs);
- return;
- case 2:
- alpha_mv.machine_check(vector, la_ptr, &regs);
- return;
- case 3:
- alpha_mv.device_interrupt(vector, &regs);
- return;
- case 4:
- perf_irq(vector, &regs);
- return;
- default:
- printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
- type, vector);
- }
- printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
-}
-
-void __init
-common_init_isa_dma(void)
-{
- outb(0, DMA1_RESET_REG);
- outb(0, DMA2_RESET_REG);
- outb(0, DMA1_CLR_MASK_REG);
- outb(0, DMA2_CLR_MASK_REG);
-}
-
-void __init
-init_IRQ(void)
-{
- wrent(entInt, 0);
- alpha_mv.init_irq();
-}
-
-
-/*
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_OS_BUGCHECK 0x008A
-#define MCHK_K_PAL_BUGCHECK 0x0090
-
-#ifndef CONFIG_SMP
-struct mcheck_info __mcheck_info;
-#endif
-
-void
-process_mcheck_info(unsigned long vector, unsigned long la_ptr,
- struct pt_regs *regs, const char *machine,
- int expected)
-{
- struct el_common *mchk_header;
- const char *reason;
-
- /*
- * See if the machine check is due to a badaddr() and if so,
- * ignore it.
- */
-
-#if DEBUG_MCHECK > 0
- printk(KERN_CRIT "%s machine check %s\n", machine,
- expected ? "expected." : "NOT expected!!!");
-#endif
-
- if (expected) {
- int cpu = smp_processor_id();
- mcheck_expected(cpu) = 0;
- mcheck_taken(cpu) = 1;
- return;
- }
-
- mchk_header = (struct el_common *)la_ptr;
-
- printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%lx\n",
- machine, vector, regs->pc, mchk_header->code);
-
- switch ((unsigned int) mchk_header->code) {
- /* Machine check reasons. Defined according to PALcode sources. */
- case 0x80: reason = "tag parity error"; break;
- case 0x82: reason = "tag control parity error"; break;
- case 0x84: reason = "generic hard error"; break;
- case 0x86: reason = "correctable ECC error"; break;
- case 0x88: reason = "uncorrectable ECC error"; break;
- case 0x8A: reason = "OS-specific PAL bugcheck"; break;
- case 0x90: reason = "callsys in kernel mode"; break;
- case 0x96: reason = "i-cache read retryable error"; break;
- case 0x98: reason = "processor detected hard error"; break;
-
- /* System specific (these are for Alcor, at least): */
- case 0x202: reason = "system detected hard error"; break;
- case 0x203: reason = "system detected uncorrectable ECC error"; break;
- case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
- case 0x205: reason = "parity error detected by CIA"; break;
- case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break;
- case 0x207: reason = "non-existent memory error"; break;
- case 0x208: reason = "MCHK_K_DCSR"; break;
- case 0x209: reason = "PCI SERR detected"; break;
- case 0x20b: reason = "PCI data parity error detected"; break;
- case 0x20d: reason = "PCI address parity error detected"; break;
- case 0x20f: reason = "PCI master abort error"; break;
- case 0x211: reason = "PCI target abort error"; break;
- case 0x213: reason = "scatter/gather PTE invalid error"; break;
- case 0x215: reason = "flash ROM write error"; break;
- case 0x217: reason = "IOA timeout detected"; break;
- case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
- case 0x21b: reason = "EISA fail-safe timer timeout"; break;
- case 0x21d: reason = "EISA bus time-out"; break;
- case 0x21f: reason = "EISA software generated NMI"; break;
- case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
- default: reason = "unknown"; break;
- }
-
- printk(KERN_CRIT "machine check type: %s%s\n",
- reason, mchk_header->retry ? " (retryable)" : "");
-
- dik_show_regs(regs, NULL);
-
-#if DEBUG_MCHECK > 1
- {
- /* Dump the logout area to give all info. */
- unsigned long *ptr = (unsigned long *)la_ptr;
- long i;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
- }
-#endif
-}
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
index ff8067a00..9818476f2 100644
--- a/arch/alpha/kernel/irq_impl.h
+++ b/arch/alpha/kernel/irq_impl.h
@@ -19,6 +19,7 @@ extern void isa_no_iack_sc_device_interrupt(unsigned long, struct pt_regs *);
extern void srm_device_interrupt(unsigned long, struct pt_regs *);
extern void pyxis_device_interrupt(unsigned long, struct pt_regs *);
+extern struct irqaction timer_irqaction;
extern struct irqaction isa_cascade_irqaction;
extern struct irqaction timer_cascade_irqaction;
extern struct irqaction halt_switch_irqaction;
@@ -33,27 +34,37 @@ extern void i8259a_enable_irq(unsigned int);
extern void i8259a_disable_irq(unsigned int);
extern void i8259a_mask_and_ack_irq(unsigned int);
extern unsigned int i8259a_startup_irq(unsigned int);
+extern void i8259a_end_irq(unsigned int);
extern struct hw_interrupt_type i8259a_irq_type;
extern void init_i8259a_irqs(void);
-extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
extern void handle_irq(int irq, struct pt_regs * regs);
+extern unsigned long prof_cpu_mask;
+
static inline void
alpha_do_profile(unsigned long pc)
{
- if (prof_buffer && current->pid) {
- extern char _stext;
-
- pc -= (unsigned long) &_stext;
- pc >>= prof_shift;
- /*
- * Don't ignore out-of-bounds PC values silently,
- * put them into the last histogram slot, so if
- * present, they will show up as a sharp peak.
- */
- if (pc > prof_len - 1)
- pc = prof_len - 1;
- atomic_inc((atomic_t *)&prof_buffer[pc]);
- }
+ extern char _stext;
+
+ if (!prof_buffer)
+ return;
+
+ /*
+ * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
+ * (default is all CPUs.)
+ */
+ if (!((1<<smp_processor_id()) & prof_cpu_mask))
+ return;
+
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+ /*
+ * Don't ignore out-of-bounds PC values silently,
+ * put them into the last histogram slot, so if
+ * present, they will show up as a sharp peak.
+ */
+ if (pc > prof_len - 1)
+ pc = prof_len - 1;
+ atomic_inc((atomic_t *)&prof_buffer[pc]);
}
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 421591104..cc55781cb 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -44,7 +44,6 @@
mv_switch_mm: ev4_switch_mm, \
mv_activate_mm: ev4_activate_mm, \
mv_flush_tlb_current: ev4_flush_tlb_current, \
- mv_flush_tlb_other: ev4_flush_tlb_other, \
mv_flush_tlb_current_page: ev4_flush_tlb_current_page
#define DO_EV5_MMU \
@@ -52,7 +51,6 @@
mv_switch_mm: ev5_switch_mm, \
mv_activate_mm: ev5_activate_mm, \
mv_flush_tlb_current: ev5_flush_tlb_current, \
- mv_flush_tlb_other: ev5_flush_tlb_other, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page
#define DO_EV6_MMU \
@@ -60,7 +58,6 @@
mv_switch_mm: ev5_switch_mm, \
mv_activate_mm: ev5_activate_mm, \
mv_flush_tlb_current: ev5_flush_tlb_current, \
- mv_flush_tlb_other: ev5_flush_tlb_other, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page
#define IO_LITE(UP,low) \
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index f91978732..3aee6ec34 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -123,6 +123,24 @@ static inline u8 bridge_swizzle(u8 pin, u8 slot)
_ctl_; })
+/* A PCI IOMMU allocation arena. There are typically two of these
+ regions per bus. */
+/* ??? The 8400 has a 32-byte pte entry, and the entire table apparently
+ lives directly on the host bridge (no tlb?). We don't support this
+ machine, but if we ever did, we'd need to parameterize all this quite
+ a bit further. Probably with per-bus operation tables. */
+
+struct pci_iommu_arena
+{
+ spinlock_t lock;
+ struct pci_controler *hose;
+ unsigned long *ptes;
+ dma_addr_t dma_base;
+ unsigned int size;
+ unsigned int next_entry;
+};
+
+
/* The hose list. */
extern struct pci_controler *hose_head, **hose_tail;
extern struct pci_controler *pci_isa_hose;
@@ -132,8 +150,9 @@ extern u8 common_swizzle(struct pci_dev *, u8 *);
extern struct pci_controler *alloc_pci_controler(void);
extern struct resource *alloc_resource(void);
-extern struct pci_iommu_arena *iommu_arena_new(dma_addr_t, unsigned long,
- unsigned long);
+extern struct pci_iommu_arena *iommu_arena_new(struct pci_controler *,
+ dma_addr_t, unsigned long,
+ unsigned long);
extern long iommu_arena_alloc(struct pci_iommu_arena *arena, long n);
extern const char *const pci_io_names[];
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index f5a9bd990..9e7e13e9b 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -27,6 +27,8 @@
# define DBGA2(args...)
#endif
+#define DEBUG_NODIRECT 0
+
static inline unsigned long
mk_iommu_pte(unsigned long paddr)
@@ -41,23 +43,29 @@ calc_npages(long bytes)
}
struct pci_iommu_arena *
-iommu_arena_new(dma_addr_t base, unsigned long window_size,
- unsigned long align)
+iommu_arena_new(struct pci_controler *hose, dma_addr_t base,
+ unsigned long window_size, unsigned long align)
{
- unsigned long entries, mem_size, mem_pages;
+ unsigned long mem_size;
struct pci_iommu_arena *arena;
- entries = window_size >> PAGE_SHIFT;
- mem_size = entries * sizeof(unsigned long);
- mem_pages = calc_npages(mem_size);
+ mem_size = window_size / (PAGE_SIZE / sizeof(unsigned long));
+
+ /* Note that the TLB lookup logic uses bitwise concatenation,
+ not addition, so the required arena alignment is based on
+ the size of the window. Retain the align parameter so that
+ particular systems can over-align the arena. */
+ if (align < mem_size)
+ align = mem_size;
arena = alloc_bootmem(sizeof(*arena));
- arena->ptes = __alloc_bootmem(mem_pages * PAGE_SIZE, align, 0);
+ arena->ptes = __alloc_bootmem(mem_size, align, 0);
spin_lock_init(&arena->lock);
+ arena->hose = hose;
arena->dma_base = base;
arena->size = window_size;
- arena->alloc_hint = 0;
+ arena->next_entry = 0;
return arena;
}
@@ -74,20 +82,22 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
/* Search forward for the first sequence of N empty ptes. */
beg = arena->ptes;
end = beg + (arena->size >> PAGE_SHIFT);
- p = beg + arena->alloc_hint;
+ p = beg + arena->next_entry;
i = 0;
while (i < n && p < end)
i = (*p++ == 0 ? i + 1 : 0);
- if (p >= end) {
- /* Failure. Assume the hint was wrong and go back to
+ 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);
- if (p >= end) {
+ if (i < n) {
spin_unlock_irqrestore(&arena->lock, flags);
return -1;
}
@@ -100,7 +110,7 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
for (p = p - n, i = 0; i < n; ++i)
p[i] = ~1UL;
- arena->alloc_hint = p - beg + n;
+ arena->next_entry = p - beg + n;
spin_unlock_irqrestore(&arena->lock, flags);
return p - beg;
@@ -115,7 +125,6 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
p = arena->ptes + ofs;
for (i = 0; i < n; ++i)
p[i] = 0;
- arena->alloc_hint = ofs;
}
/* Map a single buffer of the indicate size for PCI DMA in streaming
@@ -138,6 +147,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction)
paddr = virt_to_phys(cpu_addr);
+#if !DEBUG_NODIRECT
/* First check to see if we can use the direct map window. */
if (paddr + size + __direct_map_base - 1 <= max_dma
&& paddr + size <= __direct_map_size) {
@@ -148,6 +158,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction)
return ret;
}
+#endif
/* If the machine doesn't define a pci_tbi routine, we have to
assume it doesn't support sg mapping. */
@@ -199,6 +210,7 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
if (direction == PCI_DMA_NONE)
BUG();
+#if !DEBUG_NODIRECT
if (dma_addr >= __direct_map_base
&& dma_addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
@@ -208,6 +220,7 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
return;
}
+#endif
arena = hose->sg_pci;
if (!arena || dma_addr < arena->dma_base)
@@ -224,10 +237,9 @@ 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);
- alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
- DBGA2("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
- dma_addr, size, npages, __builtin_return_address(0));
+ DBGA("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
+ dma_addr, size, npages, __builtin_return_address(0));
}
@@ -347,6 +359,7 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
unsigned long *ptes;
long npages, dma_ofs, i;
+#if !DEBUG_NODIRECT
/* If everything is physically contiguous, and the addresses
fall into the direct-map window, use it. */
if (leader->dma_address == 0
@@ -360,6 +373,7 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
return 0;
}
+#endif
/* Otherwise, we'll use the iommu to make the pages virtually
contiguous. */
@@ -376,56 +390,38 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
DBGA(" sg_fill: [%p,%lx] -> sg %x np %ld\n",
leader->address, size, out->dma_address, npages);
+ /* All virtually contiguous. We need to find the length of each
+ physically contiguous subsegment to fill in the ptes. */
ptes = &arena->ptes[dma_ofs];
sg = leader;
- if (0 && leader->dma_address == 0) {
- /* All physically contiguous. We already have the
- length, all we need is to fill in the ptes. */
-
- paddr = virt_to_phys(sg->address) & PAGE_MASK;
- for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
- *ptes++ = mk_iommu_pte(paddr);
-
-#if DEBUG_ALLOC > 0
- DBGA(" (0) [%p,%x] np %ld\n",
- sg->address, sg->length, npages);
- for (++sg; sg < end && (int) sg->dma_address < 0; ++sg)
- DBGA(" (%ld) [%p,%x] cont\n",
- sg - leader, sg->address, sg->length);
-#endif
- } else {
- /* All virtually contiguous. We need to find the
- length of each physically contiguous subsegment
- to fill in the ptes. */
- do {
- struct scatterlist *last_sg = sg;
+ do {
+ struct scatterlist *last_sg = sg;
- size = sg->length;
- paddr = virt_to_phys(sg->address);
+ size = sg->length;
+ paddr = virt_to_phys(sg->address);
- while (sg+1 < end && (int) sg[1].dma_address == -1) {
- size += sg[1].length;
- sg++;
- }
+ while (sg+1 < end && (int) sg[1].dma_address == -1) {
+ size += sg[1].length;
+ sg++;
+ }
- npages = calc_npages((paddr & ~PAGE_MASK) + size);
+ npages = calc_npages((paddr & ~PAGE_MASK) + size);
- paddr &= PAGE_MASK;
- for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
- *ptes++ = mk_iommu_pte(paddr);
+ paddr &= PAGE_MASK;
+ for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
+ *ptes++ = mk_iommu_pte(paddr);
#if DEBUG_ALLOC > 0
- DBGA(" (%ld) [%p,%x] np %ld\n",
+ DBGA(" (%ld) [%p,%x] np %ld\n",
+ last_sg - leader, last_sg->address,
+ last_sg->length, npages);
+ while (++last_sg <= sg) {
+ DBGA(" (%ld) [%p,%x] cont\n",
last_sg - leader, last_sg->address,
- last_sg->length, npages);
- while (++last_sg <= sg) {
- DBGA(" (%ld) [%p,%x] cont\n",
- last_sg - leader, last_sg->address,
- last_sg->length);
- }
+ last_sg->length);
+ }
#endif
- } while (++sg < end && (int) sg->dma_address < 0);
- }
+ } while (++sg < end && (int) sg->dma_address < 0);
return 1;
}
@@ -472,13 +468,9 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
/* Third, iterate over the scatterlist leaders and allocate
dma space as needed. */
for (out = sg; sg < end; ++sg) {
- int ret;
-
if ((int) sg->dma_address < 0)
continue;
-
- ret = sg_fill(sg, end, out, arena, max_dma);
- if (ret < 0)
+ if (sg_fill(sg, end, out, arena, max_dma) < 0)
goto error;
out++;
}
@@ -517,7 +509,6 @@ 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 fstart, fend;
if (direction == PCI_DMA_NONE)
BUG();
@@ -531,42 +522,32 @@ 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;
- fstart = -1;
- fend = 0;
for (end = sg + nents; sg < end; ++sg) {
unsigned long addr, size;
+ long npages, ofs;
addr = sg->dma_address;
size = sg->dma_length;
-
if (!size)
break;
+#if !DEBUG_NODIRECT
if (addr >= __direct_map_base
&& addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
DBGA(" (%ld) direct [%lx,%lx]\n",
sg - end + nents, addr, size);
- } else {
- long npages, ofs;
- dma_addr_t tend;
-
- DBGA(" (%ld) sg [%lx,%lx]\n",
- sg - end + nents, addr, size);
+ continue;
+ }
+#endif
- npages = calc_npages((addr & ~PAGE_MASK) + size);
- ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
- iommu_arena_free(arena, ofs, npages);
+ DBGA(" (%ld) sg [%lx,%lx]\n",
+ sg - end + nents, addr, size);
- tend = addr + size - 1;
- if (fstart > addr)
- fstart = addr;
- if (fend < tend)
- fend = tend;
- }
+ npages = calc_npages((addr & ~PAGE_MASK) + size);
+ ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
+ iommu_arena_free(arena, ofs, npages);
}
- if (fend)
- alpha_mv.mv_pci_tbi(hose, fstart, fend);
DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg));
}
@@ -580,6 +561,7 @@ pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask)
struct pci_controler *hose;
struct pci_iommu_arena *arena;
+#if !DEBUG_NODIRECT
/* If there exists a direct map, and the mask fits either
MAX_DMA_ADDRESS defined such that GFP_DMA does something
useful, or the total system memory as shifted by the
@@ -588,6 +570,7 @@ pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask)
&& (__direct_map_base + MAX_DMA_ADDRESS-IDENT_ADDR-1 <= mask
|| __direct_map_base + (max_low_pfn<<PAGE_SHIFT)-1 <= mask))
return 1;
+#endif
/* Check that we have a scatter-gather arena that fits. */
hose = pdev ? pdev->sysdata : pci_isa_hose;
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index a8859059b..8e7bbcfaf 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -10,7 +10,6 @@ struct pt_regs;
struct task_struct;
struct pci_dev;
struct pci_controler;
-struct irqaction;
/* core_apecs.c */
extern struct pci_ops apecs_pci_ops;
@@ -81,14 +80,13 @@ extern void setup_smp(void);
extern int smp_info(char *buffer);
extern void handle_ipi(struct pt_regs *);
extern void smp_percpu_timer_interrupt(struct pt_regs *);
-extern unsigned long cpu_present_mask;
/* bios32.c */
/* extern void reset_for_srm(void); */
/* time.c */
extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
-extern void common_init_rtc(struct irqaction *);
+extern void common_init_rtc(void);
extern unsigned long est_cycle_freq;
/* smc37c93x.c */
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 1311d939b..615914535 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -487,6 +487,7 @@ setup_arch(char **cmdline_p)
#ifdef __SMP__
setup_smp();
#endif
+ paging_init();
}
static char sys_unknown[] = "Unknown";
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index cc5d8b16b..ff12b9e8d 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -437,6 +437,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
+ if (err)
+ goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -499,6 +501,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
set->sig[0], oldsp);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index be1a6440e..ab1fb9ab2 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -972,6 +972,33 @@ flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
flush_tlb_mm(mm);
}
+static void
+ipi_flush_icache_page(void *x)
+{
+ struct mm_struct *mm = (struct mm_struct *) x;
+ if (mm == current->active_mm)
+ __load_new_mm_context(mm);
+}
+
+void
+flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if ((vma->vm_flags & VM_EXEC) == 0)
+ return;
+
+ mm->context = 0;
+ if (mm == current->active_mm) {
+ __load_new_mm_context(mm);
+ if (atomic_read(&mm->mm_users) <= 1)
+ return;
+ }
+
+ if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) {
+ printk(KERN_CRIT "flush_icache_page: timed out\n");
+ }
+}
int
smp_info(char *buffer)
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index 5498c72ec..867d762f8 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -48,7 +48,7 @@ alcor_enable_irq(unsigned int irq)
alcor_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
}
-static inline void
+static void
alcor_disable_irq(unsigned int irq)
{
alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
@@ -81,6 +81,13 @@ alcor_isa_mask_and_ack_irq(unsigned int irq)
*(vuip)GRU_INT_CLEAR = 0; mb();
}
+static void
+alcor_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ alcor_enable_irq(irq);
+}
+
static struct hw_interrupt_type alcor_irq_type = {
typename: "ALCOR",
startup: alcor_startup_irq,
@@ -88,7 +95,7 @@ static struct hw_interrupt_type alcor_irq_type = {
enable: alcor_enable_irq,
disable: alcor_disable_irq,
ack: alcor_mask_and_ack_irq,
- end: alcor_enable_irq,
+ end: alcor_end_irq,
};
static void
@@ -134,13 +141,12 @@ alcor_init_irq(void)
on while IRQ probing. */
if (i >= 16+20 && i <= 16+30)
continue;
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &alcor_irq_type;
}
i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
setup_irq(16+31, &isa_cascade_irqaction);
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index acea58d1e..8e016ada0 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -65,6 +65,13 @@ cabriolet_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
+static void
+cabriolet_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ cabriolet_enable_irq(irq);
+}
+
static struct hw_interrupt_type cabriolet_irq_type = {
typename: "CABRIOLET",
startup: cabriolet_startup_irq,
@@ -72,7 +79,7 @@ static struct hw_interrupt_type cabriolet_irq_type = {
enable: cabriolet_enable_irq,
disable: cabriolet_disable_irq,
ack: cabriolet_disable_irq,
- end: cabriolet_enable_irq,
+ end: cabriolet_end_irq,
};
static void
@@ -103,7 +110,6 @@ static void __init
cabriolet_init_irq(void)
{
init_i8259a_irqs();
- init_rtc_irq();
if (alpha_using_srm) {
alpha_mv.device_interrupt = srm_device_interrupt;
@@ -117,7 +123,7 @@ cabriolet_init_irq(void)
outb(0xff, 0x806);
for (i = 16; i < 35; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &cabriolet_irq_type;
}
}
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 7414b8cc2..63abc109f 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -35,6 +35,10 @@
/* 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];
+
+spinlock_t dp264_irq_lock = SPIN_LOCK_UNLOCKED;
static void
tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
@@ -50,9 +54,14 @@ tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
mask0 = mask1 = mask2 = mask3 = mask;
maskB = mask | isa_enable;
if (bcpu == 0) mask0 = maskB;
- if (bcpu == 1) mask1 = maskB;
- if (bcpu == 2) mask2 = maskB;
- if (bcpu == 3) mask3 = maskB;
+ else if (bcpu == 1) mask1 = maskB;
+ else if (bcpu == 2) mask2 = maskB;
+ else if (bcpu == 3) mask3 = maskB;
+
+ mask0 &= cpu_irq_affinity[0];
+ mask1 &= cpu_irq_affinity[1];
+ mask2 &= cpu_irq_affinity[2];
+ mask3 &= cpu_irq_affinity[3];
dim0 = &cchip->dim0.csr;
dim1 = &cchip->dim1.csr;
@@ -73,10 +82,12 @@ tsunami_update_irq_hw(unsigned long mask, unsigned long isa_enable)
*dim2;
*dim3;
#else
- volatile unsigned long *dimB = &cchip->dim1.csr;
+ volatile unsigned long *dimB;
if (bcpu == 0) dimB = &cchip->dim0.csr;
- if (bcpu == 2) dimB = &cchip->dim2.csr;
- if (bcpu == 3) dimB = &cchip->dim3.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;
+
*dimB = mask | isa_enable;
mb();
*dimB;
@@ -95,18 +106,22 @@ clipper_update_irq_hw(unsigned long mask)
tsunami_update_irq_hw(mask, 1UL << 55);
}
-static inline void
+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);
+ spin_unlock(&dp264_irq_lock);
}
static void
dp264_disable_irq(unsigned int irq)
{
+ spin_lock(&dp264_irq_lock);
cached_irq_mask &= ~(1UL << irq);
dp264_update_irq_hw(cached_irq_mask);
+ spin_unlock(&dp264_irq_lock);
}
static unsigned int
@@ -116,18 +131,29 @@ dp264_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
-static inline void
+static void
+dp264_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ dp264_enable_irq(irq);
+}
+
+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);
+ spin_unlock(&dp264_irq_lock);
}
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);
+ spin_unlock(&dp264_irq_lock);
}
static unsigned int
@@ -137,6 +163,47 @@ clipper_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
+static void
+clipper_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ clipper_enable_irq(irq);
+}
+
+static void
+cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
+{
+ int cpu;
+
+ for (cpu = 0; cpu < 4; cpu++) {
+ unsigned long aff = cpu_irq_affinity[cpu];
+ if (affinity & (1UL << cpu))
+ aff |= 1UL << irq;
+ else
+ aff &= ~(1UL << irq);
+ cpu_irq_affinity[cpu] = aff;
+ }
+
+}
+
+static void
+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);
+ spin_unlock(&dp264_irq_lock);
+}
+
+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);
+ spin_unlock(&dp264_irq_lock);
+}
+
static struct hw_interrupt_type dp264_irq_type = {
typename: "DP264",
startup: dp264_startup_irq,
@@ -144,7 +211,8 @@ static struct hw_interrupt_type dp264_irq_type = {
enable: dp264_enable_irq,
disable: dp264_disable_irq,
ack: dp264_disable_irq,
- end: dp264_enable_irq,
+ end: dp264_end_irq,
+ set_affinity: dp264_set_affinity,
};
static struct hw_interrupt_type clipper_irq_type = {
@@ -154,7 +222,8 @@ static struct hw_interrupt_type clipper_irq_type = {
enable: clipper_enable_irq,
disable: clipper_disable_irq,
ack: clipper_disable_irq,
- end: clipper_enable_irq,
+ end: clipper_end_irq,
+ set_affinity: clipper_set_affinity,
};
static void
@@ -249,6 +318,8 @@ 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);
@@ -257,10 +328,12 @@ 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);
init_i8259a_irqs();
- init_rtc_irq();
init_tsunami_irqs(&dp264_irq_type);
}
@@ -278,7 +351,6 @@ clipper_init_irq(void)
clipper_update_irq_hw(0UL);
init_i8259a_irqs();
- init_rtc_irq();
init_tsunami_irqs(&clipper_irq_type);
}
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index 0820bd5a0..b3e9e3867 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -48,7 +48,7 @@ eb64p_enable_irq(unsigned int irq)
eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
}
-static inline void
+static void
eb64p_disable_irq(unsigned int irq)
{
eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
@@ -61,6 +61,13 @@ eb64p_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
+static void
+eb64p_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ eb64p_enable_irq(irq);
+}
+
static struct hw_interrupt_type eb64p_irq_type = {
typename: "EB64P",
startup: eb64p_startup_irq,
@@ -68,7 +75,7 @@ static struct hw_interrupt_type eb64p_irq_type = {
enable: eb64p_enable_irq,
disable: eb64p_disable_irq,
ack: eb64p_disable_irq,
- end: eb64p_enable_irq,
+ end: eb64p_end_irq,
};
static void
@@ -119,10 +126,9 @@ eb64p_init_irq(void)
outb(0xff, 0x27);
init_i8259a_irqs();
- init_rtc_irq();
for (i = 16; i < 32; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &eb64p_irq_type;
}
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index c4d120799..9e4fbe569 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -76,6 +76,13 @@ eiger_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
+static void
+eiger_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ eiger_enable_irq(irq);
+}
+
static struct hw_interrupt_type eiger_irq_type = {
typename: "EIGER",
startup: eiger_startup_irq,
@@ -83,7 +90,7 @@ static struct hw_interrupt_type eiger_irq_type = {
enable: eiger_enable_irq,
disable: eiger_disable_irq,
ack: eiger_disable_irq,
- end: eiger_enable_irq,
+ end: eiger_end_irq,
};
static void
@@ -147,10 +154,9 @@ eiger_init_irq(void)
eiger_update_irq_hw(i, -1);
init_i8259a_irqs();
- init_rtc_irq();
for (i = 16; i < 128; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &eiger_irq_type;
}
}
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index 98dea0902..2f5400632 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -71,7 +71,7 @@ static struct hw_interrupt_type jensen_local_irq_type = {
enable: i8259a_enable_irq,
disable: i8259a_disable_irq,
ack: jensen_local_ack,
- end: i8259a_enable_irq,
+ end: i8259a_end_irq,
};
static void
@@ -110,7 +110,6 @@ static void __init
jensen_init_irq(void)
{
init_i8259a_irqs();
- init_rtc_irq();
irq_desc[1].handler = &jensen_local_irq_type;
irq_desc[4].handler = &jensen_local_irq_type;
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index 06457a0e8..0191ef91b 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -70,7 +70,6 @@ miata_init_irq(void)
#endif
init_i8259a_irqs();
- init_rtc_irq();
/* Not interested in the bogus interrupts (3,10), Fan Fault (0),
NMI (1), or EIDE (9).
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index 936fa4f17..a66731154 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -48,7 +48,7 @@ mikasa_enable_irq(unsigned int irq)
mikasa_update_irq_hw(cached_irq_mask |= 1 << (irq - 16));
}
-static inline void
+static void
mikasa_disable_irq(unsigned int irq)
{
mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (irq - 16)));
@@ -61,6 +61,13 @@ mikasa_startup_irq(unsigned int irq)
return 0;
}
+static void
+mikasa_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ mikasa_enable_irq(irq);
+}
+
static struct hw_interrupt_type mikasa_irq_type = {
typename: "MIKASA",
startup: mikasa_startup_irq,
@@ -68,7 +75,7 @@ static struct hw_interrupt_type mikasa_irq_type = {
enable: mikasa_enable_irq,
disable: mikasa_disable_irq,
ack: mikasa_disable_irq,
- end: mikasa_enable_irq,
+ end: mikasa_end_irq,
};
static void
@@ -108,12 +115,11 @@ mikasa_init_irq(void)
mikasa_update_irq_hw(0);
for (i = 16; i < 32; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &mikasa_irq_type;
}
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 621df72f8..32653e3a7 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -54,7 +54,6 @@ static void __init
nautilus_init_irq(void)
{
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index 31eac0da4..523d29853 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -45,13 +45,13 @@ noritake_update_irq_hw(int irq, int mask)
outw(mask, port);
}
-static inline void
+static void
noritake_enable_irq(unsigned int irq)
{
noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
}
-static inline void
+static void
noritake_disable_irq(unsigned int irq)
{
noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
@@ -135,12 +135,11 @@ noritake_init_irq(void)
outw(0, 0x54c);
for (i = 16; i < 48; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &noritake_irq_type;
}
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index f956626a4..3ccce8640 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -41,6 +41,7 @@ static unsigned int hose_irq_masks[4] = {
0xff0000, 0xfe0000, 0xff0000, 0xff0000
};
static unsigned int cached_irq_masks[4];
+spinlock_t rawhide_irq_lock = SPIN_LOCK_UNLOCKED;
static inline void
rawhide_update_irq_hw(int hose, int mask)
@@ -50,7 +51,7 @@ rawhide_update_irq_hw(int hose, int mask)
*(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose));
}
-static void
+static inline void
rawhide_enable_irq(unsigned int irq)
{
unsigned int mask, hose;
@@ -59,9 +60,11 @@ rawhide_enable_irq(unsigned int irq)
hose = irq / 24;
irq -= hose * 24;
+ spin_lock(&rawhide_irq_lock);
mask = cached_irq_masks[hose] |= 1 << irq;
mask |= hose_irq_masks[hose];
rawhide_update_irq_hw(hose, mask);
+ spin_unlock(&rawhide_irq_lock);
}
static void
@@ -73,9 +76,11 @@ rawhide_disable_irq(unsigned int irq)
hose = irq / 24;
irq -= hose * 24;
+ spin_lock(&rawhide_irq_lock);
mask = cached_irq_masks[hose] &= ~(1 << irq);
mask |= hose_irq_masks[hose];
rawhide_update_irq_hw(hose, mask);
+ spin_unlock(&rawhide_irq_lock);
}
@@ -86,6 +91,13 @@ rawhide_startup_irq(unsigned int irq)
return 0;
}
+static void
+rawhide_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ rawhide_enable_irq(irq);
+}
+
static struct hw_interrupt_type rawhide_irq_type = {
typename: "RAWHIDE",
startup: rawhide_startup_irq,
@@ -93,7 +105,7 @@ static struct hw_interrupt_type rawhide_irq_type = {
enable: rawhide_enable_irq,
disable: rawhide_disable_irq,
ack: rawhide_disable_irq,
- end: rawhide_enable_irq,
+ end: rawhide_end_irq,
};
static void
@@ -138,12 +150,11 @@ rawhide_init_irq(void)
}
for (i = 16; i < 128; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &rawhide_irq_type;
}
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index ae89e81b2..01d80ab97 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -64,7 +64,7 @@ ruffian_init_irq(void)
}
static void __init
-ruffian_init_rtc(struct irqaction *action)
+ruffian_init_rtc(void)
{
/* Ruffian does not have the RTC connected to the CPU timer
interrupt. Instead, it uses the PIT connected to IRQ 0. */
@@ -78,7 +78,7 @@ ruffian_init_rtc(struct irqaction *action)
outb(0x31, 0x42);
outb(0x13, 0x42);
- setup_irq(0, action);
+ setup_irq(0, &timer_irqaction);
}
static void
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index d5299d008..2d5927c84 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -65,6 +65,13 @@ rx164_startup_irq(unsigned int irq)
return 0;
}
+static void
+rx164_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ rx164_enable_irq(irq);
+}
+
static struct hw_interrupt_type rx164_irq_type = {
typename: "RX164",
startup: rx164_startup_irq,
@@ -72,7 +79,7 @@ static struct hw_interrupt_type rx164_irq_type = {
enable: rx164_enable_irq,
disable: rx164_disable_irq,
ack: rx164_disable_irq,
- end: rx164_enable_irq,
+ end: rx164_end_irq,
};
static void
@@ -109,12 +116,11 @@ rx164_init_irq(void)
rx164_update_irq_hw(0);
for (i = 16; i < 40; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &rx164_irq_type;
}
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
setup_irq(16+20, &isa_cascade_irqaction);
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index e2a69b5c7..b27d757b2 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -30,6 +30,7 @@
#include "pci_impl.h"
#include "machvec_impl.h"
+spinlock_t sable_irq_lock = SPIN_LOCK_UNLOCKED;
/*
* For SABLE, which is really baroque, we manage 40 IRQ's, but the
@@ -137,8 +138,10 @@ sable_enable_irq(unsigned int irq)
unsigned long bit, mask;
bit = sable_irq_swizzle.irq_to_mask[irq];
+ spin_lock(&sable_irq_lock);
mask = sable_irq_swizzle.shadow_mask &= ~(1UL << bit);
sable_update_irq_hw(bit, mask);
+ spin_unlock(&sable_irq_lock);
}
static void
@@ -147,8 +150,10 @@ sable_disable_irq(unsigned int irq)
unsigned long bit, mask;
bit = sable_irq_swizzle.irq_to_mask[irq];
+ spin_lock(&sable_irq_lock);
mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
sable_update_irq_hw(bit, mask);
+ spin_unlock(&sable_irq_lock);
}
static unsigned int
@@ -159,14 +164,23 @@ sable_startup_irq(unsigned int irq)
}
static void
+sable_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ sable_enable_irq(irq);
+}
+
+static void
sable_mask_and_ack_irq(unsigned int irq)
{
unsigned long bit, mask;
bit = sable_irq_swizzle.irq_to_mask[irq];
+ spin_lock(&sable_irq_lock);
mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
sable_update_irq_hw(bit, mask);
sable_ack_irq_hw(bit);
+ spin_unlock(&sable_irq_lock);
}
static struct hw_interrupt_type sable_irq_type = {
@@ -176,7 +190,7 @@ static struct hw_interrupt_type sable_irq_type = {
enable: sable_enable_irq,
disable: sable_disable_irq,
ack: sable_mask_and_ack_irq,
- end: sable_enable_irq,
+ end: sable_end_irq,
};
static void
@@ -204,11 +218,10 @@ sable_init_irq(void)
outb(0x44, 0x535); /* enable cascades in master */
for (i = 0; i < 40; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &sable_irq_type;
}
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 0230ec6d9..e378408f2 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -42,7 +42,6 @@ sio_init_irq(void)
alpha_mv.device_interrupt = srm_device_interrupt;
init_i8259a_irqs();
- init_rtc_irq();
common_init_isa_dma();
}
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index 806241a32..bad57d35e 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -43,7 +43,6 @@ sx164_init_irq(void)
alpha_mv.device_interrupt = srm_device_interrupt;
init_i8259a_irqs();
- init_rtc_irq();
/* Not interested in the bogus interrupts (0,3,4,5,40-47),
NMI (1), or HALT (2). */
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index 360f135b6..a0bc57125 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -66,6 +66,13 @@ takara_startup_irq(unsigned int irq)
return 0; /* never anything pending */
}
+static void
+takara_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ takara_enable_irq(irq);
+}
+
static struct hw_interrupt_type takara_irq_type = {
typename: "TAKARA",
startup: takara_startup_irq,
@@ -73,7 +80,7 @@ static struct hw_interrupt_type takara_irq_type = {
enable: takara_enable_irq,
disable: takara_disable_irq,
ack: takara_disable_irq,
- end: takara_enable_irq,
+ end: takara_end_irq,
};
static void
@@ -126,7 +133,6 @@ takara_init_irq(void)
long i;
init_i8259a_irqs();
- init_rtc_irq();
if (alpha_using_srm) {
alpha_mv.device_interrupt = takara_srm_device_interrupt;
@@ -146,7 +152,7 @@ takara_init_irq(void)
takara_update_irq_hw(i, -1);
for (i = 16; i < 128; ++i) {
- irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = &takara_irq_type;
}
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index d7b5cee8c..291682e33 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -163,7 +163,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
}
void
-common_init_rtc(struct irqaction *action)
+common_init_rtc()
{
unsigned char x;
@@ -192,18 +192,12 @@ common_init_rtc(struct irqaction *action)
outb(0x31, 0x42);
outb(0x13, 0x42);
- setup_irq(RTC_IRQ, action);
+ init_rtc_irq();
}
void
time_init(void)
{
- static struct irqaction timer_irqaction = {
- handler: timer_interrupt,
- flags: SA_INTERRUPT,
- name: "timer",
- };
-
unsigned int year, mon, day, hour, min, sec, cc1, cc2;
unsigned long cycle_freq, one_percent;
long diff;
@@ -292,7 +286,9 @@ time_init(void)
state.partial_tick = 0L;
/* Startup the timer source. */
- alpha_mv.init_rtc(&timer_irqaction);
+ alpha_mv.init_rtc();
+
+ do_get_fast_time = do_gettimeofday;
}
/*
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 4da99bad2..3d9c8e75e 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -38,9 +38,18 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
unsigned long last_asn = ASN_FIRST_VERSION;
#endif
-void ev5_flush_tlb_current(struct mm_struct *mm)
+extern void
+__load_new_mm_context(struct mm_struct *next_mm)
{
- ev5_activate_mm(NULL, mm, smp_processor_id());
+ unsigned long mmc;
+
+ mmc = __get_new_mm_context(next_mm, smp_processor_id());
+ next_mm->context = mmc;
+ current->thread.asn = mmc & HARDWARE_ASN_MASK;
+ current->thread.ptbr
+ = ((unsigned long) next_mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
+
+ __reload_thread(&current->thread);
}
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index d2992a491..d92f2b093 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -46,13 +46,12 @@ endif
ifeq ($(CONFIG_ARCH_SA1100),y)
OBJS += head-sa1100.o
-ifeq ($(CONFIG_SA1100_VICTOR),y)
-ZTEXTADDR = 0x00002000
-ZBSSADDR = 0xc0100000
-else
ZTEXTADDR = 0xc0008000
-endif
ZRELADDR = 0xc0008000
+ifeq ($(CONFIG_SA1100_VICTOR),y)
+ ZTEXTADDR = 0x00002000
+ ZBSSADDR = 0xc0100000
+endif
endif
#
diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S
index 90018e52b..4464157c3 100644
--- a/arch/arm/boot/compressed/head-sa1100.S
+++ b/arch/arm/boot/compressed/head-sa1100.S
@@ -11,6 +11,8 @@
.section ".start", #alloc, #execinstr
+__SA1100_start:
+
#ifndef CONFIG_ARCH_SA1100
#error What am I doing here...
#endif
@@ -58,6 +60,65 @@
orr r0, r0, #0x1000 @ set Icache
mcr p15, 0, r0, c1, c0, 0
+#ifdef CONFIG_SA1100_BRUTUS
+ @ Initialize UART1 for early serial communication
+ @ since UART3 is used by angelboot. It is routed to
+ @ alternate GPIO functions on Brutus.
+ b 1f
+
+GPIO_BASE: .long 0x90040000
+#define GPDR 0x04
+#define GAFR 0x1c
+
+PPC_BASE: .long 0x90060000
+#define PPAR 0x08
+
+UART1_BASE: .long 0x80010000
+#define UTCR0 0x00
+#define UTCR1 0x04
+#define UTCR2 0x08
+#define UTCR3 0x0c
+#define UTSR0 0x1c
+#define UTSR1 0x20
+
+#define BAUD_DIV_230400 0x000
+#define BAUD_DIV_115200 0x001
+#define BAUD_DIV_57600 0x003
+#define BAUD_DIV_38400 0x005
+#define BAUD_DIV_19200 0x00b
+#define BAUD_DIV_9600 0x017
+#define BAUD_DIV BAUD_DIV_9600
+
+1: ldr r0, GPIO_BASE
+ ldr r1, [r0, #GPDR]
+ bic r1, r1, #1<<15
+ orr r1, r1, #1<<14
+ str r1, [r0, #GPDR]
+ ldr r1, [r0, #GAFR]
+ orr r1, r1, #(1<<15)|(1<<14)
+ str r1, [r0, #GAFR]
+ ldr r0, PPC_BASE
+ ldr r1, [r0, #PPAR]
+ orr r1, r1, #1<<12
+ str r1, [r0, #PPAR]
+ ldr r0, UART1_BASE
+1: ldr r1, [r0, #UTSR1]
+ tst r1, #1<<0 @ TBY
+ bne 1b
+ mov r1, #0
+ str r1, [r0, #UTCR3]
+ mov r1, #0x08 @ 8N1
+ str r1, [r0, #UTCR0]
+ mov r1, #BAUD_DIV
+ str r1, [r0, #UTCR2]
+ mov r1, r1, lsr #8
+ str r1, [r0, #UTCR1]
+ mov r1, #0x03 @ RXE + TXE
+ str r1, [r0, #UTCR3]
+ mov r1, #0xff @ flush status reg
+ str r1, [r0, #UTSR0]
+#endif
+
@ set registers for entry
mov r0, #0
mov r1, #16
diff --git a/arch/arm/config.in b/arch/arm/config.in
index be7102698..5e9cc8bfc 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -92,6 +92,8 @@ else
if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
"$CONFIG_ARCH_SA1100" = "y" -o \
"$CONFIG_FOOTBRIDGE" = "y" -o \
+ "$CONFIG_ARCH_TBOX" = "y" -o \
+ "$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
define_bool CONFIG_CPU_32v4 y
if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
@@ -122,6 +124,7 @@ fi
# These machines have ISA-DMA
#
if [ "$CONFIG_CATS" = "y" -o \
+ "$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_NETWINDER" = "y" ]; then
define_bool CONFIG_ISA_DMA y
else
@@ -186,6 +189,8 @@ if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
fi
endmenu
+source drivers/ieee1394/Config.in
+
source drivers/i2o/Config.in
source drivers/pnp/Config.in
@@ -209,6 +214,8 @@ fi
source drivers/usb/Config.in
+source drivers/misc/Config.in
+
if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment
comment 'Console drivers'
@@ -256,7 +263,10 @@ if [ "$CONFIG_SCSI" != "n" ]; then
fi
endmenu
-if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_PCI" = "y" ]; then
+if [ "$CONFIG_ARCH_ACORN" = "y" -o \
+ "$CONFIG_ARCH_CLPS7500" = "y" -o \
+ "$CONFIG_ARCH_SHARK" = "y" -o \
+ "$CONFIG_PCI" = "y" ]; then
mainmenu_option next_comment
comment 'Sound'
diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c
index 9994fdd4a..77c7d7396 100644
--- a/arch/arm/kernel/arthur.c
+++ b/arch/arm/kernel/arthur.c
@@ -1,6 +1,6 @@
/*
* Arthur personality
- * Copyright (C) 1998 Philip Blundell
+ * Copyright (C) 1998-1999 Philip Blundell
*/
#include <linux/personality.h>
@@ -8,35 +8,36 @@
#include <linux/stddef.h>
#include <linux/signal.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/ptrace.h>
-/* RISC OS doesn't have many signals, and a lot of those that it does
+/* Arthur doesn't have many signals, and a lot of those that it does
have don't map easily to any Linux equivalent. Never mind. */
-#define RISCOS_SIGABRT 1
-#define RISCOS_SIGFPE 2
-#define RISCOS_SIGILL 3
-#define RISCOS_SIGINT 4
-#define RISCOS_SIGSEGV 5
-#define RISCOS_SIGTERM 6
-#define RISCOS_SIGSTAK 7
-#define RISCOS_SIGUSR1 8
-#define RISCOS_SIGUSR2 9
-#define RISCOS_SIGOSERROR 10
+#define ARTHUR_SIGABRT 1
+#define ARTHUR_SIGFPE 2
+#define ARTHUR_SIGILL 3
+#define ARTHUR_SIGINT 4
+#define ARTHUR_SIGSEGV 5
+#define ARTHUR_SIGTERM 6
+#define ARTHUR_SIGSTAK 7
+#define ARTHUR_SIGUSR1 8
+#define ARTHUR_SIGUSR2 9
+#define ARTHUR_SIGOSERROR 10
-static unsigned long riscos_to_linux_signals[32] = {
+static unsigned long arthur_to_linux_signals[32] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31
};
-static unsigned long linux_to_riscos_signals[32] = {
- 0, -1, RISCOS_SIGINT, -1,
- RISCOS_SIGILL, 5, RISCOS_SIGABRT, 7,
- RISCOS_SIGFPE, 9, RISCOS_SIGUSR1, RISCOS_SIGSEGV,
- RISCOS_SIGUSR2, 13, 14, RISCOS_SIGTERM,
+static unsigned long linux_to_arthur_signals[32] = {
+ 0, -1, ARTHUR_SIGINT, -1,
+ ARTHUR_SIGILL, 5, ARTHUR_SIGABRT, 7,
+ ARTHUR_SIGFPE, 9, ARTHUR_SIGUSR1, ARTHUR_SIGSEGV,
+ ARTHUR_SIGUSR2, 13, 14, ARTHUR_SIGTERM,
16, 17, 18, 19,
20, 21, 22, 23,
24, 25, 26, 27,
@@ -52,12 +53,12 @@ static void arthur_lcall7(int nr, struct pt_regs *regs)
send_sig_info(SIGSWI, &info, current);
}
-static struct exec_domain riscos_exec_domain = {
+static struct exec_domain arthur_exec_domain = {
"Arthur", /* name */
(lcall7_func)arthur_lcall7,
PER_RISCOS, PER_RISCOS,
- riscos_to_linux_signals,
- linux_to_riscos_signals,
+ arthur_to_linux_signals,
+ linux_to_arthur_signals,
#ifdef MODULE
&__this_module, /* No usage counter. */
#else
@@ -71,18 +72,15 @@ static struct exec_domain riscos_exec_domain = {
* processes are using it.
*/
-#ifdef MODULE
-int init_module(void)
-#else
-int initialise_arthur(void)
-#endif
+int __init arthur_init(void)
{
- return register_exec_domain(&riscos_exec_domain);
+ return register_exec_domain(&arthur_exec_domain);
}
-#ifdef MODULE
-void cleanup_module(void)
+void __exit arthur_exit(void)
{
- unregister_exec_domain(&riscos_exec_domain);
+ unregister_exec_domain(&arthur_exec_domain);
}
-#endif
+
+module_init(arthur_init);
+module_exit(arthur_exit);
diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S
index f2dc9e36c..d6fa94867 100644
--- a/arch/arm/kernel/entry-armo.S
+++ b/arch/arm/kernel/entry-armo.S
@@ -22,6 +22,7 @@
* adhering to the above criteria.
*/
#include <linux/linkage.h>
+#include <linux/config.h>
#include <asm/assembler.h>
#include <asm/errno.h>
@@ -29,6 +30,12 @@
#include "../lib/constants.h"
+ .macro zero_fp
+#ifdef CONFIG_FRAME_POINTER
+ mov fp, #0
+#endif
+ .endm
+
.text
@ Offsets into task structure
@@ -213,7 +220,7 @@ irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
stmfd sp!, {r0 - r12} ;\
mov r0, #-1 ;\
str r0, [sp, #S_OLD_R0] ;\
- mov fp, #0
+ zero_fp
#define SVC_IRQ_SAVE_ALL \
str sp, [sp, #-16]! ;\
@@ -224,7 +231,7 @@ irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
stmfd sp!, {r0 - r12} ;\
mov r0, #-1 ;\
str r0, [sp, #S_OLD_R0] ;\
- mov fp, #0
+ zero_fp
#define SVC_RESTORE_ALL \
ldmfd sp, {r0 - pc}^
@@ -261,7 +268,7 @@ vector_undefinstr:
tst lr,#3
bne __und_svc
save_user_regs
- mov fp, #0
+ zero_fp
teqp pc, #I_BIT | MODE_SVC
.Lbug_undef:
ldr r4, .LC2
@@ -283,6 +290,10 @@ __und_svc: SVC_SAVE_ALL @ Non-user mode
bl SYMBOL_NAME(do_undefinstr)
SVC_RESTORE_ALL
+#ifdef CONFIG_NWFPE
+ /* The FPE is always present */
+ .equ fpe_not_present, 0
+#else
/* We get here if an undefined instruction happens and the floating
* point emulator is not present. If the offending instruction was
* a WFS, we just perform a normal return as if we had emulated the
@@ -319,6 +330,7 @@ wfs_mask_data: .word 0x0e200110 @ WFS/RFS
.word 0x0d0d0100 @ LDF [sp]/STF [sp]
.word 0x0d0b0100 @ LDF [fp]/STF [fp]
.word 0x0f0f0f00
+#endif
.LC2: .word SYMBOL_NAME(fp_enter)
@@ -686,7 +698,7 @@ ENTRY(__switch_to)
/*
* initialise the trap system
*/
-ENTRY(trap_init)
+ENTRY(__trap_init)
stmfd sp!, {r4 - r7, lr}
adr r1, .Ljump_addresses
ldmia r1, {r1 - r7, ip, lr}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index f4f03ee93..fe3939888 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -24,6 +24,12 @@
#define MODE_SVC 0x13
#endif
+ .macro zero_fp
+#ifdef CONFIG_FRAME_POINTER
+ mov fp, #0
+#endif
+ .endm
+
.text
#define PF_TRACESYS 0x20
@@ -421,7 +427,7 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE
ldr r4, .LCund
mov r1, #BAD_UNDEFINSTR @ int reason
-1: mov fp, #0
+1: zero_fp
ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
add r4, sp, #S_PC
stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
@@ -573,7 +579,7 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
stmdb r3, {sp, lr}^
alignment_trap r4, r7, __temp_abt
- mov fp, #0
+ zero_fp
#ifdef MULTI_CPU
ldr r2, .LCprocfns
mov lr, pc
@@ -595,7 +601,7 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
stmia r8, {r5 - r7} @ save pc, psr, old_r0
stmdb r8, {sp, lr}^
alignment_trap r4, r7, __temp_irq
- mov fp, #0
+ zero_fp
1: get_irqnr_and_base r0, r6, r5
movne r1, sp
adrsvc ne, lr, 1b
@@ -615,7 +621,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
stmdb r8, {sp, lr}^ @ Save user r0 - r12
alignment_trap r4, r7, __temp_und
- mov fp, #0
+ zero_fp
adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return
adrsvc al, lr, fpundefinstr @ lr = undefined instr return
@@ -641,7 +647,7 @@ __pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr
alignment_trap r4, r7, __temp_abt
- mov fp, #0
+ zero_fp
msr cpsr_c, #MODE_SVC @ Enable interrupts
mov r0, r5 @ address (pc)
mov r1, sp @ regs
@@ -688,11 +694,11 @@ t: .ascii "Prefetch -> undefined instruction\n\0"
ENTRY(__switch_to)
stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack
mrs ip, cpsr
- stmfd sp!, {ip} @ Save cpsr_SVC
+ str ip, [sp, #-4]! @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
ldr r2, [r1, #TSS_DOMAIN]
- ldmfd sp!, {ip}
+ ldr ip, [sp], #4
mcr p15, 0, r2, c3, c0 @ Set domain register
msr spsr, ip @ Save tasks CPSR into SPSR for this return
ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 5dc61c6d7..97dfef0c1 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -4,16 +4,6 @@
*/
#define S_OFF 8
-#define SYSCALL_REGS r4, r5
-
-/*
- * Define to favour ARM8, ARM9 and StrongARM cpus. This says that it is
- * cheaper to use two LDR instructions than a two-register LDM, if the
- * latter would entail calculating an address specially.
- */
-#if defined(CONFIG_CPU_SA110)
-#define HARVARD_CACHE
-#endif
.macro get_softirq, rd
#ifdef __SMP__
@@ -85,7 +75,7 @@ tip .req r7 @ temporary IP
.align 5
vector_swi: save_user_regs
mask_pc lr, lr
- mov fp, #0
+ zero_fp
ldr scno, [lr, #-4] @ get SWI instruction
arm700_bug_check scno, ip
#ifdef CONFIG_ALIGNMENT_TRAP
@@ -95,9 +85,7 @@ vector_swi: save_user_regs
#endif
enable_irqs ip
- stmdb sp!, {SYSCALL_REGS} @ new style: (r0 = arg1, r4 = arg5, r5 = arg6)
- @ Note that we dont have to handle
- @ sys_syscalls arg7 here
+ str r4, [sp, #-S_OFF]! @ push fifth arg
adrsvc al, lr, fast_syscall_return
bic scno, scno, #0xff000000 @ mask off SWI op-code
@@ -141,10 +129,11 @@ vector_swi: save_user_regs
b SYMBOL_NAME(deferred)
.align 5
-
+ .type __softirq_state, #object
__softirq_state:
.word SYMBOL_NAME(softirq_state)
+ .type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"
@@ -153,15 +142,18 @@ ENTRY(sys_call_table)
*/
@ r0 = syscall number
@ r5 = syscall table
+ .type sys_syscall, #function
SYMBOL_NAME(sys_syscall):
eor scno, r0, #OS_NUMBER << 20
cmp scno, #NR_syscalls @ check range
add ip, sp, #S_OFF
- ldmleib ip, {r0 - r3, SYSCALL_REGS} @ get our args
- stmleia sp, {SYSCALL_REGS} @ Put our arg on the stack
+ stmleia sp, {r5, r6} @ shuffle args
+ movle r0, r1
+ movle r1, r2
+ movle r2, r3
+ movle r3, r4
ldrle pc, [tbl, scno, lsl #2]
- mov r0, #-ENOSYS
- RETINSTR(mov,pc,lr)
+ b sys_ni_syscall
sys_fork_wrapper:
add r0, sp, #S_OFF
@@ -199,6 +191,23 @@ sys_sigaltstack_wrapper:
ldr r2, [sp, #S_OFF + S_SP]
b do_sigaltstack
+/*
+ * Note: off_4k (r5) is always units of 4K. If we can't do the requested
+ * offset, we return EINVAL.
+ */
+sys_mmap2:
+#if PAGE_SHIFT > 12
+ tst r5, #PGOFF_MASK
+ moveq r5, r5, lsr #PGOFF_SHIFT
+ streq r5, [sp, #4]
+ beq do_mmap2
+ mov r0, #-EINVAL
+ RETINSTR(mov,pc, lr)
+#else
+ str r5, [sp, #4]
+ b do_mmap2
+#endif
+
.data
ENTRY(fp_enter)
diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c
index e06c8092d..8dcad0b93 100644
--- a/arch/arm/kernel/hw-footbridge.c
+++ b/arch/arm/kernel/hw-footbridge.c
@@ -68,13 +68,13 @@ static inline void wb977_ww(int reg, int val)
/*
* This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
*/
-spinlock_t __netwinder_data gpio_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t gpio_lock = SPIN_LOCK_UNLOCKED;
-static unsigned int __netwinder_data current_gpio_op = 0;
-static unsigned int __netwinder_data current_gpio_io = 0;
-static unsigned int __netwinder_data current_cpld = 0;
+static unsigned int current_gpio_op = 0;
+static unsigned int current_gpio_io = 0;
+static unsigned int current_cpld = 0;
-void __netwinder_text gpio_modify_op(int mask, int set)
+void gpio_modify_op(int mask, int set)
{
unsigned int new_gpio, changed;
@@ -119,7 +119,7 @@ static inline void __gpio_modify_io(int mask, int in)
}
}
-void __netwinder_text gpio_modify_io(int mask, int in)
+void gpio_modify_io(int mask, int in)
{
/* Open up the SuperIO chip */
wb977_open();
@@ -130,7 +130,7 @@ void __netwinder_text gpio_modify_io(int mask, int in)
wb977_close();
}
-int __netwinder_text gpio_read(void)
+int gpio_read(void)
{
return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
}
@@ -360,7 +360,7 @@ static void __init wb977_init(void)
wb977_close();
}
-void __netwinder_text cpld_modify(int mask, int set)
+void cpld_modify(int mask, int set)
{
int msk;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 6e3c863d5..699cea4ab 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -471,6 +471,10 @@ out:
return irq_found;
}
+void __init init_irq_proc(void)
+{
+}
+
void __init init_IRQ(void)
{
extern void init_dma(void);
diff --git a/arch/arm/kernel/leds-footbridge.c b/arch/arm/kernel/leds-footbridge.c
index 90f2fe109..05f232f57 100644
--- a/arch/arm/kernel/leds-footbridge.c
+++ b/arch/arm/kernel/leds-footbridge.c
@@ -37,7 +37,7 @@ extern spinlock_t gpio_lock;
#ifdef CONFIG_FOOTBRIDGE
-static void __ebsa285_text ebsa285_leds_event(led_event_t evt)
+static void ebsa285_leds_event(led_event_t evt)
{
unsigned long flags;
@@ -129,7 +129,7 @@ static void __ebsa285_text ebsa285_leds_event(led_event_t evt)
#ifdef CONFIG_ARCH_NETWINDER
-static void __netwinder_text netwinder_leds_event(led_event_t evt)
+static void netwinder_leds_event(led_event_t evt)
{
unsigned long flags;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index a2f7292f6..5815529aa 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -767,6 +767,8 @@ void __init setup_arch(char **cmdline_p)
setup_bootmem();
request_standard_resources(mdesc);
+ paging_init();
+
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 47b2930c2..9abb9e617 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -50,7 +50,7 @@ asmlinkage int sys_pipe(unsigned long * fildes)
}
/* common code for old and new mmaps */
-static inline long do_mmap2(
+inline long do_mmap2(
unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
@@ -79,27 +79,6 @@ out:
return error;
}
-#define PGOFF_SHIFT (PAGE_SHIFT - 12)
-#define PGOFF_MASK (~((1 << PGOFF_SHIFT) - 1))
-
-/*
- * Note: off_4k is always units of 4K. If we can't do the requested
- * offset, we return EINVAL.
- */
-asmlinkage long
-sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
- unsigned long flags, unsigned long fd, unsigned long off_4k)
-{
- unsigned long pgoff;
-
- if (off_4k & ~PGOFF_MASK)
- return -EINVAL;
-
- pgoff = off_4k >> PGOFF_SHIFT;
-
- return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
struct mmap_arg_struct {
unsigned long addr;
unsigned long len;
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index e1651904f..3544ac89d 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -53,10 +53,10 @@ ENTRY(find_next_zero_bit)
beq Lfindzbit1lp @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
orr r3, r3, #0xFF00 @ Set top bits so we wont get confused
- stmfd sp!, {r4}
+ str r4, [sp, #-4]!
and r4, r2, #7
mov r3, r3, lsr r4 @ Shift right by no. of bits
- ldmfd sp!, {r4}
+ ldr r4, [sp], #4
and r3, r3, #0xFF
teq r3, #0xFF
orreq r2, r2, #7
diff --git a/arch/arm/lib/getconsdata.c b/arch/arm/lib/getconsdata.c
index aaa7a7ad2..8b6a0affa 100644
--- a/arch/arm/lib/getconsdata.c
+++ b/arch/arm/lib/getconsdata.c
@@ -91,3 +91,5 @@ unsigned long PAGE_SZ = PAGE_SIZE;
unsigned long KSWI_BASE = 0x900000;
unsigned long KSWI_SYS_BASE = 0x9f0000;
unsigned long SYS_ERROR0 = 0x9f0000;
+unsigned long PGOFF_SHIFT = PAGE_SHIFT - 12;
+unsigned long PGOFF_MASK = (1 << (PAGE_SHIFT - 12)) - 1;
diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
index ad5a46089..c9145d7af 100644
--- a/arch/arm/lib/strrchr.S
+++ b/arch/arm/lib/strrchr.S
@@ -12,7 +12,7 @@
.text
ENTRY(strrchr)
- stmfd sp!, {lr}
+ str lr, [sp, #-4]!
mov r3, #0
1: ldrb r2, [r0], #1
teq r2, r1
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 7101b2936..76d1a5c74 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -1,13 +1,14 @@
/*
* Dynamic DMA mapping support.
*/
-
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
+#include <linux/pci.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
@@ -49,6 +50,22 @@ no_page:
return NULL;
}
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle)
+{
+ void *__ret;
+ int __gfp = GFP_KERNEL;
+
+#ifdef CONFIG_PCI
+ if ((hwdev) == NULL ||
+ (hwdev)->dma_mask != 0xffffffff)
+#endif
+ __gfp |= GFP_DMA;
+
+ __ret = consistent_alloc(__gfp, (size),
+ (handle));
+ return __ret;
+}
+
/*
* free a page as defined by the above mapping. We expressly forbid
* calling this from interrupt context.
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 5151591b8..4a23d14bd 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -351,7 +351,7 @@ do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
#endif
-static struct fsr_info {
+static const struct fsr_info {
int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
int sig;
char *name;
@@ -384,7 +384,7 @@ static struct fsr_info {
asmlinkage void
do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
- struct fsr_info *inf;
+ const struct fsr_info *inf;
if (user_mode(regs) && addr == regs->ARM_pc) {
static int first = 1;
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index d04808ffa..c34c37203 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -6,7 +6,7 @@
*/
#include <linux/config.h>
-extern void die(const char *msg, struct pt_regs *regs, unsigned int err);
+extern void die(const char *msg, struct pt_regs *regs, int err);
/*
* This is useful to dump out the page tables associated with
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 92007d975..ddc69089a 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -60,6 +60,8 @@ __setup("noalign", noalign_setup);
__setup("nocache", nocache_setup);
__setup("nowb", nowrite_setup);
+#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+
/*
* need to get a 16k page for level 1
*/
@@ -71,9 +73,9 @@ pgd_t *get_pgd_slow(void)
if (pgd) {
pgd_t *init = pgd_offset_k(0);
- memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ memzero(pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+ memcpy(pgd + FIRST_KERNEL_PGD_NR, init + FIRST_KERNEL_PGD_NR,
+ (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
clean_cache_area(pgd, PTRS_PER_PGD * sizeof(pgd_t));
/*
diff --git a/arch/arm/mm/mm-nexuspci.c b/arch/arm/mm/mm-nexuspci.c
index 5b66faa51..ccb6c8a5c 100644
--- a/arch/arm/mm/mm-nexuspci.c
+++ b/arch/arm/mm/mm-nexuspci.c
@@ -2,9 +2,9 @@
* arch/arm/mm/mm-nexuspci.c
* from arch/arm/mm/mm-ebsa110.c
*
- * Extra MM routines for the NexusPCI architecture
+ * Extra MM routines for the FTV/PCI architecture
*
- * Copyright (C) 1998 Phil Blundell
+ * Copyright (C) 1998-1999 Phil Blundell
* Copyright (C) 1998-1999 Russell King
*/
@@ -18,14 +18,14 @@
#include "map.h"
-#define SIZE(x) (sizeof(x) / sizeof(x[0]))
-
-const struct map_desc io_desc[] __initdata = {
- { 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { 0xffe00000, 0x20000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { 0xffc00000, 0x60000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { 0xfe000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
- { 0xfd000000, 0x88000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }
+struct map_desc io_desc[] __initdata = {
+ { INTCONT_BASE, INTCONT_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PLX_BASE, PLX_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIO_BASE, PLX_IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
+ { DUART_BASE, DUART_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { STATUS_BASE, STATUS_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }
};
+#define SIZE(x) (sizeof(x) / sizeof(x[0]))
+
unsigned int __initdata io_desc_size = SIZE(io_desc);
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 5fbafe77a..94c155232 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -28,6 +28,11 @@ SECTIONS
*(.init.task)
}
+ /DISCARD/ : { /* Exit code and data */
+ *(.text.exit)
+ *(.data.exit)
+ }
+
_text = .; /* Text and read-only data */
.text : {
*(.text)
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index 93b8946e7..d2a79ca9d 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -25,22 +25,6 @@ SECTIONS
__init_end = .;
}
- .ebsa285 : {
- __ebsa285_begin = .;
- *(.text.ebsa285)
- *(.data.ebsa285)
- . = ALIGN(4096);
- __ebsa285_end = .;
- }
-
- .netwinder : {
- __netwinder_begin = .;
- *(.text.netwinder)
- *(.data.netwinder)
- . = ALIGN(4096);
- __netwinder_end = .;
- }
-
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(.text)
@@ -65,11 +49,26 @@ SECTIONS
. = ALIGN(8192);
- .data : { /* Data */
+ .data : {
+ /*
+ * first, the init task union, aligned
+ * to an 8192 byte boundary.
+ */
*(.init.task)
+
+ /*
+ * then the cacheline aligned data
+ */
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
+
+ /*
+ * and the usual data section
+ */
*(.data)
CONSTRUCTORS
- _edata = .; /* End of data section */
+
+ _edata = .;
}
.bss : {
diff --git a/arch/i386/config.in b/arch/i386/config.in
index e074ea81d..1d5c0d5f7 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -49,8 +49,8 @@ if [ "$CONFIG_MK7" = "y" ]; then
define_bool CONFIG_X86_USE_3DNOW y
fi
-if [ "$CONFIG_PROC_FS" = "y" ]; then
- tristate '/proc/driver/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
+if [ "$CONFIG_DEVFS_FS" = "y" ]; then
+ tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
fi
choice 'High Memory Support' \
@@ -139,30 +139,31 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-source drivers/parport/Config.in
+bool 'Power Management support' CONFIG_PM
-bool 'ACPI support' CONFIG_ACPI
+dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM
if [ "$CONFIG_ACPI" != "n" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP
+ bool ' Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP
fi
fi
-tristate 'Advanced Power Management BIOS support' CONFIG_APM
+dep_tristate ' Advanced Power Management BIOS support' CONFIG_APM $CONFIG_PM
if [ "$CONFIG_APM" != "n" ]; then
- bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
- bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
- bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
- bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
- bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
- bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
- bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
- bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
+ bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
+ bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
+ bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
+ bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
+ bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+ bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+ bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
+ bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
+ bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
fi
endmenu
+source drivers/parport/Config.in
source drivers/pnp/Config.in
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 34b453c2c..f2517c27d 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -27,7 +27,6 @@ CONFIG_X86_POPAD_OK=y
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
CONFIG_X86_PGE=y
-# CONFIG_MICROCODE is not set
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
@@ -74,9 +73,10 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
-# CONFIG_PARPORT is not set
+CONFIG_PM=y
CONFIG_ACPI=y
# CONFIG_APM is not set
+# CONFIG_PARPORT is not set
#
# Plug and Play configuration
@@ -96,6 +96,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -264,6 +265,7 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_SB1000 is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 3b7bb1258..6671bb35b 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -40,7 +40,6 @@ else
endif
endif
-ifeq ($(CONFIG_PROC_FS),y)
ifeq ($(CONFIG_MICROCODE),y)
OX_OBJS += microcode.o
else
@@ -48,7 +47,6 @@ else
MX_OBJS += microcode.o
endif
endif
-endif
ifeq ($(CONFIG_ACPI),y)
O_OBJS += acpi.o
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index 6228805db..b19097420 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -977,11 +977,9 @@ static void acpi_enter_sx(acpi_sstate_t state)
typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
- if (state != ACPI_S0) {
- acpi_sleep_start = get_cmos_time();
- acpi_enter_dx(ACPI_D3);
- acpi_sleep_state = state;
- }
+ acpi_sleep_start = get_cmos_time();
+ acpi_enter_dx(ACPI_D3);
+ acpi_sleep_state = state;
// clear wake status
acpi_write_pm1_status(acpi_facp, ACPI_WAK);
@@ -996,17 +994,11 @@ static void acpi_enter_sx(acpi_sstate_t state)
outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt);
}
- if (state == ACPI_S0) {
- acpi_sleep_state = state;
- acpi_enter_dx(ACPI_D0);
- acpi_sleep_start = 0;
- }
- else if (state == ACPI_S1) {
- // wait until S1 is entered
- while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ;
- // finished sleeping, update system time
- acpi_update_clock();
- }
+ // wait until S1 is entered
+ while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ;
+ // finished sleeping, update system time
+ acpi_update_clock();
+ acpi_enter_dx(ACPI_D0);
}
}
@@ -1292,7 +1284,6 @@ static int acpi_do_sleep(ctl_table *ctl,
{
#ifdef CONFIG_ACPI_S1_SLEEP
acpi_enter_sx(ACPI_S1);
- acpi_enter_sx(ACPI_S0);
#endif
}
file->f_pos += *len;
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index ec33f2269..b14f8caf3 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -131,7 +131,7 @@ static spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
static void end_8259A_irq (unsigned int irq)
{
- if (!(irq_desc[irq].status & IRQ_DISABLED))
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_8259A_irq(irq);
}
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 129a587f0..02669540f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -18,6 +18,7 @@
#include <linux/mm.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -1160,7 +1161,7 @@ static void end_level_ioapic_irq (unsigned int i)
static void mask_and_ack_level_ioapic_irq (unsigned int i) { /* nothing */ }
-static void set_ioapic_affinity (unsigned int irq, unsigned int mask)
+static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
{
unsigned long flags;
/*
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 7054249e6..4163626f4 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -32,7 +32,6 @@
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
-#include <linux/irq.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -184,24 +183,43 @@ int get_irq_list(char *buf)
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile int global_irq_lock;
+extern void show_stack(unsigned long* esp);
+
static void show(char * str)
{
int i;
- unsigned long *stack;
int cpu = smp_processor_id();
printk("\n%s, CPU %d:\n", str, cpu);
- printk("irq: %d [%d %d]\n",
- irqs_running(), local_irq_count(0), local_irq_count(1));
- printk("bh: %d [%d %d]\n",
- spin_is_locked(&global_bh_lock) ? 1 : 0, local_bh_count(0), local_bh_count(1));
- stack = (unsigned long *) &stack;
- for (i = 40; i ; i--) {
- unsigned long x = *++stack;
- if (x > (unsigned long) &get_option && x < (unsigned long) &vsprintf) {
- printk("<[%08lx]> ", x);
+ printk("irq: %d [",irqs_running());
+ for(i=0;i < smp_num_cpus;i++)
+ printk(" %d",local_irq_count(i));
+ printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
+ for(i=0;i < smp_num_cpus;i++)
+ printk(" %d",local_bh_count(i));
+
+ printk(" ]\nStack dumps:");
+ for(i=0;i< smp_num_cpus;i++) {
+ unsigned long esp;
+ if(i==cpu)
+ continue;
+ printk("\nCPU %d:",i);
+ esp = init_tss[i].esp0;
+ if(esp==NULL) {
+ /* tss->esp0 is set to NULL in cpu_init(),
+ * it's initialized when the cpu returns to user
+ * space. -- manfreds
+ */
+ printk(" <unknown> ");
+ continue;
}
- }
+ esp &= ~(THREAD_SIZE-1);
+ esp += sizeof(struct task_struct);
+ show_stack((void*)esp);
+ }
+ printk("\nCPU %d:",cpu);
+ show_stack(NULL);
+ printk("\n");
}
#define MAXCOUNT 100000000
@@ -874,7 +892,7 @@ 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];
-unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0xffffffff};
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
#define HEX_DIGITS 8
@@ -883,7 +901,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off,
{
if (count < HEX_DIGITS+1)
return -EINVAL;
- return sprintf (page, "%08x\n", irq_affinity[(int)data]);
+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
}
static unsigned int parse_hex_value (const char *buffer,
@@ -926,7 +944,7 @@ out:
static int irq_affinity_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data)
{
- int irq = (int) data, full_count = count, err;
+ int irq = (long) data, full_count = count, err;
unsigned long new_value;
if (!irq_desc[irq].handler->set_affinity)
@@ -993,7 +1011,7 @@ static void register_irq_proc (unsigned int irq)
entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
entry->nlink = 1;
- entry->data = (void *)irq;
+ entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc;
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 84490b40b..f858d7da9 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -23,20 +23,23 @@
* 1.02 21 February 2000, Tigran Aivazian <tigran@sco.com>
* Added 'device trimming' support. open(O_WRONLY) zeroes
* and frees the saved copy of applied microcode.
+ * 1.03 29 February 2000, Tigran Aivazian <tigran@sco.com>
+ * Made to use devfs (/dev/cpu/microcode) + cleanups.
*/
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
-#include <linux/proc_fs.h>
+#include <linux/devfs_fs_kernel.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
-#define MICROCODE_VERSION "1.02"
+#define MICROCODE_VERSION "1.03"
MODULE_DESCRIPTION("CPU (P6) microcode update driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@ocston.org>");
@@ -60,9 +63,10 @@ static void do_update_one(void *);
static unsigned long microcode_status = 0;
/* the actual array of microcode blocks, each 2048 bytes */
-static struct microcode * microcode = NULL;
+static struct microcode *microcode = NULL;
static unsigned int microcode_num = 0;
static char *mc_applied = NULL; /* holds an array of applied microcode blocks */
+static unsigned int mc_fsize; /* used often, so compute once at microcode_init() */
static struct file_operations microcode_fops = {
read: microcode_read,
@@ -71,23 +75,25 @@ static struct file_operations microcode_fops = {
release: microcode_release,
};
-static struct proc_dir_entry *proc_microcode;
+static devfs_handle_t devfs_handle;
static int __init microcode_init(void)
{
- proc_microcode = create_proc_entry("microcode", S_IWUSR|S_IRUSR, proc_root_driver);
- if (!proc_microcode) {
- printk(KERN_ERR "microcode: can't create /proc/driver/microcode\n");
- return -ENOMEM;
- }
- proc_microcode->proc_fops = &microcode_fops;
+ devfs_handle = devfs_register(NULL, "cpu/microcode", 0, DEVFS_FL_DEFAULT, 0, 0,
+ S_IFREG | S_IRUSR | S_IWUSR, 0, 0, &microcode_fops, NULL);
+ if (!devfs_handle) {
+ printk(KERN_ERR "microcode: can't create /dev/cpu/microcode\n");
+ return -ENOMEM;
+ }
+ /* XXX assume no hotplug CPUs so smp_num_cpus does not change */
+ mc_fsize = smp_num_cpus * sizeof(struct microcode);
printk(KERN_INFO "P6 Microcode Update Driver v%s registered\n", MICROCODE_VERSION);
return 0;
}
static void __exit microcode_exit(void)
{
- remove_proc_entry("microcode", proc_root_driver);
+ devfs_unregister(devfs_handle);
if (mc_applied)
kfree(mc_applied);
printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n", MICROCODE_VERSION);
@@ -108,25 +114,21 @@ static int microcode_open(struct inode *inode, struct file *file)
if (test_and_set_bit(MICROCODE_IS_OPEN, &microcode_status))
return -EBUSY;
- if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
- proc_microcode->size = 0;
- if (mc_applied) {
- memset(mc_applied, 0, smp_num_cpus * sizeof(struct microcode));
- kfree(mc_applied);
- mc_applied = NULL;
- }
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY && mc_applied) {
+ devfs_set_file_size(devfs_handle, 0);
+ memset(mc_applied, 0, mc_fsize);
+ kfree(mc_applied);
+ mc_applied = NULL;
}
MOD_INC_USE_COUNT;
-
return 0;
}
static int microcode_release(struct inode *inode, struct file *file)
{
- MOD_DEC_USE_COUNT;
-
clear_bit(MICROCODE_IS_OPEN, &microcode_status);
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -156,19 +158,17 @@ static int do_microcode_update(void)
memcpy(m, &microcode[update_req[i].slot], sizeof(struct microcode));
}
}
- return error ? -EIO : 0;
+ return error;
}
static void do_update_one(void *arg)
{
- struct update_req *req;
- struct cpuinfo_x86 * c;
+ int cpu_num = smp_processor_id();
+ struct cpuinfo_x86 *c = cpu_data + cpu_num;
+ struct update_req *req = (struct update_req *)arg + cpu_num;
unsigned int pf = 0, val[2], rev, sig;
- int i, cpu_num;
+ int i;
- cpu_num = smp_processor_id();
- c = cpu_data + cpu_num;
- req = (struct update_req *)arg + cpu_num;
req->err = 1; /* be pessimistic */
if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6)
@@ -210,8 +210,8 @@ static void do_update_one(void *arg)
req->err = 0;
req->slot = i;
- printk(KERN_ERR "microcode: CPU%d microcode updated "
- "from revision %d to %d, date=%08x\n",
+ printk(KERN_ERR "microcode: CPU%d updated from revision "
+ "%d to %d, date=%08x\n",
cpu_num, rev, val[1], m->date);
}
break;
@@ -220,12 +220,10 @@ static void do_update_one(void *arg)
static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
{
- size_t fsize = smp_num_cpus * sizeof(struct microcode);
-
- if (!proc_microcode->size || *ppos >= fsize)
- return 0; /* EOF */
- if (*ppos + len > fsize)
- len = fsize - *ppos;
+ if (*ppos >= mc_fsize)
+ return 0;
+ if (*ppos + len > mc_fsize)
+ len = mc_fsize - *ppos;
if (copy_to_user(buf, mc_applied + *ppos, len))
return -EFAULT;
*ppos += len;
@@ -242,33 +240,34 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l
return -EINVAL;
}
if (!mc_applied) {
- int size = smp_num_cpus * sizeof(struct microcode);
- mc_applied = kmalloc(size, GFP_KERNEL);
+ mc_applied = kmalloc(mc_fsize, GFP_KERNEL);
if (!mc_applied) {
- printk(KERN_ERR "microcode: can't allocate memory for saved microcode\n");
+ printk(KERN_ERR "microcode: out of memory for saved microcode\n");
return -ENOMEM;
}
- memset(mc_applied, 0, size);
+ memset(mc_applied, 0, mc_fsize);
}
lock_kernel();
microcode_num = len/sizeof(struct microcode);
microcode = vmalloc(len);
if (!microcode) {
- unlock_kernel();
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_unlock;
}
if (copy_from_user(microcode, buf, len)) {
- vfree(microcode);
- unlock_kernel();
- return -EFAULT;
+ ret = -EFAULT;
+ goto out_vfree;
}
- ret = do_microcode_update();
- if (!ret) {
- proc_microcode->size = smp_num_cpus * sizeof(struct microcode);
- ret = (ssize_t)len;
+ if(do_microcode_update()) {
+ ret = -EIO;
+ goto out_vfree;
}
+ devfs_set_file_size(devfs_handle, mc_fsize);
+ ret = (ssize_t)len;
+out_vfree:
vfree(microcode);
+out_unlock:
unlock_kernel();
return ret;
}
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index d5b2b0062..a76c92d25 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -1044,6 +1044,45 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
}
+static void set_level_irq(unsigned irq)
+{
+ unsigned char mask = 1 << (irq & 7);
+ unsigned int port = 0x4d0 + (irq >> 3);
+ unsigned char val = inb(port);
+
+ if (val & mask) {
+ printk("PCI irq %d was level\n", irq);
+ return;
+ }
+ printk("PCI irq %d was edge, turning into level-triggered\n", irq);
+ outb(val | mask, port);
+}
+
+static int ali_set_irq(struct pci_dev *router, unsigned pirq, unsigned irq)
+{
+ if (irq < 15) {
+ static unsigned char irqmap[16] = {
+ 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15
+ };
+ unsigned char val = irqmap[irq];
+ if (val && pirq < 8) {
+ u8 byte;
+ unsigned offset = 0x48 + (pirq >> 1);
+ unsigned shift = (pirq & 1) << 2;
+ pci_read_config_byte(router, offset, &byte);
+ printk("ALI: old %04x=%02x\n", offset, byte);
+ byte &= ~(0xf << shift);
+ byte |= val << shift;
+ printk("ALI: new %04x=%02x\n", offset, byte);
+ pci_write_config_byte(router, offset, byte);
+ set_level_irq(irq);
+ return irq;
+ }
+ }
+ return 0;
+}
+
+
/*
* In case BIOS forgets to tell us about IRQ, we try to look it up in the routing
* table, but unfortunately we have to know the interrupt router chip.
@@ -1135,6 +1174,10 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
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;
default:
DBG(" -> unknown router %04x/%04x\n", rt->rtr_vendor, rt->rtr_device);
if (newirq && mask == (1 << newirq)) {
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 19f7022a4..a043b4cfe 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -693,7 +693,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
int error;
char * filename;
- lock_kernel();
filename = getname((char *) regs.ebx);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -703,7 +702,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
current->flags &= ~PF_DTRACE;
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index a973746b9..d9af88d82 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -419,13 +419,19 @@ static void setup_frame(int sig, struct k_sigaction *ka,
? current->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
+ if (err)
+ goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+ if (err)
+ goto give_sigsegv;
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
+ if (err)
+ goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -486,6 +492,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= __copy_to_user(&frame->info, info, sizeof(*info));
+ if (err)
+ goto give_sigsegv;
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -497,6 +505,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7400b628b..3a7004970 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#ifdef CONFIG_MCA
#include <linux/mca.h>
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 8b1324520..b9e535a71 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -631,13 +631,14 @@ 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) {
ClearPageReserved(mem_map + MAP_NR(start));
set_page_count(mem_map+MAP_NR(start), 1);
free_page(start);
totalram_pages++;
}
- printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
}
#endif
diff --git a/arch/mips/arc/console.c b/arch/mips/arc/console.c
index 4675eb4a1..4de5130fb 100644
--- a/arch/mips/arc/console.c
+++ b/arch/mips/arc/console.c
@@ -4,8 +4,9 @@
* Copyright (C) 1996 David S. Miller (dm@sgi.com)
* Compability with board caches, Ulf Carlsson
*
- * $Id: console.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $
+ * $Id: console.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <asm/sgialib.h>
#include <asm/bcache.h>
diff --git a/arch/mips/arc/init.c b/arch/mips/arc/init.c
index 32117b858..81cf6cf74 100644
--- a/arch/mips/arc/init.c
+++ b/arch/mips/arc/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.3 1999/08/20 21:59:01 ralf Exp $
+/* $Id: init.c,v 1.4 1999/10/09 00:00:57 ralf Exp $
* This file is subject to the terms and conditions of the GNU General Public+
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -9,7 +9,6 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <asm/sgialib.h>
diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c
index 4582297c2..d1c530fda 100644
--- a/arch/mips/arc/memory.c
+++ b/arch/mips/arc/memory.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: memory.c,v 1.9 2000/01/27 01:05:23 ralf Exp $
+ * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -13,7 +13,6 @@
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/swap.h>
-#include <linux/config.h>
#include <asm/sgialib.h>
#include <asm/page.h>
diff --git a/arch/mips/arc/printf.c b/arch/mips/arc/printf.c
index 17e5fe352..78b1b5937 100644
--- a/arch/mips/arc/printf.c
+++ b/arch/mips/arc/printf.c
@@ -4,8 +4,9 @@
*
* Copyright (C) 1996 David S. Miller (dm@sgi.com)
*
- * $Id: printf.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $
+ * $Id: printf.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
diff --git a/arch/mips/baget/balo_supp.S b/arch/mips/baget/balo_supp.S
index 6b79d22d3..96f2a8f50 100644
--- a/arch/mips/baget/balo_supp.S
+++ b/arch/mips/baget/balo_supp.S
@@ -1,10 +1,9 @@
-/* $Id$
+/* $Id: balo_supp.S,v 1.1 1999/01/17 03:49:38 ralf Exp $
* balo_supp.S: BAget Loader supplement
*
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
*/
-#include <linux/config.h>
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
diff --git a/arch/mips/baget/prom/init.c b/arch/mips/baget/prom/init.c
index ad576f984..a87c004ec 100644
--- a/arch/mips/baget/prom/init.c
+++ b/arch/mips/baget/prom/init.c
@@ -3,10 +3,9 @@
*
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
*
- * $Id: init.c,v 1.2 1999/08/17 22:18:38 ralf Exp $
+ * $Id: init.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
*/
#include <linux/init.h>
-#include <linux/config.h>
#include <asm/bootinfo.h>
char arcs_cmdline[CL_SIZE];
diff --git a/arch/mips/baget/setup.c b/arch/mips/baget/setup.c
index 07a7ede00..dd0a7733e 100644
--- a/arch/mips/baget/setup.c
+++ b/arch/mips/baget/setup.c
@@ -1,11 +1,10 @@
-/* $Id: setup.c,v 1.3 1999/08/13 17:07:26 harald Exp $
+/* $Id: setup.c,v 1.4 1999/10/09 00:00:57 ralf Exp $
*
* setup.c: Baget/MIPS specific setup, including init of the feature struct.
*
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
*
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/arch/mips/ddb5074/irq.c b/arch/mips/ddb5074/irq.c
index 1faba4c5c..4fee350e2 100644
--- a/arch/mips/ddb5074/irq.c
+++ b/arch/mips/ddb5074/irq.c
@@ -4,9 +4,10 @@
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Suprastructure Center Europe (SUPC-E), Brussels
*
- * $Id$
+ * $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/arch/mips/ddb5074/pci.c b/arch/mips/ddb5074/pci.c
index 50dffdcc2..e0f39c666 100644
--- a/arch/mips/ddb5074/pci.c
+++ b/arch/mips/ddb5074/pci.c
@@ -5,16 +5,14 @@
* Albert Dorofeev <albert@sonycom.com>
* Sony Suprastructure Center Europe (SUPC-E), Brussels
*
- * $Id: pci.c,v 1.3 2000/02/16 01:45:55 ralf Exp $
+ * $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $
*/
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/sched.h>
-#include <linux/pci.h>
#include <linux/ioport.h>
#include <asm-mips/nile4.h>
diff --git a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c
index 421d4058b..27b31818a 100644
--- a/arch/mips/dec/prom/cmdline.c
+++ b/arch/mips/dec/prom/cmdline.c
@@ -3,11 +3,10 @@
*
* Copyright (C) 1998 Harald Koerfgen
*
- * $Id: cmdline.c,v 1.1 1999/01/17 03:49:44 ralf Exp $
+ * $Id: cmdline.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
index dbb1e98bc..6acacc1c4 100644
--- a/arch/mips/dec/prom/identify.c
+++ b/arch/mips/dec/prom/identify.c
@@ -3,10 +3,9 @@
*
* Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
*
- * $Id: identify.c,v 1.1 1999/01/17 03:49:44 ralf Exp $
+ * $Id: identify.c,v 1.2 1999/10/09 00:00:58 ralf Exp $
*/
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 41ea11b98..fa9e68e6f 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -1,4 +1,4 @@
-/* $Id: irixelf.c,v 1.24 2000/02/04 07:40:23 ralf Exp $
+/* $Id: irixelf.c,v 1.25 2000/03/02 02:36:50 ralf Exp $
*
* irixelf.c: Code to load IRIX ELF executables which conform to
* the MIPS ABI.
@@ -29,6 +29,7 @@
#include <linux/shm.h>
#include <linux/personality.h>
#include <linux/elfcore.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -449,29 +450,31 @@ static inline int look_for_irix_interpreter(char **name,
*name = NULL;
for(i = 0; i < pnum; i++, epp++) {
- if(epp->p_type != PT_INTERP)
+ if (epp->p_type != PT_INTERP)
continue;
/* It is illegal to have two interpreters for one executable. */
- if(*name != NULL)
+ if (*name != NULL)
goto out;
*name = (char *) kmalloc((epp->p_filesz +
strlen(IRIX_INTERP_PREFIX)),
GFP_KERNEL);
- if(!*name)
+ if (!*name)
return -ENOMEM;
strcpy(*name, IRIX_INTERP_PREFIX);
retval = read_exec(bprm->dentry, epp->p_offset, (*name + 16),
epp->p_filesz, 1);
- if(retval < 0)
+ if (retval < 0)
goto out;
old_fs = get_fs(); set_fs(get_ds());
+ lock_kernel();
dentry = namei(*name);
+ unlock_kernel();
set_fs(old_fs);
- if(IS_ERR(dentry)) {
+ if (IS_ERR(dentry)) {
retval = PTR_ERR(dentry);
goto out;
}
@@ -485,7 +488,9 @@ static inline int look_for_irix_interpreter(char **name,
return 0;
dput_and_out:
+ lock_kernel();
dput(dentry);
+ unlock_kernel();
out:
kfree(*name);
return retval;
@@ -566,7 +571,9 @@ static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,
old_fs = get_fs();
set_fs(get_ds());
+ lock_kernel();
dput(identry);
+ unlock_kernel();
if(*eentry == 0xffffffff)
return -1;
@@ -682,10 +689,10 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
&interpreter_dentry,
&interp_elf_ex, elf_phdata, bprm,
elf_ex.e_phnum);
- if(retval)
+ if (retval)
goto out_free_file;
- if(elf_interpreter) {
+ if (elf_interpreter) {
retval = verify_irix_interpreter(&interp_elf_ex);
if(retval)
goto out_free_interp;
@@ -811,7 +818,9 @@ out:
return retval;
out_free_dentry:
+ lock_kernel();
dput(interpreter_dentry);
+ unlock_kernel();
out_free_interp:
if (elf_interpreter)
kfree(elf_interpreter);
diff --git a/arch/mips/kernel/r2300_misc.S b/arch/mips/kernel/r2300_misc.S
index 149012a1f..30031e295 100644
--- a/arch/mips/kernel/r2300_misc.S
+++ b/arch/mips/kernel/r2300_misc.S
@@ -1,4 +1,4 @@
-/* $Id: r2300_misc.S,v 1.7 1999/10/09 00:00:58 ralf Exp $
+/* $Id: r2300_misc.S,v 1.8 1999/12/08 22:05:10 harald Exp $
* misc.S: Misc. exception handling code for R3000/R2000.
*
* Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
@@ -10,8 +10,6 @@
* Copyright (c) 1998 Harald Koerfgen
* Copyright (c) 1998, 1999 Gleb Raiko & Vladimir Roganov
*/
-#include <linux/config.h>
-
#include <asm/asm.h>
#include <asm/current.h>
#include <asm/bootinfo.h>
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 0f5124280..d2df0dc20 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -1,4 +1,4 @@
-/* $Id: syscall.c,v 1.12 1999/12/04 03:59:00 ralf Exp $
+/* $Id: syscall.c,v 1.13 2000/02/04 07:40:23 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -129,7 +129,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
int error;
char * filename;
- lock_kernel();
filename = getname((char *) (long)regs.regs[4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -139,7 +138,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 362d6a760..0c07b8dd6 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.23 2000/02/04 07:40:23 ralf Exp $
+/* $Id: sysirix.c,v 1.24 2000/02/05 06:47:08 ralf Exp $
*
* sysirix.c: IRIX system call emulation.
*
@@ -878,7 +878,6 @@ asmlinkage int irix_exec(struct pt_regs *regs)
int error, base = 0;
char *filename;
- lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
filename = getname((char *) (long)regs->regs[base + 4]);
@@ -890,7 +889,6 @@ asmlinkage int irix_exec(struct pt_regs *regs)
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index a35da14d2..ea36ed5b2 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.13 1999/10/09 00:00:58 ralf Exp $
+/* $Id: time.c,v 1.14 2000/01/26 00:07:44 ralf Exp $
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
* Copyright (C) 1996, 1997, 1998 Ralf Baechle
@@ -6,6 +6,7 @@
* This file contains the time handling details for PC-style clocks as
* found in some MIPS systems.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/sched.h>
diff --git a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c
index afbbef5eb..cb5e1e66d 100644
--- a/arch/mips/mm/loadmmu.c
+++ b/arch/mips/mm/loadmmu.c
@@ -3,8 +3,9 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: loadmmu.c,v 1.14 2000/01/27 01:05:23 ralf Exp $
+ * $Id: loadmmu.c,v 1.15 2000/02/24 00:12:40 ralf Exp $
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/arch/mips/sgi/kernel/indy_int.c b/arch/mips/sgi/kernel/indy_int.c
index cab112c29..06d8573cb 100644
--- a/arch/mips/sgi/kernel/indy_int.c
+++ b/arch/mips/sgi/kernel/indy_int.c
@@ -1,4 +1,4 @@
-/* $Id: indy_int.c,v 1.17 2000/02/04 07:40:23 ralf Exp $
+/* $Id: indy_int.c,v 1.18 2000/03/02 02:36:50 ralf Exp $
*
* indy_int.c: Routines for generic manipulation of the INT[23] ASIC
* found on INDY workstations..
@@ -9,7 +9,6 @@
* - Indigo2 changes
* - Interrupt handling fixes
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
diff --git a/arch/mips64/arc/init.c b/arch/mips64/arc/init.c
index 496f296ef..b961fc899 100644
--- a/arch/mips64/arc/init.c
+++ b/arch/mips64/arc/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.3 1999/10/19 20:51:45 ralf Exp $
+/* $Id: init.c,v 1.3 1999/11/19 23:29:05 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -10,7 +10,6 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <asm/sgialib.h>
diff --git a/arch/mips64/arc/memory.c b/arch/mips64/arc/memory.c
index 78a37a841..58d4835ea 100644
--- a/arch/mips64/arc/memory.c
+++ b/arch/mips64/arc/memory.c
@@ -1,4 +1,4 @@
-/* $Id: memory.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
+/* $Id: memory.c,v 1.5 2000/01/27 23:21:57 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -13,7 +13,6 @@
* because on some machines like SGI IP27 the ARC memory configuration data
* completly bogus and alternate easier to use mechanisms are available.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -21,7 +20,6 @@
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/swap.h>
-#include <linux/config.h>
#include <asm/sgialib.h>
#include <asm/page.h>
diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22
index b40469cfc..4caa8e70d 100644
--- a/arch/mips64/defconfig-ip22
+++ b/arch/mips64/defconfig-ip22
@@ -134,6 +134,7 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_SB1000 is not set
diff --git a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c
index 6983cfdc2..109c4d37b 100644
--- a/arch/mips64/kernel/signal32.c
+++ b/arch/mips64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: signal32.c,v 1.2 2000/02/18 00:03:48 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -8,7 +8,6 @@
* Copyright (C) 1994 - 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
diff --git a/arch/mips64/kernel/syscall.c b/arch/mips64/kernel/syscall.c
index 67d84f874..ea225ff08 100644
--- a/arch/mips64/kernel/syscall.c
+++ b/arch/mips64/kernel/syscall.c
@@ -1,4 +1,4 @@
-/* $Id: syscall.c,v 1.2 2000/01/29 01:41:59 ralf Exp $
+/* $Id: syscall.c,v 1.3 2000/02/04 07:40:24 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -7,7 +7,6 @@
* Copyright (C) 1995 - 1999 by Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/mm.h>
@@ -109,7 +108,6 @@ asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs)
int error;
char * filename;
- lock_kernel();
filename = getname((char *) (long)regs.regs[4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -119,7 +117,6 @@ asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs)
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/mips64/sgi-ip27/ip27-init.c b/arch/mips64/sgi-ip27/ip27-init.c
index f6b3d6e09..e09bc6036 100644
--- a/arch/mips64/sgi-ip27/ip27-init.c
+++ b/arch/mips64/sgi-ip27/ip27-init.c
@@ -7,7 +7,6 @@
#include <asm/sn/klconfig.h>
#include <asm/ioc3.h>
#include <asm/mipsregs.h>
-#include <asm/sn/klconfig.h>
#include <asm/sn/gda.h>
typedef unsigned long cpumask_t; /* into asm/sn/types.h */
diff --git a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c
index c9e6fe150..d7ddb8682 100644
--- a/arch/mips64/sgi-ip27/ip27-irq.c
+++ b/arch/mips64/sgi-ip27/ip27-irq.c
@@ -1,11 +1,10 @@
-/* $Id: ip27-irq.c,v 1.6 2000/02/10 05:58:56 dagum Exp $
+/* $Id: ip27-irq.c,v 1.7 2000/03/02 02:36:50 ralf Exp $
*
* ip27-irq.c: Highlevel interrupt handling for IP27 architecture.
*
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
diff --git a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c
index bf85c06f2..e5f174ab1 100644
--- a/arch/mips64/sgi-ip27/ip27-rtc.c
+++ b/arch/mips64/sgi-ip27/ip27-rtc.c
@@ -192,16 +192,9 @@ static int rtc_release(struct inode *inode, struct file *file)
*/
static struct file_operations rtc_fops = {
- NULL, /* No llseek (yet) */
- NULL, /* No read (yet) */
- NULL, /* No write */
- NULL, /* No readdir */
- NULL, /* No poll (yet) */
- rtc_ioctl,
- NULL, /* No mmap */
- rtc_open,
- NULL, /* flush */
- rtc_release
+ ioctl: rtc_ioctl,
+ open: rtc_open,
+ release: rtc_release,
};
static struct miscdevice rtc_dev=
diff --git a/arch/mips64/sgi-ip27/ip27-setup.c b/arch/mips64/sgi-ip27/ip27-setup.c
index c97eeb8b6..f0d7d66ab 100644
--- a/arch/mips64/sgi-ip27/ip27-setup.c
+++ b/arch/mips64/sgi-ip27/ip27-setup.c
@@ -1,4 +1,4 @@
-/* $Id: ip27-setup.c,v 1.3 2000/01/21 22:34:03 ralf Exp $
+/* $Id: ip27-setup.c,v 1.6 2000/02/05 02:12:32 kanoj Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -19,7 +19,6 @@
#include <asm/sn/klconfig.h>
#include <asm/ioc3.h>
#include <asm/mipsregs.h>
-#include <asm/sn/klconfig.h>
/* Check against user dumbness. */
#ifdef CONFIG_VT
diff --git a/arch/mips64/sgi-ip27/ip27-timer.c b/arch/mips64/sgi-ip27/ip27-timer.c
index c75fa725f..ff6ea60e7 100644
--- a/arch/mips64/sgi-ip27/ip27-timer.c
+++ b/arch/mips64/sgi-ip27/ip27-timer.c
@@ -1,4 +1,4 @@
-/* $Id: ip27-timer.c,v 1.2 2000/01/27 01:05:24 ralf Exp $
+/* $Id: ip27-timer.c,v 1.3 2000/02/18 09:54:40 ulfc Exp $
*
* Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
* Copytight (C) 1999 Silicon Graphics, Inc.
@@ -148,13 +148,10 @@ void do_settimeofday(struct timeval *tv)
}
/* Includes for ioc3_init(). */
-#include <linux/init.h>
#include <asm/sn/types.h>
#include <asm/sn/sn0/addrs.h>
#include <asm/sn/sn0/hubni.h>
#include <asm/sn/sn0/hubio.h>
-#include <asm/sn/klconfig.h>
-#include <asm/ioc3.h>
#include <asm/pci/bridge.h>
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index ebaa64806..756e531c2 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.86 2000/02/10 02:51:10 davem Exp $
+# $Id: config.in,v 1.87 2000/02/27 19:34:12 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -163,6 +163,7 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
tristate ' Dummy net driver support' CONFIG_DUMMY
+ tristate ' Bonding driver support' CONFIG_BONDING
tristate ' PPP (point-to-point) support' CONFIG_PPP
if [ ! "$CONFIG_PPP" = "n" ]; then
dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 7589958c8..580d004d7 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -218,6 +218,7 @@ CONFIG_SCSI_FCAL=m
#
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
+CONFIG_BONDING=m
CONFIG_PPP=m
CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
@@ -240,7 +241,7 @@ CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=m
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f0dbea065..e9b506e10 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.34 2000/02/18 13:48:48 davem Exp $
+/* $Id: ioport.c,v 1.35 2000/02/27 08:16:25 davem Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 335eba208..b497201f5 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.13 2000/02/12 03:05:37 zaitcev Exp $
+/* $Id: pcic.c,v 1.14 2000/03/01 02:53:28 davem Exp $
* pcic.c: Sparc/PCI controller support
*
* Copyright (C) 1998 V. Roganov and G. Raiko
@@ -884,13 +884,6 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size
{
}
-#if 0
-int pci_assign_resource(struct pci_dev *dev, int i)
-{
- return -ENOSYS; /* :-)... actually implement this soon */
-}
-#endif
-
int pcibios_enable_device(struct pci_dev *pdev)
{
return 0;
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index c24d8649c..d167d5de7 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.145 2000/01/29 01:08:56 anton Exp $
+/* $Id: process.c,v 1.146 2000/03/01 02:53:27 davem Exp $
* linux/arch/sparc/kernel/process.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -652,7 +652,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
if(regs->u_regs[UREG_G1] == 0)
base = 1;
- lock_kernel();
filename = getname((char *)regs->u_regs[base + UREG_I0]);
error = PTR_ERR(filename);
if(IS_ERR(filename))
@@ -661,7 +660,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
(char **) regs->u_regs[base + UREG_I2], regs);
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index bee2a5574..47c6a5afd 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.95 2000/02/10 02:51:12 davem Exp $
+# $Id: config.in,v 1.99 2000/02/27 19:34:17 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -112,6 +112,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
define_bool CONFIG_IDEDMA_NEW_DRIVE_LISTINGS y
define_bool CONFIG_BLK_DEV_NS87415 y
define_bool CONFIG_BLK_DEV_CMD64X y
+ define_bool CONFIG_BLK_DEV_IDE_MODES y
fi
fi
@@ -200,6 +201,7 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
tristate ' Dummy net driver support' CONFIG_DUMMY
+ tristate ' Bonding driver support' CONFIG_BONDING
tristate ' PPP (point-to-point) support' CONFIG_PPP
if [ ! "$CONFIG_PPP" = "n" ]; then
dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 12e9432a7..7e7a45a70 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -136,6 +136,7 @@ CONFIG_IDEDMA_AUTO=y
CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
CONFIG_BLK_DEV_NS87415=y
CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_IDE_MODES=y
#
# Networking options
@@ -254,6 +255,7 @@ CONFIG_SCSI_FCAL=m
#
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
+CONFIG_BONDING=m
CONFIG_PPP=m
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index ed9e49685..d2bc6baf5 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.84 2000/02/25 05:44:41 davem Exp $
+/* $Id: irq.c,v 1.85 2000/03/02 02:00:24 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -955,7 +955,7 @@ int probe_irq_off(unsigned long mask)
void init_timers(void (*cfunc)(int, void *, struct pt_regs *),
unsigned long *clock)
{
- unsigned long flags;
+ unsigned long pstate;
extern unsigned long timer_tick_offset;
int node, err;
#ifdef __SMP__
@@ -978,31 +978,57 @@ void init_timers(void (*cfunc)(int, void *, struct pt_regs *),
prom_halt();
}
- save_and_cli(flags);
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
/* Set things up so user can access tick register for profiling
- * purposes.
+ * purposes. Also workaround BB_ERRATA_1 by doing a dummy
+ * read back of %tick after writing it.
*/
__asm__ __volatile__("
sethi %%hi(0x80000000), %%g1
- sllx %%g1, 32, %%g1
- rd %%tick, %%g2
+ ba,pt %%xcc, 1f
+ sllx %%g1, 32, %%g1
+ .align 64
+ 1: rd %%tick, %%g2
add %%g2, 6, %%g2
andn %%g2, %%g1, %%g2
wrpr %%g2, 0, %%tick
-" : /* no outputs */
+ rdpr %%tick, %%g0"
+ : /* no outputs */
: /* no inputs */
: "g1", "g2");
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ */
__asm__ __volatile__("
rd %%tick, %%g1
- add %%g1, %0, %%g1
- wr %%g1, 0x0, %%tick_cmpr"
+ ba,pt %%xcc, 1f
+ add %%g1, %0, %%g1
+ .align 64
+ 1: wr %%g1, 0x0, %%tick_cmpr
+ rd %%tick_cmpr, %%g0"
: /* no outputs */
: "r" (timer_tick_offset)
: "g1");
- restore_flags(flags);
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
+
sti();
}
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 3cf95bb86..cd28d9392 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.15 2000/02/08 05:11:29 jj Exp $
+/* $Id: pci.c,v 1.16 2000/03/01 02:53:33 davem Exp $
* pci.c: UltraSparc PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -218,11 +218,6 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size
{
}
-int pci_assign_resource(struct pci_dev *dev, int i)
-{
- return -ENOSYS; /* :-)... actually implement this soon */
-}
-
int pcibios_enable_device(struct pci_dev *pdev)
{
return 0;
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 503f5b875..dd71b1e92 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.103 2000/01/21 11:38:53 jj Exp $
+/* $Id: process.c,v 1.104 2000/03/01 02:53:32 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -779,24 +779,22 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
/* User register window flush is done by entry.S */
/* Check for indirect call. */
- if(regs->u_regs[UREG_G1] == 0)
+ if (regs->u_regs[UREG_G1] == 0)
base = 1;
- lock_kernel();
filename = getname((char *)regs->u_regs[base + UREG_I0]);
error = PTR_ERR(filename);
- if(IS_ERR(filename))
+ if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1],
(char **) regs->u_regs[base + UREG_I2], regs);
putname(filename);
- if(!error) {
+ if (!error) {
fprs_write(0);
current->thread.xfsr[0] = 0;
current->thread.fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF;
}
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 273c12de1..175372877 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -119,6 +119,7 @@ extern void cpu_probe(void);
void __init smp_callin(void)
{
int cpuid = hard_smp_processor_id();
+ unsigned long pstate;
inherit_locked_prom_mappings(0);
@@ -127,18 +128,37 @@ void __init smp_callin(void)
cpu_probe();
- /* Master did this already, now is the time for us to do it. */
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Set things up so user can access tick register for profiling
+ * purposes. Also workaround BB_ERRATA_1 by doing a dummy
+ * read back of %tick after writing it.
+ */
__asm__ __volatile__("
sethi %%hi(0x80000000), %%g1
- sllx %%g1, 32, %%g1
- rd %%tick, %%g2
+ ba,pt %%xcc, 1f
+ sllx %%g1, 32, %%g1
+ .align 64
+1: rd %%tick, %%g2
add %%g2, 6, %%g2
andn %%g2, %%g1, %%g2
wrpr %%g2, 0, %%tick
-" : /* no outputs */
+ rdpr %%tick, %%g0"
+ : /* no outputs */
: /* no inputs */
: "g1", "g2");
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
+
smp_setup_percpu_timer();
__sti();
@@ -598,7 +618,7 @@ extern void update_one_process(struct task_struct *p, unsigned long ticks,
void smp_percpu_timer_interrupt(struct pt_regs *regs)
{
- unsigned long compare, tick;
+ unsigned long compare, tick, pstate;
int cpu = smp_processor_id();
int user = user_mode(regs);
@@ -664,27 +684,87 @@ do { hardirq_enter(cpu); \
prof_counter(cpu) = prof_multiplier(cpu);
}
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ *
+ * Just to be anal we add a workaround for Spitfire
+ * Errata 50 by preventing pipeline bypasses on the
+ * final read of the %tick register into a compare
+ * instruction. The Errata 50 description states
+ * that %tick is not prone to this bug, but I am not
+ * taking any chances.
+ */
__asm__ __volatile__("rd %%tick_cmpr, %0\n\t"
- "add %0, %2, %0\n\t"
- "wr %0, 0x0, %%tick_cmpr\n\t"
- "rd %%tick, %1"
+ "ba,pt %%xcc, 1f\n\t"
+ " add %0, %2, %0\n\t"
+ ".align 64\n"
+ "1: wr %0, 0x0, %%tick_cmpr\n\t"
+ "rd %%tick_cmpr, %%g0\n\t"
+ "rd %%tick, %1\n\t"
+ "mov %1, %1"
: "=&r" (compare), "=r" (tick)
: "r" (current_tick_offset));
+
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
} while (tick >= compare);
}
static void __init smp_setup_percpu_timer(void)
{
int cpu = smp_processor_id();
+ unsigned long pstate;
prof_counter(cpu) = prof_multiplier(cpu) = 1;
- __asm__ __volatile__("rd %%tick, %%g1\n\t"
- "add %%g1, %0, %%g1\n\t"
- "wr %%g1, 0x0, %%tick_cmpr"
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ */
+ __asm__ __volatile__("
+ rd %%tick, %%g1
+ ba,pt %%xcc, 1f
+ add %%g1, %0, %%g1
+ .align 64
+ 1: wr %%g1, 0x0, %%tick_cmpr
+ rd %%tick_cmpr, %%g0"
+ : /* no outputs */
+ : "r" (current_tick_offset)
+ : "g1");
+
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
- : "r" (current_tick_offset)
- : "g1");
+ : "r" (pstate));
}
void __init smp_tick_init(void)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 1ebb7772c..6e2d566b2 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.132 2000/02/16 07:31:35 davem Exp $
+/* $Id: sys_sparc32.c,v 1.133 2000/03/01 02:53:33 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3086,7 +3086,10 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
+ lock_kernel();
dentry = open_namei(filename, 0, 0);
+ unlock_kernel();
+
retval = PTR_ERR(dentry);
if (IS_ERR(dentry))
return retval;
@@ -3097,11 +3100,15 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count32(argv)) < 0) {
+ lock_kernel();
dput(dentry);
+ unlock_kernel();
return bprm.argc;
}
if ((bprm.envc = count32(envp)) < 0) {
+ lock_kernel();
dput(dentry);
+ unlock_kernel();
return bprm.envc;
}
@@ -3129,8 +3136,11 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
out:
/* Something went wrong, return the inode and free the argument pages*/
- if (bprm.dentry)
+ if (bprm.dentry) {
+ lock_kernel();
dput(bprm.dentry);
+ unlock_kernel();
+ }
for (i=0 ; i<MAX_ARG_PAGES ; i++)
if (bprm.page[i])
@@ -3154,7 +3164,6 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
if((u32)regs->u_regs[UREG_G1] == 0)
base = 1;
- lock_kernel();
filename = getname32((char *)AA(regs->u_regs[base + UREG_I0]));
error = PTR_ERR(filename);
if(IS_ERR(filename))
@@ -3171,7 +3180,6 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
regs->tstate &= ~TSTATE_PEF;
}
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 57f5b1622..e599b48cb 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.23 1999/09/21 14:35:27 davem Exp $
+/* $Id: time.c,v 1.24 2000/03/02 02:00:25 davem Exp $
* time.c: UltraSparc timer and TOD clock support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -69,20 +69,53 @@ static __inline__ void timer_check_rtc(void)
static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
- unsigned long ticks;
+ unsigned long ticks, pstate;
write_lock(&xtime_lock);
do {
do_timer(regs);
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ *
+ * Just to be anal we add a workaround for Spitfire
+ * Errata 50 by preventing pipeline bypasses on the
+ * final read of the %tick register into a compare
+ * instruction. The Errata 50 description states
+ * that %tick is not prone to this bug, but I am not
+ * taking any chances.
+ */
__asm__ __volatile__("
rd %%tick_cmpr, %0
- add %0, %2, %0
- wr %0, 0, %%tick_cmpr
- rd %%tick, %1"
+ ba,pt %%xcc, 1f
+ add %0, %2, %0
+ .align 64
+ 1: wr %0, 0, %%tick_cmpr
+ rd %%tick_cmpr, %%g0
+ rd %%tick, %1
+ mov %1, %1"
: "=&r" (timer_tick_compare), "=r" (ticks)
: "r" (timer_tick_offset));
+
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
} while (ticks >= timer_tick_compare);
timer_check_rtc();