summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/pci-noop.c4
-rw-r--r--arch/alpha/kernel/pci_iommu.c24
-rw-r--r--arch/alpha/kernel/setup.c1
-rw-r--r--arch/alpha/kernel/systbls.S2
-rw-r--r--arch/arm/Kconfig21
-rw-r--r--arch/arm/common/time-acorn.c2
-rw-r--r--arch/arm/configs/ixp4xx_defconfig982
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/atags.c86
-rw-r--r--arch/arm/kernel/atags.h5
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/machine_kexec.c2
-rw-r--r--arch/arm/kernel/relocate_kernel.S30
-rw-r--r--arch/arm/kernel/setup.c33
-rw-r--r--arch/arm/kernel/smp.c41
-rw-r--r--arch/arm/mach-at91/Kconfig30
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c3
-rw-r--r--arch/arm/mach-at91/generic.h3
-rw-r--r--arch/arm/mach-at91/gpio.c89
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig14
-rw-r--r--arch/arm/mach-ixp4xx/Makefile8
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-power.c125
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c134
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c29
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_npe.c741
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_qmgr.c274
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-power.c69
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c174
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-power.c91
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c137
-rw-r--r--arch/arm/mach-pxa/Makefile5
-rw-r--r--arch/arm/mach-pxa/cm-x270.c1
-rw-r--r--arch/arm/mach-pxa/devices.c1
-rw-r--r--arch/arm/mach-pxa/generic.c150
-rw-r--r--arch/arm/mach-pxa/generic.h4
-rw-r--r--arch/arm/mach-pxa/gpio.c197
-rw-r--r--arch/arm/mach-pxa/irq.c64
-rw-r--r--arch/arm/mach-pxa/mfp.c11
-rw-r--r--arch/arm/mach-pxa/pcm027.c1
-rw-r--r--arch/arm/mach-pxa/poodle.c8
-rw-r--r--arch/arm/mach-pxa/pxa25x.c43
-rw-r--r--arch/arm/mach-pxa/pxa27x.c49
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c99
-rw-r--r--arch/arm/mach-pxa/sleep.S102
-rw-r--r--arch/arm/mach-pxa/smemc.c88
-rw-r--r--arch/arm/mach-pxa/spitz.c1
-rw-r--r--arch/arm/mach-pxa/tosa.c1
-rw-r--r--arch/arm/mach-realview/Kconfig21
-rw-r--r--arch/arm/mach-realview/Makefile3
-rw-r--r--arch/arm/mach-realview/core.c179
-rw-r--r--arch/arm/mach-realview/core.h71
-rw-r--r--arch/arm/mach-realview/localtimer.c144
-rw-r--r--arch/arm/mach-realview/platsmp.c20
-rw-r--r--arch/arm/mach-realview/realview_eb.c234
-rw-r--r--arch/arm/mach-sa1100/generic.c2
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/mm/pgd.c8
-rw-r--r--arch/arm/plat-iop/time.c4
-rw-r--r--arch/arm/plat-s3c24xx/time.c2
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/avr32/mach-at32ap/pio.c172
-rw-r--r--arch/avr32/mach-at32ap/pio.h2
-rw-r--r--arch/blackfin/mach-common/entry.S2
-rw-r--r--arch/cris/Kconfig5
-rw-r--r--arch/cris/arch-v10/Kconfig4
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig4
-rw-r--r--arch/cris/arch-v10/kernel/entry.S2
-rw-r--r--arch/cris/arch-v32/Kconfig4
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig4
-rw-r--r--arch/cris/arch-v32/drivers/pci/dma.c4
-rw-r--r--arch/frv/Kconfig9
-rw-r--r--arch/frv/kernel/vmlinux.lds.S2
-rw-r--r--arch/frv/mm/mmu-context.c2
-rw-r--r--arch/frv/mm/pgalloc.c2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c8
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c4
-rw-r--r--arch/m68k/Kconfig14
-rw-r--r--arch/m68k/Makefile11
-rw-r--r--arch/m68k/amiga/Makefile2
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c33
-rw-r--r--arch/m68k/amiga/amisound.c5
-rw-r--r--arch/m68k/amiga/chipram.c7
-rw-r--r--arch/m68k/amiga/config.c12
-rw-r--r--arch/m68k/amiga/pcmcia.c9
-rw-r--r--arch/m68k/atari/Makefile2
-rw-r--r--arch/m68k/atari/ataints.c3
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c2
-rw-r--r--arch/m68k/atari/config.c11
-rw-r--r--arch/m68k/atari/debug.c6
-rw-r--r--arch/m68k/atari/hades-pci.c54
-rw-r--r--arch/m68k/atari/stdma.c5
-rw-r--r--arch/m68k/atari/stram.c3
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/hp300/Makefile2
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/mac/Makefile2
-rw-r--r--arch/m68k/mac/config.c2
-rw-r--r--arch/m68k/mac/mac_ksyms.c8
-rw-r--r--arch/m68k/mac/via.c5
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c2
-rw-r--r--arch/m68k/mvme16x/mvme16x_ksyms.c6
-rw-r--r--arch/m68knommu/Kconfig.debug7
-rw-r--r--arch/m68knommu/defconfig1
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c11
-rw-r--r--arch/m68knommu/kernel/setup.c3
-rw-r--r--arch/m68knommu/kernel/syscalltable.S2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/powerpc/Kconfig3
-rw-r--r--arch/powerpc/kernel/dma_64.c8
-rw-r--r--arch/powerpc/kernel/iommu.c93
-rw-r--r--arch/powerpc/mm/pgtable_32.c6
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/ppc/mm/pgtable.c6
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Kconfig.debug8
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/entry.S7
-rw-r--r--arch/s390/kernel/entry64.S7
-rw-r--r--arch/s390/kernel/ipl.c27
-rw-r--r--arch/s390/kernel/setup.c14
-rw-r--r--arch/s390/kernel/smp.c13
-rw-r--r--arch/s390/kernel/stacktrace.c31
-rw-r--r--arch/s390/kernel/syscalls.S2
-rw-r--r--arch/s390/kernel/traps.c5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/mm/init.c27
-rw-r--r--arch/s390/mm/vmem.c5
-rw-r--r--arch/sparc/kernel/systbls.S2
-rw-r--r--arch/sparc64/kernel/iommu.c2
-rw-r--r--arch/sparc64/kernel/iommu_common.c8
-rw-r--r--arch/sparc64/kernel/iommu_common.h3
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c8
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/um/Kconfig26
-rw-r--r--arch/um/Kconfig.char2
-rw-r--r--arch/um/Kconfig.debug6
-rw-r--r--arch/um/Kconfig.net12
-rw-r--r--arch/um/Makefile12
-rw-r--r--arch/um/Makefile-tt5
-rw-r--r--arch/um/defconfig6
-rw-r--r--arch/um/drivers/line.c28
-rw-r--r--arch/um/drivers/mconsole_kern.c55
-rw-r--r--arch/um/drivers/mconsole_user.c5
-rw-r--r--arch/um/drivers/net_kern.c16
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/port_kern.c7
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c1
-rw-r--r--arch/um/drivers/stdio_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c30
-rw-r--r--arch/um/drivers/ubd_user.c1
-rw-r--r--arch/um/drivers/vde_user.c2
-rw-r--r--arch/um/include/arch.h2
-rw-r--r--arch/um/include/as-layout.h34
-rw-r--r--arch/um/include/chan_user.h2
-rw-r--r--arch/um/include/common-offsets.h1
-rw-r--r--arch/um/include/init.h25
-rw-r--r--arch/um/include/irq_user.h1
-rw-r--r--arch/um/include/kern_util.h120
-rw-r--r--arch/um/include/mem_user.h5
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h41
-rw-r--r--arch/um/include/ptrace_user.h11
-rw-r--r--arch/um/include/registers.h7
-rw-r--r--arch/um/include/signal_kern.h22
-rw-r--r--arch/um/include/skas/mode-skas.h11
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h5
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h9
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h2
-rw-r--r--arch/um/include/um_mmu.h4
-rw-r--r--arch/um/include/um_uaccess.h4
-rw-r--r--arch/um/kernel/exec.c5
-rw-r--r--arch/um/kernel/exitcode.c31
-rw-r--r--arch/um/kernel/gmon_syms.c11
-rw-r--r--arch/um/kernel/gprof_syms.c13
-rw-r--r--arch/um/kernel/initrd.c30
-rw-r--r--arch/um/kernel/irq.c6
-rw-r--r--arch/um/kernel/ksyms.c5
-rw-r--r--arch/um/kernel/mem.c147
-rw-r--r--arch/um/kernel/physmem.c16
-rw-r--r--arch/um/kernel/process.c154
-rw-r--r--arch/um/kernel/reboot.c7
-rw-r--r--arch/um/kernel/sigio.c18
-rw-r--r--arch/um/kernel/signal.c16
-rw-r--r--arch/um/kernel/skas/clone.c32
-rw-r--r--arch/um/kernel/skas/mmu.c127
-rw-r--r--arch/um/kernel/skas/process.c20
-rw-r--r--arch/um/kernel/skas/syscall.c6
-rw-r--r--arch/um/kernel/skas/uaccess.c140
-rw-r--r--arch/um/kernel/smp.c14
-rw-r--r--arch/um/kernel/syscall.c3
-rw-r--r--arch/um/kernel/sysrq.c44
-rw-r--r--arch/um/kernel/time.c14
-rw-r--r--arch/um/kernel/tlb.c51
-rw-r--r--arch/um/kernel/trap.c33
-rw-r--r--arch/um/kernel/uaccess.c11
-rw-r--r--arch/um/kernel/um_arch.c100
-rw-r--r--arch/um/kernel/umid.c15
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/aio.c1
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c5
-rw-r--r--arch/um/os-Linux/file.c287
-rw-r--r--arch/um/os-Linux/helper.c74
-rw-r--r--arch/um/os-Linux/irq.c39
-rw-r--r--arch/um/os-Linux/main.c14
-rw-r--r--arch/um/os-Linux/mem.c13
-rw-r--r--arch/um/os-Linux/process.c5
-rw-r--r--arch/um/os-Linux/registers.c34
-rw-r--r--arch/um/os-Linux/sigio.c244
-rw-r--r--arch/um/os-Linux/signal.c102
-rw-r--r--arch/um/os-Linux/skas/Makefile6
-rw-r--r--arch/um/os-Linux/skas/process.c281
-rw-r--r--arch/um/os-Linux/skas/trap.c69
-rw-r--r--arch/um/os-Linux/start_up.c17
-rw-r--r--arch/um/os-Linux/trap.c23
-rw-r--r--arch/um/os-Linux/tty.c57
-rw-r--r--arch/um/os-Linux/tty_log.c1
-rw-r--r--arch/um/os-Linux/util.c15
-rw-r--r--arch/um/sys-i386/bug.c1
-rw-r--r--arch/um/sys-i386/bugs.c201
-rw-r--r--arch/um/sys-i386/ldt.c19
-rw-r--r--arch/um/sys-i386/ptrace.c6
-rw-r--r--arch/um/sys-i386/ptrace_user.c14
-rw-r--r--arch/um/sys-i386/signal.c18
-rw-r--r--arch/um/sys-i386/stub.S8
-rw-r--r--arch/um/sys-i386/stub_segv.c19
-rw-r--r--arch/um/sys-i386/sys_call_table.S5
-rw-r--r--arch/um/sys-i386/tls.c41
-rw-r--r--arch/um/sys-ppc/Makefile22
-rw-r--r--arch/um/sys-x86_64/bug.c3
-rw-r--r--arch/um/sys-x86_64/bugs.c7
-rw-r--r--arch/um/sys-x86_64/ptrace.c29
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c46
-rw-r--r--arch/um/sys-x86_64/signal.c4
-rw-r--r--arch/um/sys-x86_64/stub.S8
-rw-r--r--arch/um/sys-x86_64/stub_segv.c39
-rw-r--r--arch/um/sys-x86_64/syscall_table.c43
-rw-r--r--arch/um/sys-x86_64/syscalls.c10
-rw-r--r--arch/um/sys-x86_64/sysrq.c29
-rw-r--r--arch/um/sys-x86_64/um_module.c8
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/ia32/ia32entry.S4
-rw-r--r--arch/x86/kernel/pci-calgary_64.c34
-rw-r--r--arch/x86/kernel/pci-gart_64.c48
-rw-r--r--arch/x86/kernel/syscall_table_32.S4
-rw-r--r--arch/x86/kvm/x86.c8
-rw-r--r--arch/x86/lib/Makefile2
-rw-r--r--arch/x86/lib/bitstr_64.c28
-rw-r--r--arch/x86/mm/pgtable_32.c12
-rw-r--r--arch/x86/pci/i386.c2
260 files changed, 5546 insertions, 3578 deletions
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 468b76ce66a1..8ac08311f5a5 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -165,7 +165,7 @@ dma_alloc_coherent(struct device *dev, size_t size,
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret) {
memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
+ *dma_handle = virt_to_phys(ret);
}
return ret;
}
@@ -184,7 +184,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
BUG_ON(!sg_page(sg));
va = sg_virt(sg);
- sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
+ sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
sg_dma_len(sg) = sg->length;
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 2d00a08d3f08..26d3789dfdd0 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -9,6 +9,7 @@
#include <linux/bootmem.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
@@ -470,22 +471,29 @@ EXPORT_SYMBOL(pci_free_consistent);
#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
static void
-sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
+sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
+ int virt_ok)
{
unsigned long next_paddr;
struct scatterlist *leader;
long leader_flag, leader_length;
+ unsigned int max_seg_size;
leader = sg;
leader_flag = 0;
leader_length = leader->length;
next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
+ /* we will not marge sg without device. */
+ max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
for (++sg; sg < end; ++sg) {
unsigned long addr, len;
addr = SG_ENT_PHYS_ADDRESS(sg);
len = sg->length;
+ if (leader_length + len > max_seg_size)
+ goto new_segment;
+
if (next_paddr == addr) {
sg->dma_address = -1;
leader_length += len;
@@ -494,6 +502,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
leader_flag = 1;
leader_length += len;
} else {
+new_segment:
leader->dma_address = leader_flag;
leader->dma_length = leader_length;
leader = sg;
@@ -512,7 +521,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
in the blanks. */
static int
-sg_fill(struct scatterlist *leader, struct scatterlist *end,
+sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
struct scatterlist *out, struct pci_iommu_arena *arena,
dma_addr_t max_dma, int dac_allowed)
{
@@ -562,8 +571,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
/* Otherwise, break up the remaining virtually contiguous
hunks into individual direct maps and retry. */
- sg_classify(leader, end, 0);
- return sg_fill(leader, end, out, arena, max_dma, dac_allowed);
+ sg_classify(dev, leader, end, 0);
+ return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
}
out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
@@ -619,12 +628,15 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
struct pci_iommu_arena *arena;
dma_addr_t max_dma;
int dac_allowed;
+ struct device *dev;
if (direction == PCI_DMA_NONE)
BUG();
dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ dev = pdev ? &pdev->dev : NULL;
+
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg->dma_length = sg->length;
@@ -638,7 +650,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
end = sg + nents;
/* First, prepare information about the entries. */
- sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
+ sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
/* Second, figure out where we're going to map things. */
if (alpha_mv.mv_pci_tbi) {
@@ -658,7 +670,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
for (out = sg; sg < end; ++sg) {
if ((int) sg->dma_address < 0)
continue;
- if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0)
+ if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
goto error;
out++;
}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bd5e68cd61e8..beff6297f788 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -58,7 +58,6 @@ static struct notifier_block alpha_panic_block = {
#include <asm/system.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
-#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/console.h>
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 79de99e32c35..ba914af18c4f 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -495,7 +495,7 @@ sys_call_table:
.quad sys_epoll_pwait
.quad sys_utimensat /* 475 */
.quad sys_signalfd
- .quad sys_timerfd
+ .quad sys_ni_syscall
.quad sys_eventfd
.size sys_call_table, . - sys_call_table
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 471637002e8b..e19e7744e366 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -35,6 +35,11 @@ config GENERIC_CLOCKEVENTS
bool
default n
+config GENERIC_CLOCKEVENTS_BROADCAST
+ bool
+ depends on GENERIC_CLOCKEVENTS
+ default y if SMP && !LOCAL_TIMERS
+
config MMU
bool
default y
@@ -187,6 +192,8 @@ config ARCH_REALVIEW
bool "ARM Ltd. RealView family"
select ARM_AMBA
select ICST307
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
help
This enables support for ARM Ltd RealView boards.
@@ -378,6 +385,7 @@ config ARCH_PXA
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
+ select HAVE_GPIO_LIB
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
@@ -623,7 +631,7 @@ source "kernel/time/Kconfig"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
- depends on EXPERIMENTAL && REALVIEW_MPCORE
+ depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
@@ -656,7 +664,7 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
- depends on SMP && REALVIEW_MPCORE
+ depends on SMP && REALVIEW_EB_ARM11MP
default y
help
Enable support for local timers on SMP platforms, rather then the
@@ -912,6 +920,13 @@ config KEXEC
initially work for you. It may help to enable device hotplugging
support.
+config ATAGS_PROC
+ bool "Export atags in procfs"
+ default n
+ help
+ Should the atags used to boot the kernel be exported in an "atags"
+ file in procfs. Useful with kexec.
+
endmenu
if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA)
@@ -1108,6 +1123,8 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
+source "drivers/gpio/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/power/Kconfig"
diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c
index 34038eccbba9..d544da414731 100644
--- a/arch/arm/common/time-acorn.c
+++ b/arch/arm/common/time-acorn.c
@@ -69,9 +69,7 @@ void __init ioctime_init(void)
static irqreturn_t
ioc_timer_interrupt(int irq, void *dev_id)
{
- write_seqlock(&xtime_lock);
timer_tick();
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index db850a5689eb..efa0485d2f7e 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -1,69 +1,96 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15
-# Tue Jan 3 03:20:40 2006
+# Linux kernel version: 2.6.24
+# Sun Jan 27 07:33:38 2008
#
CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_MMU=y
-CONFIG_UID16=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -81,28 +108,39 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# System Type
#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-CONFIG_ARCH_IXP4XX=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_IXP2000 is not set
+CONFIG_ARCH_IXP4XX=y
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_REALVIEW is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -112,8 +150,12 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
# IXP4xx Platforms
#
-CONFIG_ARCH_AVILA=y
+CONFIG_MACH_NSLU2=y
+CONFIG_MACH_AVILA=y
+CONFIG_MACH_LOFT=y
CONFIG_ARCH_ADI_COYOTE=y
+CONFIG_MACH_GATEWAY7001=y
+CONFIG_MACH_WG302V2=y
CONFIG_ARCH_IXDP425=y
CONFIG_MACH_IXDPG425=y
CONFIG_MACH_IXDP465=y
@@ -121,15 +163,27 @@ CONFIG_MACH_KIXRP435=y
CONFIG_ARCH_IXCDP1100=y
CONFIG_ARCH_PRPMC1100=y
CONFIG_MACH_NAS100D=y
+CONFIG_MACH_DSMG600=y
CONFIG_ARCH_IXDP4XX=y
CONFIG_CPU_IXP46X=y
CONFIG_CPU_IXP43X=y
-# CONFIG_MACH_GTWX5715 is not set
+CONFIG_MACH_GTWX5715=y
#
# IXP4xx Options
#
+CONFIG_DMABOUNCE=y
# CONFIG_IXP4XX_INDIRECT_PCI is not set
+CONFIG_IXP4XX_QMGR=y
+CONFIG_IXP4XX_NPE=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
#
# Processor Type
@@ -140,33 +194,40 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+# CONFIG_IWMMXT is not set
CONFIG_XSCALE_PMU=y
-CONFIG_DMABOUNCE=y
#
# Bus support
#
-CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
# Kernel Features
#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT is not set
-# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -175,7 +236,12 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -185,6 +251,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs"
# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
#
# Floating point emulation
@@ -203,13 +270,12 @@ CONFIG_FPE_NWFPE=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
#
# Power management options
#
# CONFIG_PM is not set
-# CONFIG_APM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
#
# Networking
@@ -219,11 +285,13 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_PACKET=m
+CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -232,9 +300,7 @@ CONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
CONFIG_IP_ROUTE_MULTIPATH=y
-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
@@ -251,15 +317,18 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
CONFIG_IP_VS=m
CONFIG_IP_VS_DEBUG=y
CONFIG_IP_VS_TAB_BITS=12
@@ -290,6 +359,9 @@ CONFIG_IP_VS_SH=m
# IPVS application helper
#
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
CONFIG_BRIDGE_NETFILTER=y
@@ -298,70 +370,57 @@ CONFIG_BRIDGE_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
# CONFIG_IP_NF_MATCH_IPRANGE is not set
-CONFIG_IP_NF_MATCH_MAC=m
-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
# CONFIG_IP_NF_MATCH_RECENT is not set
# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
+# CONFIG_IP_NF_MATCH_AH is not set
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-# CONFIG_IP_NF_MATCH_HELPER is not set
-CONFIG_IP_NF_MATCH_STATE=m
-# CONFIG_IP_NF_MATCH_CONNTRACK is not set
CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_PHYSDEV is not set
# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_DCCP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-# CONFIG_IP_NF_MATCH_STRING is not set
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_TARGET_NETMAP is not set
-# CONFIG_IP_NF_TARGET_SAME is not set
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
# CONFIG_IP_NF_TARGET_ECN is not set
-# CONFIG_IP_NF_TARGET_DSCP is not set
-CONFIG_IP_NF_TARGET_MARK=m
-# CONFIG_IP_NF_TARGET_CLASSIFY is not set
# CONFIG_IP_NF_TARGET_TTL is not set
# CONFIG_IP_NF_RAW is not set
CONFIG_IP_NF_ARPTABLES=m
@@ -372,16 +431,9 @@ CONFIG_IP_NF_ARPFILTER=m
# Bridge: Netfilter Configuration
#
# CONFIG_BRIDGE_NF_EBTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
CONFIG_ATM=y
CONFIG_ATM_CLIP=y
# CONFIG_ATM_CLIP_NO_ICMP is not set
@@ -397,25 +449,17 @@ CONFIG_LLC=m
CONFIG_IPX=m
# CONFIG_IPX_INTERN is not set
CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
+CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
CONFIG_X25=m
CONFIG_LAPB=m
-# CONFIG_NET_DIVERT is not set
CONFIG_ECONET=m
CONFIG_ECONET_AUNUDP=y
CONFIG_ECONET_NATIVE=y
CONFIG_WAN_ROUTER=m
-
-#
-# QoS and/or fair queueing
-#
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CLK_JIFFIES=y
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-# CONFIG_NET_SCH_CLK_CPU is not set
#
# Queueing/Scheduling
@@ -425,6 +469,7 @@ CONFIG_NET_SCH_HTB=m
# CONFIG_NET_SCH_HFSC is not set
# CONFIG_NET_SCH_ATM is not set
CONFIG_NET_SCH_PRIO=m
+# CONFIG_NET_SCH_RR is not set
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
@@ -449,10 +494,17 @@ CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
CONFIG_NET_CLS_POLICE=y
# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_SCH_FIFO=y
#
# Network testing
@@ -461,7 +513,18 @@ CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -470,19 +533,14 @@ CONFIG_NET_PKTGEN=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -498,11 +556,14 @@ CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -528,7 +589,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -538,6 +598,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_IXP4XX=y
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -547,7 +608,6 @@ CONFIG_MTD_IXP4XX=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -556,33 +616,24 @@ CONFIG_MTD_IXP4XX=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
CONFIG_MTD_NAND=m
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
CONFIG_MTD_NAND_IDS=m
# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
# CONFIG_MTD_ONENAND is not set
#
-# Parallel port support
+# UBI - Unsorted block images
#
+# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -592,17 +643,20 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
#
@@ -614,24 +668,28 @@ CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
CONFIG_BLK_DEV_CMD64X=y
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set
@@ -639,93 +697,163 @@ CONFIG_BLK_DEV_CMD64X=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+CONFIG_PATA_ARTOP=y
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+CONFIG_PATA_IXP4XX_CF=y
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_IFB is not set
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+CONFIG_IXP4XX_ETH=y
+# CONFIG_AX88796 is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -738,93 +866,76 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_AIRO is not set
-CONFIG_HERMES=y
-# CONFIG_PLX_HERMES is not set
-# CONFIG_TMD_HERMES is not set
-# CONFIG_NORTEL_HERMES is not set
-CONFIG_PCI_HERMES=y
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+# Wireless LAN
#
-# CONFIG_PRISM54 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
CONFIG_WAN=y
-# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
-# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=m
-CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW=m
# CONFIG_HDLC_RAW_ETH is not set
-CONFIG_HDLC_CISCO=y
-CONFIG_HDLC_FR=y
-CONFIG_HDLC_PPP=y
-CONFIG_HDLC_X25=y
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
# CONFIG_PCI200SYN is not set
# CONFIG_WANXL is not set
# CONFIG_PC300 is not set
+# CONFIG_PC300TOO is not set
# CONFIG_FARSYNC is not set
+# CONFIG_DSCC4 is not set
+# CONFIG_IXP4XX_HSS is not set
CONFIG_DLCI=m
-CONFIG_DLCI_COUNT=24
CONFIG_DLCI_MAX=8
-CONFIG_WAN_ROUTER_DRIVERS=y
+CONFIG_WAN_ROUTER_DRIVERS=m
# CONFIG_CYCLADES_SYNC is not set
# CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set
-
-#
-# ATM drivers
-#
+CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_DUMMY is not set
CONFIG_ATM_TCP=m
# CONFIG_ATM_LANAI is not set
@@ -842,20 +953,19 @@ CONFIG_ATM_TCP=m
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
#
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -865,7 +975,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -875,8 +984,16 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_IXP4XX_BEEPER=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
#
# Hardware I/O ports
@@ -895,7 +1012,9 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -907,51 +1026,17 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_IXP4XX_WATCHDOG=y
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_IXP4XX=m
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -969,57 +1054,68 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_IOP3XX is not set
CONFIG_I2C_IXP4XX=y
# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
-# Hardware Monitoring support
+# SPI support
#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -1033,67 +1129,268 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Misc devices
+# Watchdog Device Drivers
#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP4XX_WATCHDOG=y
#
-# Multimedia Capabilities Port drivers
+# PCI-based Watchdog Cards
#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
#
-# Multimedia devices
+# USB-based Watchdog Cards
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_USBPCWATCHDOG is not set
#
-# Digital Video Broadcasting Devices
+# Sonics Silicon Backplane
#
-# CONFIG_DVB is not set
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Sound
#
# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
#
-# USB support
+# USB Input Devices
#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+# CONFIG_USB_ATM is not set
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
#
-# MMC/SD Card support
+# LED drivers
+#
+# CONFIG_LEDS_IXP4XX is not set
+CONFIG_LEDS_GPIO=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+CONFIG_RTC_DRV_X1205=y
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
#
-# CONFIG_MMC is not set
#
# File systems
@@ -1107,16 +1404,19 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -1140,11 +1440,12 @@ CONFIG_DNOTIFY=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1156,13 +1457,15 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
@@ -1171,10 +1474,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -1186,6 +1486,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1193,7 +1494,6 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -1213,37 +1513,53 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
+# CONFIG_SYSV68_PARTITION is not set
# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
+# CONFIG_DLM is not set
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_DEBUG_USER is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
@@ -1254,22 +1570,22 @@ CONFIG_DEBUG_LL=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index faa761921153..00d44c6fbfe9 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
+obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
new file mode 100644
index 000000000000..e2e934c38080
--- /dev/null
+++ b/arch/arm/kernel/atags.c
@@ -0,0 +1,86 @@
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/proc_fs.h>
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/page.h>
+
+struct buffer {
+ size_t size;
+ char *data;
+};
+static struct buffer tags_buffer;
+
+static int
+read_buffer(char* page, char** start, off_t off, int count,
+ int* eof, void* data)
+{
+ struct buffer *buffer = (struct buffer *)data;
+
+ if (off >= buffer->size) {
+ *eof = 1;
+ return 0;
+ }
+
+ count = min((int) (buffer->size - off), count);
+
+ memcpy(page, &buffer->data[off], count);
+
+ return count;
+}
+
+
+static int
+create_proc_entries(void)
+{
+ struct proc_dir_entry* tags_entry;
+
+ tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
+ if (!tags_entry)
+ return -ENOMEM;
+
+ return 0;
+}
+
+
+static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
+static char __initdata *atags_copy;
+
+void __init save_atags(const struct tag *tags)
+{
+ atags_copy = atags_copy_buf;
+ memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
+}
+
+
+static int __init init_atags_procfs(void)
+{
+ struct tag *tag;
+ int error;
+
+ if (!atags_copy) {
+ printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
+ return -EIO;
+ }
+
+ for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
+ ;
+
+ tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
+ tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
+ if (tags_buffer.data == NULL)
+ return -ENOMEM;
+ memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
+
+ error = create_proc_entries();
+ if (error) {
+ printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
+ kfree(tags_buffer.data);
+ tags_buffer.size = 0;
+ tags_buffer.data = NULL;
+ }
+
+ return error;
+}
+
+arch_initcall(init_atags_procfs);
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
new file mode 100644
index 000000000000..e5f028d214a1
--- /dev/null
+++ b/arch/arm/kernel/atags.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_ATAGS_PROC
+extern void save_atags(struct tag *tags);
+#else
+static inline void save_atags(struct tag *tags) { }
+#endif
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index cecf658e3625..283e14fff993 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -359,7 +359,7 @@
CALL(sys_kexec_load)
CALL(sys_utimensat)
CALL(sys_signalfd)
-/* 350 */ CALL(sys_timerfd)
+/* 350 */ CALL(sys_ni_syscall)
CALL(sys_eventfd)
CALL(sys_fallocate)
#ifndef syscalls_counted
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 863c66454f2b..db8f54a3451f 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
extern unsigned long kexec_start_address;
extern unsigned long kexec_indirection_page;
extern unsigned long kexec_mach_type;
+extern unsigned long kexec_boot_atags;
/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
@@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
kexec_start_address = image->start;
kexec_indirection_page = page_list;
kexec_mach_type = machine_arch_type;
+ kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
/* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer,
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 062c111c572f..61930eb09029 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -7,23 +7,6 @@
.globl relocate_new_kernel
relocate_new_kernel:
- /* Move boot params back to where the kernel expects them */
-
- ldr r0,kexec_boot_params_address
- teq r0,#0
- beq 8f
-
- ldr r1,kexec_boot_params_copy
- mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
-7:
- ldr r5,[r1],#4
- str r5,[r0],#4
- subs r6,r6,#1
- bne 7b
-
-8:
- /* Boot params moved, now go on with the kernel */
-
ldr r0,kexec_indirection_page
ldr r1,kexec_start_address
@@ -67,7 +50,7 @@ relocate_new_kernel:
mov lr,r1
mov r0,#0
ldr r1,kexec_mach_type
- ldr r2,kexec_boot_params_address
+ ldr r2,kexec_boot_atags
mov pc,lr
.globl kexec_start_address
@@ -82,14 +65,9 @@ kexec_indirection_page:
kexec_mach_type:
.long 0x0
- /* phy addr where new kernel will expect to find boot params */
- .globl kexec_boot_params_address
-kexec_boot_params_address:
- .long 0x0
-
- /* phy addr where old kernel put a copy of orig boot params */
- .globl kexec_boot_params_copy
-kexec_boot_params_copy:
+ /* phy addr of the atags for the new kernel */
+ .globl kexec_boot_atags
+kexec_boot_atags:
.long 0x0
relocate_new_kernel_end:
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bf56eb337df1..d3941a7b0455 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <linux/fs.h>
-#include <linux/kexec.h>
#include <asm/cpu.h>
#include <asm/elf.h>
@@ -39,6 +38,7 @@
#include <asm/mach/time.h>
#include "compat.h"
+#include "atags.h"
#ifndef MEM_SIZE
#define MEM_SIZE (16*1024*1024)
@@ -62,6 +62,7 @@ extern int root_mountflags;
extern void _stext, _text, _etext, __data_start, _edata, _end;
unsigned int processor_id;
+EXPORT_SYMBOL(processor_id);
unsigned int __machine_arch_type;
EXPORT_SYMBOL(__machine_arch_type);
@@ -784,23 +785,6 @@ static int __init customize_machine(void)
}
arch_initcall(customize_machine);
-#ifdef CONFIG_KEXEC
-
-/* Physical addr of where the boot params should be for this machine */
-extern unsigned long kexec_boot_params_address;
-
-/* Physical addr of the buffer into which the boot params are copied */
-extern unsigned long kexec_boot_params_copy;
-
-/* Pointer to the boot params buffer, for manipulation and display */
-unsigned long kexec_boot_params;
-EXPORT_SYMBOL(kexec_boot_params);
-
-/* The buffer itself - make sure it is sized correctly */
-static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
-
-#endif
-
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
@@ -819,18 +803,6 @@ void __init setup_arch(char **cmdline_p)
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
-#ifdef CONFIG_KEXEC
- kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
- kexec_boot_params = (unsigned long)kexec_boot_params_buf;
- if (__atags_pointer) {
- kexec_boot_params_address = __atags_pointer;
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
- } else if (mdesc->boot_params) {
- kexec_boot_params_address = mdesc->boot_params;
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
- }
-#endif
-
/*
* If we have the old style parameters, convert them to
* a tag list.
@@ -846,6 +818,7 @@ void __init setup_arch(char **cmdline_p)
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
+ save_atags(tags);
parse_tags(tags);
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index eafbb2b05eb8..eefae1de334c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -150,7 +150,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.pgdir = 0;
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
- pgd_free(pgd);
+ pgd_free(&init_mm, pgd);
if (ret) {
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
@@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
local_irq_enable();
local_fiq_enable();
+ /*
+ * Setup local timer for this CPU.
+ */
+ local_timer_setup(cpu);
+
calibrate_delay();
smp_store_cpu_info(cpu);
@@ -300,11 +305,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
cpu_set(cpu, cpu_online_map);
/*
- * Setup local timer for this CPU.
- */
- local_timer_setup(cpu);
-
- /*
* OK, it's off to the idle thread for us
*/
cpu_idle();
@@ -454,6 +454,27 @@ int smp_call_function(void (*func)(void *info), void *info, int retry,
}
EXPORT_SYMBOL_GPL(smp_call_function);
+int smp_call_function_single(int cpu, void (*func)(void *info), void *info,
+ int retry, int wait)
+{
+ /* prevent preemption and reschedule on another processor */
+ int current_cpu = get_cpu();
+ int ret = 0;
+
+ if (cpu == current_cpu) {
+ local_irq_disable();
+ func(info);
+ local_irq_enable();
+ } else
+ ret = smp_call_function_on_cpu(func, info, retry, wait,
+ cpumask_of_cpu(cpu));
+
+ put_cpu();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(smp_call_function_single);
+
void show_ipi_list(struct seq_file *p)
{
unsigned int cpu;
@@ -481,8 +502,7 @@ void show_local_irqs(struct seq_file *p)
static void ipi_timer(void)
{
irq_enter();
- profile_tick(CPU_PROFILING);
- update_process_times(user_mode(get_irq_regs()));
+ local_timer_interrupt();
irq_exit();
}
@@ -621,6 +641,11 @@ void smp_send_timer(void)
send_ipi_message(mask, IPI_TIMER);
}
+void smp_timer_broadcast(cpumask_t mask)
+{
+ send_ipi_message(mask, IPI_TIMER);
+}
+
void smp_send_stop(void)
{
cpumask_t mask = cpu_online_map;
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 5b0422cdde76..074dcd5d9a7e 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -253,6 +253,36 @@ config AT91_TIMER_HZ
system clock (of at least several MHz), rounding is less of a
problem so it can be safer to use a decimal values like 100.
+choice
+ prompt "Select a UART for early kernel messages"
+
+config AT91_EARLY_DBGU
+ bool "DBGU"
+
+config AT91_EARLY_USART0
+ bool "USART0"
+
+config AT91_EARLY_USART1
+ bool "USART1"
+
+config AT91_EARLY_USART2
+ bool "USART2"
+ depends on ! ARCH_AT91X40
+
+config AT91_EARLY_USART3
+ bool "USART3"
+ depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260)
+
+config AT91_EARLY_USART4
+ bool "USART4"
+ depends on ARCH_AT91SAM9260
+
+config AT91_EARLY_USART5
+ bool "USART5"
+ depends on ARCH_AT91SAM9260
+
+endchoice
+
endmenu
endif
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 5c090c9442f5..e38d23770992 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -49,8 +49,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
volatile long nr_ticks;
if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */
- write_seqlock(&xtime_lock);
-
/* Get number to ticks performed before interrupt and clear PIT interrupt */
nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
do {
@@ -58,7 +56,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
nr_ticks--;
} while (nr_ticks);
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
} else
return IRQ_NONE; /* not handled */
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index b5daf7f5e011..7b9ce7a336b0 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -47,6 +47,9 @@ extern void at91_irq_resume(void);
#define AT91RM9200_BGA 4 /* AT91RM9200 BGA package has 4 banks */
struct at91_gpio_bank {
+ unsigned chipbase; /* bank's first GPIO number */
+ void __iomem *regbase; /* base of register bank */
+ struct at91_gpio_bank *next; /* bank sharing same IRQ/clock/... */
unsigned short id; /* peripheral ID */
unsigned long offset; /* offset from system peripheral base */
struct clk *clock; /* associated clock */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 6aeddd68d8af..f629c2b5f0c5 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -33,12 +33,10 @@ static int gpio_banks;
static inline void __iomem *pin_to_controller(unsigned pin)
{
- void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
-
pin -= PIN_BASE;
pin /= 32;
if (likely(pin < gpio_banks))
- return sys_base + gpio[pin].offset;
+ return gpio[pin].regbase;
return NULL;
}
@@ -294,11 +292,11 @@ void at91_gpio_suspend(void)
int i;
for (i = 0; i < gpio_banks; i++) {
- u32 pio = gpio[i].offset;
+ void __iomem *pio = gpio[i].regbase;
- backups[i] = at91_sys_read(pio + PIO_IMR);
- at91_sys_write(pio + PIO_IDR, backups[i]);
- at91_sys_write(pio + PIO_IER, wakeups[i]);
+ backups[i] = __raw_readl(pio + PIO_IMR);
+ __raw_writel(backups[i], pio + PIO_IDR);
+ __raw_writel(wakeups[i], pio + PIO_IER);
if (!wakeups[i])
clk_disable(gpio[i].clock);
@@ -315,13 +313,13 @@ void at91_gpio_resume(void)
int i;
for (i = 0; i < gpio_banks; i++) {
- u32 pio = gpio[i].offset;
+ void __iomem *pio = gpio[i].regbase;
if (!wakeups[i])
clk_enable(gpio[i].clock);
- at91_sys_write(pio + PIO_IDR, wakeups[i]);
- at91_sys_write(pio + PIO_IER, backups[i]);
+ __raw_writel(wakeups[i], pio + PIO_IDR);
+ __raw_writel(backups[i], pio + PIO_IER);
}
}
@@ -361,7 +359,13 @@ static void gpio_irq_unmask(unsigned pin)
static int gpio_irq_type(unsigned pin, unsigned type)
{
- return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ case IRQ_TYPE_EDGE_BOTH:
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
static struct irq_chip gpio_irqchip = {
@@ -376,20 +380,30 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
unsigned pin;
struct irq_desc *gpio;
+ struct at91_gpio_bank *bank;
void __iomem *pio;
u32 isr;
- pio = get_irq_chip_data(irq);
+ bank = get_irq_chip_data(irq);
+ pio = bank->regbase;
/* temporarily mask (level sensitive) parent IRQ */
desc->chip->ack(irq);
for (;;) {
- /* reading ISR acks the pending (edge triggered) GPIO interrupt */
+ /* Reading ISR acks pending (edge triggered) GPIO interrupts.
+ * When there none are pending, we're finished unless we need
+ * to process multiple banks (like ID_PIOCDE on sam9263).
+ */
isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
- if (!isr)
- break;
+ if (!isr) {
+ if (!bank->next)
+ break;
+ bank = bank->next;
+ pio = bank->regbase;
+ continue;
+ }
- pin = (unsigned) get_irq_data(irq);
+ pin = bank->chipbase;
gpio = &irq_desc[pin];
while (isr) {
@@ -481,24 +495,21 @@ postcore_initcall(at91_gpio_debugfs_init);
*/
void __init at91_gpio_irq_setup(void)
{
- unsigned pioc, pin;
+ unsigned pioc, pin;
+ struct at91_gpio_bank *this, *prev;
- for (pioc = 0, pin = PIN_BASE;
- pioc < gpio_banks;
- pioc++) {
- void __iomem *controller;
- unsigned id = gpio[pioc].id;
+ for (pioc = 0, pin = PIN_BASE, this = gpio, prev = NULL;
+ pioc++ < gpio_banks;
+ prev = this, this++) {
+ unsigned id = this->id;
unsigned i;
- clk_enable(gpio[pioc].clock); /* enable PIO controller's clock */
-
- controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
- __raw_writel(~0, controller + PIO_IDR);
+ /* enable PIO controller's clock */
+ clk_enable(this->clock);
- set_irq_data(id, (void *) pin);
- set_irq_chip_data(id, controller);
+ __raw_writel(~0, this->regbase + PIO_IDR);
- for (i = 0; i < 32; i++, pin++) {
+ for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
/*
* Can use the "simple" and not "edge" handler since it's
* shorter, and the AIC handles interrupts sanely.
@@ -508,6 +519,14 @@ void __init at91_gpio_irq_setup(void)
set_irq_flags(pin, IRQF_VALID);
}
+ /* The toplevel handler handles one bank of GPIOs, except
+ * AT91SAM9263_ID_PIOCDE handles three... PIOC is first in
+ * the list, so we only set up that handler.
+ */
+ if (prev && prev->next == this)
+ continue;
+
+ set_irq_chip_data(id, this);
set_irq_chained_handler(id, gpio_irq_handler);
}
pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
@@ -518,8 +537,20 @@ void __init at91_gpio_irq_setup(void)
*/
void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
{
+ unsigned i;
+ struct at91_gpio_bank *last;
+
BUG_ON(nr_banks > MAX_GPIO_BANKS);
gpio = data;
gpio_banks = nr_banks;
+
+ for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) {
+ data->chipbase = PIN_BASE + i * 32;
+ data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
+
+ /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
+ if (last && last->id == data->id)
+ last->next = data;
+ }
}
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 61b2dfcb89d6..e774447c0592 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -189,6 +189,20 @@ config IXP4XX_INDIRECT_PCI
need to use the indirect method instead. If you don't know
what you need, leave this option unselected.
+config IXP4XX_QMGR
+ tristate "IXP4xx Queue Manager support"
+ help
+ This driver supports IXP4xx built-in hardware queue manager
+ and is automatically selected by Ethernet and HSS drivers.
+
+config IXP4XX_NPE
+ tristate "IXP4xx Network Processor Engine support"
+ select HOTPLUG
+ select FW_LOADER
+ help
+ This driver supports IXP4xx built-in network coprocessors
+ and is automatically selected by Ethernet and HSS drivers.
+
endmenu
endif
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 77e00ade5585..c1956882c48b 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -23,10 +23,12 @@ obj-$(CONFIG_MACH_AVILA) += avila-setup.o
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
-obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
-obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o
-obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o
+obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o
+obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o
obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
+obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o
+obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o
diff --git a/arch/arm/mach-ixp4xx/dsmg600-power.c b/arch/arm/mach-ixp4xx/dsmg600-power.c
deleted file mode 100644
index 34717872d076..000000000000
--- a/arch/arm/mach-ixp4xx/dsmg600-power.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/dsmg600-power.c
- *
- * DSM-G600 Power/Reset driver
- * Author: Michael Westerhof <mwester@dls.net>
- *
- * Based on nslu2-power.c
- * Copyright (C) 2005 Tower Technologies
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- *
- * which was based on nslu2-io.c
- * Copyright (C) 2004 Karen Spearel
- *
- * Maintainers: http://www.nslu2-linux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-
-#include <asm/mach-types.h>
-
-extern void ctrl_alt_del(void);
-
-/* This is used to make sure the power-button pusher is serious. The button
- * must be held until the value of this counter reaches zero.
- */
-static volatile int power_button_countdown;
-
-/* Must hold the button down for at least this many counts to be processed */
-#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
-
-static void dsmg600_power_handler(unsigned long data);
-static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
-
-static void dsmg600_power_handler(unsigned long data)
-{
- /* This routine is called twice per second to check the
- * state of the power button.
- */
-
- if (*IXP4XX_GPIO_GPINR & DSMG600_PB_BM) {
-
- /* IO Pin is 1 (button pushed) */
- if (power_button_countdown == 0) {
- /* Signal init to do the ctrlaltdel action, this will bypass
- * init if it hasn't started and do a kernel_restart.
- */
- ctrl_alt_del();
-
- /* Change the state of the power LED to "blink" */
- gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
- }
- power_button_countdown--;
-
- } else {
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
- }
-
- mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
-}
-
-static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset, it shuts the machine down directly. */
- machine_power_off();
-
- return IRQ_HANDLED;
-}
-
-static int __init dsmg600_power_init(void)
-{
- if (!(machine_is_dsmg600()))
- return 0;
-
- if (request_irq(DSMG600_RB_IRQ, &dsmg600_reset_handler,
- IRQF_DISABLED | IRQF_TRIGGER_LOW, "DSM-G600 reset button",
- NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- DSMG600_RB_IRQ);
-
- return -EIO;
- }
-
- /* The power button on the D-Link DSM-G600 is on GPIO 15, but
- * it cannot handle interrupts on that GPIO line. So we'll
- * have to poll it with a kernel timer.
- */
-
- /* Make sure that the power button GPIO is set up as an input */
- gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
-
- /* Set the initial value for the power button IRQ handler */
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
-
- mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
-
- return 0;
-}
-
-static void __exit dsmg600_power_exit(void)
-{
- if (!(machine_is_dsmg600()))
- return;
-
- del_timer_sync(&dsmg600_power_timer);
-
- free_irq(DSMG600_RB_IRQ, NULL);
-}
-
-module_init(dsmg600_power_init);
-module_exit(dsmg600_power_exit);
-
-MODULE_AUTHOR("Michael Westerhof <mwester@dls.net>");
-MODULE_DESCRIPTION("DSM-G600 Power/Reset driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index c473d408aa7c..688659668bdf 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -1,25 +1,37 @@
/*
* DSM-G600 board-setup
*
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
* Copyright (C) 2006 Tower Technologies
- * Author: Alessandro Zummo <a.zummo@towertech.it>
*
- * based ixdp425-setup.c:
+ * based on ixdp425-setup.c:
* Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nslu2-power.c:
+ * Copyright (C) 2005 Tower Technologies
+ * based on nslu2-io.c:
+ * Copyright (C) 2004 Karen Spearel
*
* Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Author: Michael Westerhof <mwester@dls.net>
+ * Author: Rod Whitby <rod@whitby.id.au>
* Maintainers: http://www.nslu2-linux.org/
*/
-#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
+#include <asm/gpio.h>
static struct flash_platform_data dsmg600_flash_data = {
.map_name = "cfi_probe",
@@ -51,29 +63,34 @@ static struct platform_device dsmg600_i2c_gpio = {
},
};
-#ifdef CONFIG_LEDS_CLASS
-static struct resource dsmg600_led_resources[] = {
+static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
+ {
+ I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ },
+};
+
+static struct gpio_led dsmg600_led_pins[] = {
{
- .name = "power",
- .start = DSMG600_LED_PWR_GPIO,
- .end = DSMG600_LED_PWR_GPIO,
- .flags = IXP4XX_GPIO_HIGH,
+ .name = "power",
+ .gpio = DSMG600_LED_PWR_GPIO,
},
{
- .name = "wlan",
- .start = DSMG600_LED_WLAN_GPIO,
- .end = DSMG600_LED_WLAN_GPIO,
- .flags = IXP4XX_GPIO_LOW,
+ .name = "wlan",
+ .gpio = DSMG600_LED_WLAN_GPIO,
+ .active_low = true,
},
};
+static struct gpio_led_platform_data dsmg600_led_data = {
+ .num_leds = ARRAY_SIZE(dsmg600_led_pins),
+ .leds = dsmg600_led_pins,
+};
+
static struct platform_device dsmg600_leds = {
- .name = "IXP4XX-GPIO-LED",
- .id = -1,
- .num_resources = ARRAY_SIZE(dsmg600_led_resources),
- .resource = dsmg600_led_resources,
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = &dsmg600_led_data,
};
-#endif
static struct resource dsmg600_uart_resources[] = {
{
@@ -121,6 +138,7 @@ static struct platform_device dsmg600_uart = {
static struct platform_device *dsmg600_devices[] __initdata = {
&dsmg600_i2c_gpio,
&dsmg600_flash,
+ &dsmg600_leds,
};
static void dsmg600_power_off(void)
@@ -132,6 +150,57 @@ static void dsmg600_power_off(void)
gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
}
+/* This is used to make sure the power-button pusher is serious. The button
+ * must be held until the value of this counter reaches zero.
+ */
+static int power_button_countdown;
+
+/* Must hold the button down for at least this many counts to be processed */
+#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+
+static void dsmg600_power_handler(unsigned long data);
+static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
+
+static void dsmg600_power_handler(unsigned long data)
+{
+ /* This routine is called twice per second to check the
+ * state of the power button.
+ */
+
+ if (gpio_get_value(DSMG600_PB_GPIO)) {
+
+ /* IO Pin is 1 (button pushed) */
+ if (power_button_countdown > 0)
+ power_button_countdown--;
+
+ } else {
+
+ /* Done on button release, to allow for auto-power-on mods. */
+ if (power_button_countdown == 0) {
+ /* Signal init to do the ctrlaltdel action,
+ * this will bypass init if it hasn't started
+ * and do a kernel_restart.
+ */
+ ctrl_alt_del();
+
+ /* Change the state of the power LED to "blink" */
+ gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+ } else {
+ power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+ }
+ }
+
+ mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
+{
+ /* This is the paper-clip reset, it shuts the machine down directly. */
+ machine_power_off();
+
+ return IRQ_HANDLED;
+}
+
static void __init dsmg600_timer_init(void)
{
/* The xtal on this machine is non-standard. */
@@ -156,7 +225,8 @@ static void __init dsmg600_init(void)
dsmg600_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
- pm_power_off = dsmg600_power_off;
+ i2c_register_board_info(0, dsmg600_i2c_board_info,
+ ARRAY_SIZE(dsmg600_i2c_board_info));
/* The UART is required on the DSM-G600 (Redboot cannot use the
* NIC) -- do it here so that it does *not* get removed if
@@ -166,10 +236,28 @@ static void __init dsmg600_init(void)
platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
-#ifdef CONFIG_LEDS_CLASS
- /* We don't care whether or not this works. */
- (void)platform_device_register(&dsmg600_leds);
-#endif
+ pm_power_off = dsmg600_power_off;
+
+ if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_LOW,
+ "DSM-G600 reset button", NULL) < 0) {
+
+ printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+ gpio_to_irq(DSMG600_RB_GPIO));
+ }
+
+ /* The power button on the D-Link DSM-G600 is on GPIO 15, but
+ * it cannot handle interrupts on that GPIO line. So we'll
+ * have to poll it with a kernel timer.
+ */
+
+ /* Make sure that the power button GPIO is set up as an input */
+ gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
+
+ /* Set the initial value for the power button IRQ handler */
+ power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+ mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
}
MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index e89070da28bf..44584afb34a3 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -177,6 +177,31 @@ static struct platform_device ixdp425_uart = {
.resource = ixdp425_uart_resources
};
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+ {
+ .phy = 0,
+ .rxq = 3,
+ .txreadyq = 20,
+ }, {
+ .phy = 1,
+ .rxq = 4,
+ .txreadyq = 21,
+ }
+};
+
+static struct platform_device ixdp425_eth[] = {
+ {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEB,
+ .dev.platform_data = ixdp425_plat_eth,
+ }, {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEC,
+ .dev.platform_data = ixdp425_plat_eth + 1,
+ }
+};
+
static struct platform_device *ixdp425_devices[] __initdata = {
&ixdp425_i2c_gpio,
&ixdp425_flash,
@@ -184,7 +209,9 @@ static struct platform_device *ixdp425_devices[] __initdata = {
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
&ixdp425_flash_nand,
#endif
- &ixdp425_uart
+ &ixdp425_uart,
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
};
static void __init ixdp425_init(void)
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
new file mode 100644
index 000000000000..83c137ec582c
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -0,0 +1,741 @@
+/*
+ * Intel IXP4xx Network Processor Engine driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * The code is based on publicly available information:
+ * - Intel IXP4xx Developer's Manual and other e-papers
+ * - Intel IXP400 Access Library Software (BSD license)
+ * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
+ * Thanks, Christian.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/arch/npe.h>
+
+#define DEBUG_MSG 0
+#define DEBUG_FW 0
+
+#define NPE_COUNT 3
+#define MAX_RETRIES 1000 /* microseconds */
+#define NPE_42X_DATA_SIZE 0x800 /* in dwords */
+#define NPE_46X_DATA_SIZE 0x1000
+#define NPE_A_42X_INSTR_SIZE 0x1000
+#define NPE_B_AND_C_42X_INSTR_SIZE 0x800
+#define NPE_46X_INSTR_SIZE 0x1000
+#define REGS_SIZE 0x1000
+
+#define NPE_PHYS_REG 32
+
+#define FW_MAGIC 0xFEEDF00D
+#define FW_BLOCK_TYPE_INSTR 0x0
+#define FW_BLOCK_TYPE_DATA 0x1
+#define FW_BLOCK_TYPE_EOF 0xF
+
+/* NPE exec status (read) and command (write) */
+#define CMD_NPE_STEP 0x01
+#define CMD_NPE_START 0x02
+#define CMD_NPE_STOP 0x03
+#define CMD_NPE_CLR_PIPE 0x04
+#define CMD_CLR_PROFILE_CNT 0x0C
+#define CMD_RD_INS_MEM 0x10 /* instruction memory */
+#define CMD_WR_INS_MEM 0x11
+#define CMD_RD_DATA_MEM 0x12 /* data memory */
+#define CMD_WR_DATA_MEM 0x13
+#define CMD_RD_ECS_REG 0x14 /* exec access register */
+#define CMD_WR_ECS_REG 0x15
+
+#define STAT_RUN 0x80000000
+#define STAT_STOP 0x40000000
+#define STAT_CLEAR 0x20000000
+#define STAT_ECS_K 0x00800000 /* pipeline clean */
+
+#define NPE_STEVT 0x1B
+#define NPE_STARTPC 0x1C
+#define NPE_REGMAP 0x1E
+#define NPE_CINDEX 0x1F
+
+#define INSTR_WR_REG_SHORT 0x0000C000
+#define INSTR_WR_REG_BYTE 0x00004000
+#define INSTR_RD_FIFO 0x0F888220
+#define INSTR_RESET_MBOX 0x0FAC8210
+
+#define ECS_BG_CTXT_REG_0 0x00 /* Background Executing Context */
+#define ECS_BG_CTXT_REG_1 0x01 /* Stack level */
+#define ECS_BG_CTXT_REG_2 0x02
+#define ECS_PRI_1_CTXT_REG_0 0x04 /* Priority 1 Executing Context */
+#define ECS_PRI_1_CTXT_REG_1 0x05 /* Stack level */
+#define ECS_PRI_1_CTXT_REG_2 0x06
+#define ECS_PRI_2_CTXT_REG_0 0x08 /* Priority 2 Executing Context */
+#define ECS_PRI_2_CTXT_REG_1 0x09 /* Stack level */
+#define ECS_PRI_2_CTXT_REG_2 0x0A
+#define ECS_DBG_CTXT_REG_0 0x0C /* Debug Executing Context */
+#define ECS_DBG_CTXT_REG_1 0x0D /* Stack level */
+#define ECS_DBG_CTXT_REG_2 0x0E
+#define ECS_INSTRUCT_REG 0x11 /* NPE Instruction Register */
+
+#define ECS_REG_0_ACTIVE 0x80000000 /* all levels */
+#define ECS_REG_0_NEXTPC_MASK 0x1FFF0000 /* BG/PRI1/PRI2 levels */
+#define ECS_REG_0_LDUR_BITS 8
+#define ECS_REG_0_LDUR_MASK 0x00000700 /* all levels */
+#define ECS_REG_1_CCTXT_BITS 16
+#define ECS_REG_1_CCTXT_MASK 0x000F0000 /* all levels */
+#define ECS_REG_1_SELCTXT_BITS 0
+#define ECS_REG_1_SELCTXT_MASK 0x0000000F /* all levels */
+#define ECS_DBG_REG_2_IF 0x00100000 /* debug level */
+#define ECS_DBG_REG_2_IE 0x00080000 /* debug level */
+
+/* NPE watchpoint_fifo register bit */
+#define WFIFO_VALID 0x80000000
+
+/* NPE messaging_status register bit definitions */
+#define MSGSTAT_OFNE 0x00010000 /* OutFifoNotEmpty */
+#define MSGSTAT_IFNF 0x00020000 /* InFifoNotFull */
+#define MSGSTAT_OFNF 0x00040000 /* OutFifoNotFull */
+#define MSGSTAT_IFNE 0x00080000 /* InFifoNotEmpty */
+#define MSGSTAT_MBINT 0x00100000 /* Mailbox interrupt */
+#define MSGSTAT_IFINT 0x00200000 /* InFifo interrupt */
+#define MSGSTAT_OFINT 0x00400000 /* OutFifo interrupt */
+#define MSGSTAT_WFINT 0x00800000 /* WatchFifo interrupt */
+
+/* NPE messaging_control register bit definitions */
+#define MSGCTL_OUT_FIFO 0x00010000 /* enable output FIFO */
+#define MSGCTL_IN_FIFO 0x00020000 /* enable input FIFO */
+#define MSGCTL_OUT_FIFO_WRITE 0x01000000 /* enable FIFO + WRITE */
+#define MSGCTL_IN_FIFO_WRITE 0x02000000
+
+/* NPE mailbox_status value for reset */
+#define RESET_MBOX_STAT 0x0000F0F0
+
+const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
+
+#define print_npe(pri, npe, fmt, ...) \
+ printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
+
+#if DEBUG_MSG
+#define debug_msg(npe, fmt, ...) \
+ print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
+#else
+#define debug_msg(npe, fmt, ...)
+#endif
+
+static struct {
+ u32 reg, val;
+} ecs_reset[] = {
+ { ECS_BG_CTXT_REG_0, 0xA0000000 },
+ { ECS_BG_CTXT_REG_1, 0x01000000 },
+ { ECS_BG_CTXT_REG_2, 0x00008000 },
+ { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
+ { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
+ { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
+ { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
+ { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
+ { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
+ { ECS_DBG_CTXT_REG_0, 0x20000000 },
+ { ECS_DBG_CTXT_REG_1, 0x00000000 },
+ { ECS_DBG_CTXT_REG_2, 0x001E0000 },
+ { ECS_INSTRUCT_REG, 0x1003C00F },
+};
+
+static struct npe npe_tab[NPE_COUNT] = {
+ {
+ .id = 0,
+ .regs = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
+ .regs_phys = IXP4XX_NPEA_BASE_PHYS,
+ }, {
+ .id = 1,
+ .regs = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
+ .regs_phys = IXP4XX_NPEB_BASE_PHYS,
+ }, {
+ .id = 2,
+ .regs = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
+ .regs_phys = IXP4XX_NPEC_BASE_PHYS,
+ }
+};
+
+int npe_running(struct npe *npe)
+{
+ return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
+}
+
+static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
+{
+ __raw_writel(data, &npe->regs->exec_data);
+ __raw_writel(addr, &npe->regs->exec_addr);
+ __raw_writel(cmd, &npe->regs->exec_status_cmd);
+}
+
+static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
+{
+ __raw_writel(addr, &npe->regs->exec_addr);
+ __raw_writel(cmd, &npe->regs->exec_status_cmd);
+ /* Iintroduce extra read cycles after issuing read command to NPE
+ so that we read the register after the NPE has updated it.
+ This is to overcome race condition between XScale and NPE */
+ __raw_readl(&npe->regs->exec_data);
+ __raw_readl(&npe->regs->exec_data);
+ return __raw_readl(&npe->regs->exec_data);
+}
+
+static void npe_clear_active(struct npe *npe, u32 reg)
+{
+ u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
+ npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
+}
+
+static void npe_start(struct npe *npe)
+{
+ /* ensure only Background Context Stack Level is active */
+ npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
+ npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
+ npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
+
+ __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+ __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
+}
+
+static void npe_stop(struct npe *npe)
+{
+ __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
+ __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
+}
+
+static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
+ u32 ldur)
+{
+ u32 wc;
+ int i;
+
+ /* set the Active bit, and the LDUR, in the debug level */
+ npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
+ ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
+
+ /* set CCTXT at ECS DEBUG L3 to specify in which context to execute
+ the instruction, and set SELCTXT at ECS DEBUG Level to specify
+ which context store to access.
+ Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
+ */
+ npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
+ (ctx << ECS_REG_1_CCTXT_BITS) |
+ (ctx << ECS_REG_1_SELCTXT_BITS));
+
+ /* clear the pipeline */
+ __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+
+ /* load NPE instruction into the instruction register */
+ npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
+
+ /* we need this value later to wait for completion of NPE execution
+ step */
+ wc = __raw_readl(&npe->regs->watch_count);
+
+ /* issue a Step One command via the Execution Control register */
+ __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
+
+ /* Watch Count register increments when NPE completes an instruction */
+ for (i = 0; i < MAX_RETRIES; i++) {
+ if (wc != __raw_readl(&npe->regs->watch_count))
+ return 0;
+ udelay(1);
+ }
+
+ print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
+ return -ETIMEDOUT;
+}
+
+static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
+ u8 val, u32 ctx)
+{
+ /* here we build the NPE assembler instruction: mov8 d0, #0 */
+ u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
+ addr << 9 | /* base Operand */
+ (val & 0x1F) << 4 | /* lower 5 bits to immediate data */
+ (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
+ return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
+ u16 val, u32 ctx)
+{
+ /* here we build the NPE assembler instruction: mov16 d0, #0 */
+ u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
+ addr << 9 | /* base Operand */
+ (val & 0x1F) << 4 | /* lower 5 bits to immediate data */
+ (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
+ return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
+ u32 val, u32 ctx)
+{
+ /* write in 16 bit steps first the high and then the low value */
+ if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
+ return -ETIMEDOUT;
+ return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
+}
+
+static int npe_reset(struct npe *npe)
+{
+ u32 val, ctl, exec_count, ctx_reg2;
+ int i;
+
+ ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
+ 0x3F3FFFFF;
+
+ /* disable parity interrupt */
+ __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
+
+ /* pre exec - debug instruction */
+ /* turn off the halt bit by clearing Execution Count register. */
+ exec_count = __raw_readl(&npe->regs->exec_count);
+ __raw_writel(0, &npe->regs->exec_count);
+ /* ensure that IF and IE are on (temporarily), so that we don't end up
+ stepping forever */
+ ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
+ npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
+ ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
+
+ /* clear the FIFOs */
+ while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
+ ;
+ while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
+ /* read from the outFIFO until empty */
+ print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
+ __raw_readl(&npe->regs->in_out_fifo));
+
+ while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
+ /* step execution of the NPE intruction to read inFIFO using
+ the Debug Executing Context stack */
+ if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
+ return -ETIMEDOUT;
+
+ /* reset the mailbox reg from the XScale side */
+ __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
+ /* from NPE side */
+ if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
+ return -ETIMEDOUT;
+
+ /* Reset the physical registers in the NPE register file */
+ for (val = 0; val < NPE_PHYS_REG; val++) {
+ if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
+ return -ETIMEDOUT;
+ /* address is either 0 or 4 */
+ if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
+ return -ETIMEDOUT;
+ }
+
+ /* Reset the context store = each context's Context Store registers */
+
+ /* Context 0 has no STARTPC. Instead, this value is used to set NextPC
+ for Background ECS, to set where NPE starts executing code */
+ val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
+ val &= ~ECS_REG_0_NEXTPC_MASK;
+ val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
+ npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
+
+ for (i = 0; i < 16; i++) {
+ if (i) { /* Context 0 has no STEVT nor STARTPC */
+ /* STEVT = off, 0x80 */
+ if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
+ return -ETIMEDOUT;
+ if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
+ return -ETIMEDOUT;
+ }
+ /* REGMAP = d0->p0, d8->p2, d16->p4 */
+ if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
+ return -ETIMEDOUT;
+ if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
+ return -ETIMEDOUT;
+ }
+
+ /* post exec */
+ /* clear active bit in debug level */
+ npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
+ /* clear the pipeline */
+ __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+ /* restore previous values */
+ __raw_writel(exec_count, &npe->regs->exec_count);
+ npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
+
+ /* write reset values to Execution Context Stack registers */
+ for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
+ npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
+ ecs_reset[val].val);
+
+ /* clear the profile counter */
+ __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
+
+ __raw_writel(0, &npe->regs->exec_count);
+ __raw_writel(0, &npe->regs->action_points[0]);
+ __raw_writel(0, &npe->regs->action_points[1]);
+ __raw_writel(0, &npe->regs->action_points[2]);
+ __raw_writel(0, &npe->regs->action_points[3]);
+ __raw_writel(0, &npe->regs->watch_count);
+
+ val = ixp4xx_read_feature_bits();
+ /* reset the NPE */
+ ixp4xx_write_feature_bits(val &
+ ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
+ for (i = 0; i < MAX_RETRIES; i++) {
+ if (!(ixp4xx_read_feature_bits() &
+ (IXP4XX_FEATURE_RESET_NPEA << npe->id)))
+ break; /* reset completed */
+ udelay(1);
+ }
+ if (i == MAX_RETRIES)
+ return -ETIMEDOUT;
+
+ /* deassert reset */
+ ixp4xx_write_feature_bits(val |
+ (IXP4XX_FEATURE_RESET_NPEA << npe->id));
+ for (i = 0; i < MAX_RETRIES; i++) {
+ if (ixp4xx_read_feature_bits() &
+ (IXP4XX_FEATURE_RESET_NPEA << npe->id))
+ break; /* NPE is back alive */
+ udelay(1);
+ }
+ if (i == MAX_RETRIES)
+ return -ETIMEDOUT;
+
+ npe_stop(npe);
+
+ /* restore NPE configuration bus Control Register - parity settings */
+ __raw_writel(ctl, &npe->regs->messaging_control);
+ return 0;
+}
+
+
+int npe_send_message(struct npe *npe, const void *msg, const char *what)
+{
+ const u32 *send = msg;
+ int cycles = 0;
+
+ debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
+ what, send[0], send[1]);
+
+ if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
+ debug_msg(npe, "NPE input FIFO not empty\n");
+ return -EIO;
+ }
+
+ __raw_writel(send[0], &npe->regs->in_out_fifo);
+
+ if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
+ debug_msg(npe, "NPE input FIFO full\n");
+ return -EIO;
+ }
+
+ __raw_writel(send[1], &npe->regs->in_out_fifo);
+
+ while ((cycles < MAX_RETRIES) &&
+ (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
+ udelay(1);
+ cycles++;
+ }
+
+ if (cycles == MAX_RETRIES) {
+ debug_msg(npe, "Timeout sending message\n");
+ return -ETIMEDOUT;
+ }
+
+ debug_msg(npe, "Sending a message took %i cycles\n", cycles);
+ return 0;
+}
+
+int npe_recv_message(struct npe *npe, void *msg, const char *what)
+{
+ u32 *recv = msg;
+ int cycles = 0, cnt = 0;
+
+ debug_msg(npe, "Trying to receive message %s\n", what);
+
+ while (cycles < MAX_RETRIES) {
+ if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
+ recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
+ if (cnt == 2)
+ break;
+ } else {
+ udelay(1);
+ cycles++;
+ }
+ }
+
+ switch(cnt) {
+ case 1:
+ debug_msg(npe, "Received [%08X]\n", recv[0]);
+ break;
+ case 2:
+ debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
+ break;
+ }
+
+ if (cycles == MAX_RETRIES) {
+ debug_msg(npe, "Timeout waiting for message\n");
+ return -ETIMEDOUT;
+ }
+
+ debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
+ return 0;
+}
+
+int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
+{
+ int result;
+ u32 *send = msg, recv[2];
+
+ if ((result = npe_send_message(npe, msg, what)) != 0)
+ return result;
+ if ((result = npe_recv_message(npe, recv, what)) != 0)
+ return result;
+
+ if ((recv[0] != send[0]) || (recv[1] != send[1])) {
+ debug_msg(npe, "Message %s: unexpected message received\n",
+ what);
+ return -EIO;
+ }
+ return 0;
+}
+
+
+int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
+{
+ const struct firmware *fw_entry;
+
+ struct dl_block {
+ u32 type;
+ u32 offset;
+ } *blk;
+
+ struct dl_image {
+ u32 magic;
+ u32 id;
+ u32 size;
+ union {
+ u32 data[0];
+ struct dl_block blocks[0];
+ };
+ } *image;
+
+ struct dl_codeblock {
+ u32 npe_addr;
+ u32 size;
+ u32 data[0];
+ } *cb;
+
+ int i, j, err, data_size, instr_size, blocks, table_end;
+ u32 cmd;
+
+ if ((err = request_firmware(&fw_entry, name, dev)) != 0)
+ return err;
+
+ err = -EINVAL;
+ if (fw_entry->size < sizeof(struct dl_image)) {
+ print_npe(KERN_ERR, npe, "incomplete firmware file\n");
+ goto err;
+ }
+ image = (struct dl_image*)fw_entry->data;
+
+#if DEBUG_FW
+ print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
+ image->magic, image->id, image->size, image->size * 4);
+#endif
+
+ if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
+ image->id = swab32(image->id);
+ image->size = swab32(image->size);
+ } else if (image->magic != FW_MAGIC) {
+ print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
+ image->magic);
+ goto err;
+ }
+ if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
+ print_npe(KERN_ERR, npe,
+ "inconsistent size of firmware file\n");
+ goto err;
+ }
+ if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
+ print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
+ goto err;
+ }
+ if (image->magic == swab32(FW_MAGIC))
+ for (i = 0; i < image->size; i++)
+ image->data[i] = swab32(image->data[i]);
+
+ if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) {
+ print_npe(KERN_INFO, npe, "IXP46x firmware ignored on "
+ "IXP42x\n");
+ goto err;
+ }
+
+ if (npe_running(npe)) {
+ print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
+ "already running\n");
+ err = -EBUSY;
+ goto err;
+ }
+#if 0
+ npe_stop(npe);
+ npe_reset(npe);
+#endif
+
+ print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
+ "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
+ (image->id >> 8) & 0xFF, image->id & 0xFF);
+
+ if (!cpu_is_ixp46x()) {
+ if (!npe->id)
+ instr_size = NPE_A_42X_INSTR_SIZE;
+ else
+ instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
+ data_size = NPE_42X_DATA_SIZE;
+ } else {
+ instr_size = NPE_46X_INSTR_SIZE;
+ data_size = NPE_46X_DATA_SIZE;
+ }
+
+ for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
+ blocks++)
+ if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
+ break;
+ if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
+ print_npe(KERN_INFO, npe, "firmware EOF block marker not "
+ "found\n");
+ goto err;
+ }
+
+#if DEBUG_FW
+ print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
+#endif
+
+ table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
+ for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
+ if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
+ || blk->offset < table_end) {
+ print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
+ "firmware block #%i\n", blk->offset, i);
+ goto err;
+ }
+
+ cb = (struct dl_codeblock*)&image->data[blk->offset];
+ if (blk->type == FW_BLOCK_TYPE_INSTR) {
+ if (cb->npe_addr + cb->size > instr_size)
+ goto too_big;
+ cmd = CMD_WR_INS_MEM;
+ } else if (blk->type == FW_BLOCK_TYPE_DATA) {
+ if (cb->npe_addr + cb->size > data_size)
+ goto too_big;
+ cmd = CMD_WR_DATA_MEM;
+ } else {
+ print_npe(KERN_INFO, npe, "invalid firmware block #%i "
+ "type 0x%X\n", i, blk->type);
+ goto err;
+ }
+ if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
+ print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
+ "fit in firmware image: type %c, start 0x%X,"
+ " length 0x%X\n", i,
+ blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+ cb->npe_addr, cb->size);
+ goto err;
+ }
+
+ for (j = 0; j < cb->size; j++)
+ npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
+ }
+
+ npe_start(npe);
+ if (!npe_running(npe))
+ print_npe(KERN_ERR, npe, "unable to start\n");
+ release_firmware(fw_entry);
+ return 0;
+
+too_big:
+ print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
+ "memory: type %c, start 0x%X, length 0x%X\n", i,
+ blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+ cb->npe_addr, cb->size);
+err:
+ release_firmware(fw_entry);
+ return err;
+}
+
+
+struct npe *npe_request(int id)
+{
+ if (id < NPE_COUNT)
+ if (npe_tab[id].valid)
+ if (try_module_get(THIS_MODULE))
+ return &npe_tab[id];
+ return NULL;
+}
+
+void npe_release(struct npe *npe)
+{
+ module_put(THIS_MODULE);
+}
+
+
+static int __init npe_init_module(void)
+{
+
+ int i, found = 0;
+
+ for (i = 0; i < NPE_COUNT; i++) {
+ struct npe *npe = &npe_tab[i];
+ if (!(ixp4xx_read_feature_bits() &
+ (IXP4XX_FEATURE_RESET_NPEA << i)))
+ continue; /* NPE already disabled or not present */
+ if (!(npe->mem_res = request_mem_region(npe->regs_phys,
+ REGS_SIZE,
+ npe_name(npe)))) {
+ print_npe(KERN_ERR, npe,
+ "failed to request memory region\n");
+ continue;
+ }
+
+ if (npe_reset(npe))
+ continue;
+ npe->valid = 1;
+ found++;
+ }
+
+ if (!found)
+ return -ENOSYS;
+ return 0;
+}
+
+static void __exit npe_cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < NPE_COUNT; i++)
+ if (npe_tab[i].mem_res) {
+ npe_reset(&npe_tab[i]);
+ release_resource(npe_tab[i].mem_res);
+ }
+}
+
+module_init(npe_init_module);
+module_exit(npe_cleanup_module);
+
+MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_LICENSE("GPL v2");
+
+EXPORT_SYMBOL(npe_names);
+EXPORT_SYMBOL(npe_running);
+EXPORT_SYMBOL(npe_request);
+EXPORT_SYMBOL(npe_release);
+EXPORT_SYMBOL(npe_load_firmware);
+EXPORT_SYMBOL(npe_send_message);
+EXPORT_SYMBOL(npe_recv_message);
+EXPORT_SYMBOL(npe_send_recv_message);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
new file mode 100644
index 000000000000..e83301325301
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -0,0 +1,274 @@
+/*
+ * Intel IXP4xx Queue Manager driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/arch/qmgr.h>
+
+#define DEBUG 0
+
+struct qmgr_regs __iomem *qmgr_regs;
+static struct resource *mem_res;
+static spinlock_t qmgr_lock;
+static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
+static void (*irq_handlers[HALF_QUEUES])(void *pdev);
+static void *irq_pdevs[HALF_QUEUES];
+
+void qmgr_set_irq(unsigned int queue, int src,
+ void (*handler)(void *pdev), void *pdev)
+{
+ u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
+ int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
+ unsigned long flags;
+
+ src &= 7;
+ spin_lock_irqsave(&qmgr_lock, flags);
+ __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
+ irq_handlers[queue] = handler;
+ irq_pdevs[queue] = pdev;
+ spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+
+static irqreturn_t qmgr_irq1(int irq, void *pdev)
+{
+ int i;
+ u32 val = __raw_readl(&qmgr_regs->irqstat[0]);
+ __raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */
+
+ for (i = 0; i < HALF_QUEUES; i++)
+ if (val & (1 << i))
+ irq_handlers[i](irq_pdevs[i]);
+
+ return val ? IRQ_HANDLED : 0;
+}
+
+
+void qmgr_enable_irq(unsigned int queue)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&qmgr_lock, flags);
+ __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
+ &qmgr_regs->irqen[0]);
+ spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+void qmgr_disable_irq(unsigned int queue)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&qmgr_lock, flags);
+ __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
+ &qmgr_regs->irqen[0]);
+ spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+static inline void shift_mask(u32 *mask)
+{
+ mask[3] = mask[3] << 1 | mask[2] >> 31;
+ mask[2] = mask[2] << 1 | mask[1] >> 31;
+ mask[1] = mask[1] << 1 | mask[0] >> 31;
+ mask[0] <<= 1;
+}
+
+int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+ unsigned int nearly_empty_watermark,
+ unsigned int nearly_full_watermark)
+{
+ u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
+ int err;
+
+ if (queue >= HALF_QUEUES)
+ return -ERANGE;
+
+ if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
+ return -EINVAL;
+
+ switch (len) {
+ case 16:
+ cfg = 0 << 24;
+ mask[0] = 0x1;
+ break;
+ case 32:
+ cfg = 1 << 24;
+ mask[0] = 0x3;
+ break;
+ case 64:
+ cfg = 2 << 24;
+ mask[0] = 0xF;
+ break;
+ case 128:
+ cfg = 3 << 24;
+ mask[0] = 0xFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cfg |= nearly_empty_watermark << 26;
+ cfg |= nearly_full_watermark << 29;
+ len /= 16; /* in 16-dwords: 1, 2, 4 or 8 */
+ mask[1] = mask[2] = mask[3] = 0;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ spin_lock_irq(&qmgr_lock);
+ if (__raw_readl(&qmgr_regs->sram[queue])) {
+ err = -EBUSY;
+ goto err;
+ }
+
+ while (1) {
+ if (!(used_sram_bitmap[0] & mask[0]) &&
+ !(used_sram_bitmap[1] & mask[1]) &&
+ !(used_sram_bitmap[2] & mask[2]) &&
+ !(used_sram_bitmap[3] & mask[3]))
+ break; /* found free space */
+
+ addr++;
+ shift_mask(mask);
+ if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
+ printk(KERN_ERR "qmgr: no free SRAM space for"
+ " queue %i\n", queue);
+ err = -ENOMEM;
+ goto err;
+ }
+ }
+
+ used_sram_bitmap[0] |= mask[0];
+ used_sram_bitmap[1] |= mask[1];
+ used_sram_bitmap[2] |= mask[2];
+ used_sram_bitmap[3] |= mask[3];
+ __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
+ spin_unlock_irq(&qmgr_lock);
+
+#if DEBUG
+ printk(KERN_DEBUG "qmgr: requested queue %i, addr = 0x%02X\n",
+ queue, addr);
+#endif
+ return 0;
+
+err:
+ spin_unlock_irq(&qmgr_lock);
+ module_put(THIS_MODULE);
+ return err;
+}
+
+void qmgr_release_queue(unsigned int queue)
+{
+ u32 cfg, addr, mask[4];
+
+ BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
+
+ spin_lock_irq(&qmgr_lock);
+ cfg = __raw_readl(&qmgr_regs->sram[queue]);
+ addr = (cfg >> 14) & 0xFF;
+
+ BUG_ON(!addr); /* not requested */
+
+ switch ((cfg >> 24) & 3) {
+ case 0: mask[0] = 0x1; break;
+ case 1: mask[0] = 0x3; break;
+ case 2: mask[0] = 0xF; break;
+ case 3: mask[0] = 0xFF; break;
+ }
+
+ while (addr--)
+ shift_mask(mask);
+
+ __raw_writel(0, &qmgr_regs->sram[queue]);
+
+ used_sram_bitmap[0] &= ~mask[0];
+ used_sram_bitmap[1] &= ~mask[1];
+ used_sram_bitmap[2] &= ~mask[2];
+ used_sram_bitmap[3] &= ~mask[3];
+ irq_handlers[queue] = NULL; /* catch IRQ bugs */
+ spin_unlock_irq(&qmgr_lock);
+
+ module_put(THIS_MODULE);
+#if DEBUG
+ printk(KERN_DEBUG "qmgr: released queue %i\n", queue);
+#endif
+}
+
+static int qmgr_init(void)
+{
+ int i, err;
+ mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
+ IXP4XX_QMGR_REGION_SIZE,
+ "IXP4xx Queue Manager");
+ if (mem_res == NULL)
+ return -EBUSY;
+
+ qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
+ if (qmgr_regs == NULL) {
+ err = -ENOMEM;
+ goto error_map;
+ }
+
+ /* reset qmgr registers */
+ for (i = 0; i < 4; i++) {
+ __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
+ __raw_writel(0, &qmgr_regs->irqsrc[i]);
+ }
+ for (i = 0; i < 2; i++) {
+ __raw_writel(0, &qmgr_regs->stat2[i]);
+ __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
+ __raw_writel(0, &qmgr_regs->irqen[i]);
+ }
+
+ for (i = 0; i < QUEUES; i++)
+ __raw_writel(0, &qmgr_regs->sram[i]);
+
+ err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
+ "IXP4xx Queue Manager", NULL);
+ if (err) {
+ printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
+ IRQ_IXP4XX_QM1);
+ goto error_irq;
+ }
+
+ used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
+ spin_lock_init(&qmgr_lock);
+
+ printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
+ return 0;
+
+error_irq:
+ iounmap(qmgr_regs);
+error_map:
+ release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
+ return err;
+}
+
+static void qmgr_remove(void)
+{
+ free_irq(IRQ_IXP4XX_QM1, NULL);
+ synchronize_irq(IRQ_IXP4XX_QM1);
+ iounmap(qmgr_regs);
+ release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
+}
+
+module_init(qmgr_init);
+module_exit(qmgr_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Krzysztof Halasa");
+
+EXPORT_SYMBOL(qmgr_regs);
+EXPORT_SYMBOL(qmgr_set_irq);
+EXPORT_SYMBOL(qmgr_enable_irq);
+EXPORT_SYMBOL(qmgr_disable_irq);
+EXPORT_SYMBOL(qmgr_request_queue);
+EXPORT_SYMBOL(qmgr_release_queue);
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
deleted file mode 100644
index 29aa98d3a7fa..000000000000
--- a/arch/arm/mach-ixp4xx/nas100d-power.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/nas100d-power.c
- *
- * NAS 100d Power/Reset driver
- *
- * Copyright (C) 2005 Tower Technologies
- *
- * based on nas100d-io.c
- * Copyright (C) 2004 Karen Spearel
- *
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- * Maintainers: http://www.nslu2-linux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-
-#include <asm/mach-types.h>
-
-static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
-{
- /* Signal init to do the ctrlaltdel action, this will bypass init if
- * it hasn't started and do a kernel_restart.
- */
- ctrl_alt_del();
-
- return IRQ_HANDLED;
-}
-
-static int __init nas100d_power_init(void)
-{
- if (!(machine_is_nas100d()))
- return 0;
-
- set_irq_type(NAS100D_RB_IRQ, IRQT_LOW);
-
- if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler,
- IRQF_DISABLED, "NAS100D reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- NAS100D_RB_IRQ);
-
- return -EIO;
- }
-
- return 0;
-}
-
-static void __exit nas100d_power_exit(void)
-{
- if (!(machine_is_nas100d()))
- return;
-
- free_irq(NAS100D_RB_IRQ, NULL);
-}
-
-module_init(nas100d_power_init);
-module_exit(nas100d_power_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("NAS100D Power/Reset driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 54d884fb2517..4cecae84837b 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -3,8 +3,14 @@
*
* NAS 100d board-setup
*
- * based ixdp425-setup.c:
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * based on ixdp425-setup.c:
* Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nas100d-power.c:
+ * Copyright (C) 2005 Tower Technologies
+ * based on nas100d-io.c
+ * Copyright (C) 2004 Karen Spearel
*
* Author: Alessandro Zummo <a.zummo@towertech.it>
* Author: Rod Whitby <rod@whitby.id.au>
@@ -12,15 +18,22 @@
*
*/
-#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
static struct flash_platform_data nas100d_flash_data = {
.map_name = "cfi_probe",
@@ -39,35 +52,40 @@ static struct platform_device nas100d_flash = {
.resource = &nas100d_flash_resource,
};
-#ifdef CONFIG_LEDS_IXP4XX
-static struct resource nas100d_led_resources[] = {
+static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
+ {
+ I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ },
+};
+
+static struct gpio_led nas100d_led_pins[] = {
{
.name = "wlan", /* green led */
- .start = 0,
- .end = 0,
- .flags = IXP4XX_GPIO_LOW,
+ .gpio = NAS100D_LED_WLAN_GPIO,
+ .active_low = true,
},
{
- .name = "ready", /* blue power led (off is flashing!) */
- .start = 15,
- .end = 15,
- .flags = IXP4XX_GPIO_LOW,
+ .name = "power", /* blue power led (off=flashing) */
+ .gpio = NAS100D_LED_PWR_GPIO,
+ .active_low = true,
},
{
.name = "disk", /* yellow led */
- .start = 3,
- .end = 3,
- .flags = IXP4XX_GPIO_LOW,
+ .gpio = NAS100D_LED_DISK_GPIO,
+ .active_low = true,
},
};
+static struct gpio_led_platform_data nas100d_led_data = {
+ .num_leds = ARRAY_SIZE(nas100d_led_pins),
+ .leds = nas100d_led_pins,
+};
+
static struct platform_device nas100d_leds = {
- .name = "IXP4XX-GPIO-LED",
+ .name = "leds-gpio",
.id = -1,
- .num_resources = ARRAY_SIZE(nas100d_led_resources),
- .resource = nas100d_led_resources,
+ .dev.platform_data = &nas100d_led_data,
};
-#endif
static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
.sda_pin = NAS100D_SDA_PIN,
@@ -125,12 +143,28 @@ static struct platform_device nas100d_uart = {
.resource = nas100d_uart_resources,
};
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info nas100d_plat_eth[] = {
+ {
+ .phy = 0,
+ .rxq = 3,
+ .txreadyq = 20,
+ }
+};
+
+static struct platform_device nas100d_eth[] = {
+ {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEB,
+ .dev.platform_data = nas100d_plat_eth,
+ }
+};
+
static struct platform_device *nas100d_devices[] __initdata = {
&nas100d_i2c_gpio,
&nas100d_flash,
-#ifdef CONFIG_LEDS_IXP4XX
&nas100d_leds,
-#endif
+ &nas100d_eth[0],
};
static void nas100d_power_off(void)
@@ -144,8 +178,63 @@ static void nas100d_power_off(void)
gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH);
}
+/* This is used to make sure the power-button pusher is serious. The button
+ * must be held until the value of this counter reaches zero.
+ */
+static int power_button_countdown;
+
+/* Must hold the button down for at least this many counts to be processed */
+#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+
+static void nas100d_power_handler(unsigned long data);
+static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
+
+static void nas100d_power_handler(unsigned long data)
+{
+ /* This routine is called twice per second to check the
+ * state of the power button.
+ */
+
+ if (gpio_get_value(NAS100D_PB_GPIO)) {
+
+ /* IO Pin is 1 (button pushed) */
+ if (power_button_countdown > 0)
+ power_button_countdown--;
+
+ } else {
+
+ /* Done on button release, to allow for auto-power-on mods. */
+ if (power_button_countdown == 0) {
+ /* Signal init to do the ctrlaltdel action,
+ * this will bypass init if it hasn't started
+ * and do a kernel_restart.
+ */
+ ctrl_alt_del();
+
+ /* Change the state of the power LED to "blink" */
+ gpio_line_set(NAS100D_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+ } else {
+ power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+ }
+ }
+
+ mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
+{
+ /* This is the paper-clip reset, it shuts the machine down directly. */
+ machine_power_off();
+
+ return IRQ_HANDLED;
+}
+
static void __init nas100d_init(void)
{
+ DECLARE_MAC_BUF(mac_buf);
+ uint8_t __iomem *f;
+ int i;
+
ixp4xx_sys_init();
/* gpio 14 and 15 are _not_ clocks */
@@ -155,7 +244,8 @@ static void __init nas100d_init(void)
nas100d_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
- pm_power_off = nas100d_power_off;
+ i2c_register_board_info(0, nas100d_i2c_board_info,
+ ARRAY_SIZE(nas100d_i2c_board_info));
/*
* This is only useful on a modified machine, but it is valuable
@@ -165,6 +255,48 @@ static void __init nas100d_init(void)
(void)platform_device_register(&nas100d_uart);
platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
+
+ pm_power_off = nas100d_power_off;
+
+ if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_LOW,
+ "NAS100D reset button", NULL) < 0) {
+
+ printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+ gpio_to_irq(NAS100D_RB_GPIO));
+ }
+
+ /* The power button on the Iomega NAS100d is on GPIO 14, but
+ * it cannot handle interrupts on that GPIO line. So we'll
+ * have to poll it with a kernel timer.
+ */
+
+ /* Make sure that the power button GPIO is set up as an input */
+ gpio_line_config(NAS100D_PB_GPIO, IXP4XX_GPIO_IN);
+
+ /* Set the initial value for the power button IRQ handler */
+ power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+ mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
+
+ /*
+ * Map in a portion of the flash and read the MAC address.
+ * Since it is stored in BE in the flash itself, we need to
+ * byteswap it if we're in LE mode.
+ */
+ f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000);
+ if (f) {
+ for (i = 0; i < 6; i++)
+#ifdef __ARMEB__
+ nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + i);
+#else
+ nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + (i^3));
+#endif
+ iounmap(f);
+ }
+ printk(KERN_INFO "NAS100D: Using MAC address %s for port 0\n",
+ print_mac(mac_buf, nas100d_plat_eth[0].hwaddr));
+
}
MACHINE_START(NAS100D, "Iomega NAS 100d")
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
deleted file mode 100644
index 6f10dc208320..000000000000
--- a/arch/arm/mach-ixp4xx/nslu2-power.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/nslu2-power.c
- *
- * NSLU2 Power/Reset driver
- *
- * Copyright (C) 2005 Tower Technologies
- *
- * based on nslu2-io.c
- * Copyright (C) 2004 Karen Spearel
- *
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- * Maintainers: http://www.nslu2-linux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-#include <asm/mach-types.h>
-
-static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
-{
- /* Signal init to do the ctrlaltdel action, this will bypass init if
- * it hasn't started and do a kernel_restart.
- */
- ctrl_alt_del();
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset, it shuts the machine down directly.
- */
- machine_power_off();
-
- return IRQ_HANDLED;
-}
-
-static int __init nslu2_power_init(void)
-{
- if (!(machine_is_nslu2()))
- return 0;
-
- *IXP4XX_GPIO_GPISR = 0x20400000; /* read the 2 irqs to clr */
-
- set_irq_type(NSLU2_RB_IRQ, IRQT_LOW);
- set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH);
-
- if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler,
- IRQF_DISABLED, "NSLU2 reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- NSLU2_RB_IRQ);
-
- return -EIO;
- }
-
- if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler,
- IRQF_DISABLED, "NSLU2 power button", NULL) < 0) {
-
- printk(KERN_DEBUG "Power Button IRQ %d not available\n",
- NSLU2_PB_IRQ);
-
- return -EIO;
- }
-
- return 0;
-}
-
-static void __exit nslu2_power_exit(void)
-{
- if (!(machine_is_nslu2()))
- return;
-
- free_irq(NSLU2_RB_IRQ, NULL);
- free_irq(NSLU2_PB_IRQ, NULL);
-}
-
-module_init(nslu2_power_init);
-module_exit(nslu2_power_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("NSLU2 Power/Reset driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 77277d27fcc5..acaebcbce53a 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -3,27 +3,35 @@
*
* NSLU2 board-setup
*
- * based ixdp425-setup.c:
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * based on ixdp425-setup.c:
* Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nslu2-power.c:
+ * Copyright (C) 2005 Tower Technologies
*
* Author: Mark Rakes <mrakes at mac.com>
* Author: Rod Whitby <rod@whitby.id.au>
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
* Maintainers: http://www.nslu2-linux.org/
*
- * Fixed missing init_time in MACHINE_START kas11 10/22/04
- * Changed to conform to new style __init ixdp425 kas11 10/22/04
*/
-#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/irq.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
static struct flash_platform_data nslu2_flash_data = {
.map_name = "cfi_probe",
@@ -47,41 +55,43 @@ static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
.scl_pin = NSLU2_SCL_PIN,
};
-#ifdef CONFIG_LEDS_IXP4XX
-static struct resource nslu2_led_resources[] = {
+static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
+ {
+ I2C_BOARD_INFO("rtc-x1205", 0x6f),
+ },
+};
+
+static struct gpio_led nslu2_led_pins[] = {
{
.name = "ready", /* green led */
- .start = NSLU2_LED_GRN_GPIO,
- .end = NSLU2_LED_GRN_GPIO,
- .flags = IXP4XX_GPIO_HIGH,
+ .gpio = NSLU2_LED_GRN_GPIO,
},
{
.name = "status", /* red led */
- .start = NSLU2_LED_RED_GPIO,
- .end = NSLU2_LED_RED_GPIO,
- .flags = IXP4XX_GPIO_HIGH,
+ .gpio = NSLU2_LED_RED_GPIO,
},
{
.name = "disk-1",
- .start = NSLU2_LED_DISK1_GPIO,
- .end = NSLU2_LED_DISK1_GPIO,
- .flags = IXP4XX_GPIO_LOW,
+ .gpio = NSLU2_LED_DISK1_GPIO,
+ .active_low = true,
},
{
.name = "disk-2",
- .start = NSLU2_LED_DISK2_GPIO,
- .end = NSLU2_LED_DISK2_GPIO,
- .flags = IXP4XX_GPIO_LOW,
+ .gpio = NSLU2_LED_DISK2_GPIO,
+ .active_low = true,
},
};
+static struct gpio_led_platform_data nslu2_led_data = {
+ .num_leds = ARRAY_SIZE(nslu2_led_pins),
+ .leds = nslu2_led_pins,
+};
+
static struct platform_device nslu2_leds = {
- .name = "IXP4XX-GPIO-LED",
+ .name = "leds-gpio",
.id = -1,
- .num_resources = ARRAY_SIZE(nslu2_led_resources),
- .resource = nslu2_led_resources,
+ .dev.platform_data = &nslu2_led_data,
};
-#endif
static struct platform_device nslu2_i2c_gpio = {
.name = "i2c-gpio",
@@ -140,13 +150,29 @@ static struct platform_device nslu2_uart = {
.resource = nslu2_uart_resources,
};
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info nslu2_plat_eth[] = {
+ {
+ .phy = 1,
+ .rxq = 3,
+ .txreadyq = 20,
+ }
+};
+
+static struct platform_device nslu2_eth[] = {
+ {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEB,
+ .dev.platform_data = nslu2_plat_eth,
+ }
+};
+
static struct platform_device *nslu2_devices[] __initdata = {
&nslu2_i2c_gpio,
&nslu2_flash,
&nslu2_beeper,
-#ifdef CONFIG_LEDS_IXP4XX
&nslu2_leds,
-#endif
+ &nslu2_eth[0],
};
static void nslu2_power_off(void)
@@ -160,6 +186,25 @@ static void nslu2_power_off(void)
gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
}
+static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
+{
+ /* Signal init to do the ctrlaltdel action, this will bypass init if
+ * it hasn't started and do a kernel_restart.
+ */
+ ctrl_alt_del();
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
+{
+ /* This is the paper-clip reset, it shuts the machine down directly.
+ */
+ machine_power_off();
+
+ return IRQ_HANDLED;
+}
+
static void __init nslu2_timer_init(void)
{
/* The xtal on this machine is non-standard. */
@@ -175,13 +220,18 @@ static struct sys_timer nslu2_timer = {
static void __init nslu2_init(void)
{
+ DECLARE_MAC_BUF(mac_buf);
+ uint8_t __iomem *f;
+ int i;
+
ixp4xx_sys_init();
nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
nslu2_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
- pm_power_off = nslu2_power_off;
+ i2c_register_board_info(0, nslu2_i2c_board_info,
+ ARRAY_SIZE(nslu2_i2c_board_info));
/*
* This is only useful on a modified machine, but it is valuable
@@ -191,6 +241,43 @@ static void __init nslu2_init(void)
(void)platform_device_register(&nslu2_uart);
platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
+
+ pm_power_off = nslu2_power_off;
+
+ if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_LOW,
+ "NSLU2 reset button", NULL) < 0) {
+
+ printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+ gpio_to_irq(NSLU2_RB_GPIO));
+ }
+
+ if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_HIGH,
+ "NSLU2 power button", NULL) < 0) {
+
+ printk(KERN_DEBUG "Power Button IRQ %d not available\n",
+ gpio_to_irq(NSLU2_PB_GPIO));
+ }
+
+ /*
+ * Map in a portion of the flash and read the MAC address.
+ * Since it is stored in BE in the flash itself, we need to
+ * byteswap it if we're in LE mode.
+ */
+ f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000);
+ if (f) {
+ for (i = 0; i < 6; i++)
+#ifdef __ARMEB__
+ nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i);
+#else
+ nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3));
+#endif
+ iounmap(f);
+ }
+ printk(KERN_INFO "NSLU2: Using MAC address %s for port 0\n",
+ print_mac(mac_buf, nslu2_plat_eth[0].hwaddr));
+
}
MACHINE_START(NSLU2, "Linksys NSLU2")
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index b5c916c0747d..6e0c4f5b5ae6 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,10 +3,11 @@
#
# Common support (must be linked before board specific support)
-obj-y += clock.o devices.o generic.o irq.o dma.o time.o
+obj-y += clock.o devices.o generic.o irq.o dma.o \
+ time.o gpio.o
obj-$(CONFIG_PXA25x) += pxa25x.o
obj-$(CONFIG_PXA27x) += pxa27x.o
-obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
+obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index 28cfd71c032d..6012177a29a3 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -29,6 +29,7 @@
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 50ff453ad370..bfccb80ac8ef 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -10,6 +10,7 @@
#include <asm/arch/mmc.h>
#include <asm/arch/irda.h>
#include <asm/arch/i2c.h>
+#include <asm/arch/ohci.h>
#include "devices.h"
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 698aeec52961..80721c610d41 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -23,6 +23,7 @@
#include <linux/ioport.h>
#include <linux/pm.h>
#include <linux/string.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -31,7 +32,6 @@
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/gpio.h>
#include "generic.h"
@@ -66,97 +66,6 @@ unsigned int get_memclk_frequency_10khz(void)
EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
- * Handy function to set GPIO alternate functions
- */
-int pxa_last_gpio;
-
-int pxa_gpio_mode(int gpio_mode)
-{
- unsigned long flags;
- int gpio = gpio_mode & GPIO_MD_MASK_NR;
- int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
- int gafr;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- local_irq_save(flags);
- if (gpio_mode & GPIO_DFLT_LOW)
- GPCR(gpio) = GPIO_bit(gpio);
- else if (gpio_mode & GPIO_DFLT_HIGH)
- GPSR(gpio) = GPIO_bit(gpio);
- if (gpio_mode & GPIO_MD_MASK_DIR)
- GPDR(gpio) |= GPIO_bit(gpio);
- else
- GPDR(gpio) &= ~GPIO_bit(gpio);
- gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
- GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(pxa_gpio_mode);
-
-int gpio_direction_input(unsigned gpio)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- GPDR(gpio) &= ~mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- if (value)
- GPSR(gpio) = mask;
- else
- GPCR(gpio) = mask;
- GPDR(gpio) |= mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*
- * Return GPIO level
- */
-int pxa_gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-EXPORT_SYMBOL(pxa_gpio_get_value);
-
-/*
- * Set output GPIO level
- */
-void pxa_gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-EXPORT_SYMBOL(pxa_gpio_set_value);
-
-/*
* Routine to safely enable or disable a clock in the CKEN
*/
void __pxa_set_cken(int clock, int enable)
@@ -171,7 +80,6 @@ void __pxa_set_cken(int clock, int enable)
local_irq_restore(flags);
}
-
EXPORT_SYMBOL(__pxa_set_cken);
/*
@@ -226,3 +134,59 @@ void __init pxa_map_io(void)
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
get_clk_frequency_khz(1);
}
+
+#ifdef CONFIG_PM
+
+static unsigned long saved_gplr[4];
+static unsigned long saved_gpdr[4];
+static unsigned long saved_grer[4];
+static unsigned long saved_gfer[4];
+
+static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+{
+ int i, gpio;
+
+ for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+ saved_gplr[i] = GPLR(gpio);
+ saved_gpdr[i] = GPDR(gpio);
+ saved_grer[i] = GRER(gpio);
+ saved_gfer[i] = GFER(gpio);
+
+ /* Clear GPIO transition detect bits */
+ GEDR(gpio) = GEDR(gpio);
+ }
+ return 0;
+}
+
+static int pxa_gpio_resume(struct sys_device *dev)
+{
+ int i, gpio;
+
+ for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+ /* restore level with set/clear */
+ GPSR(gpio) = saved_gplr[i];
+ GPCR(gpio) = ~saved_gplr[i];
+
+ GRER(gpio) = saved_grer[i];
+ GFER(gpio) = saved_gfer[i];
+ GPDR(gpio) = saved_gpdr[i];
+ }
+ return 0;
+}
+#else
+#define pxa_gpio_suspend NULL
+#define pxa_gpio_resume NULL
+#endif
+
+struct sysdev_class pxa_gpio_sysclass = {
+ .name = "gpio",
+ .suspend = pxa_gpio_suspend,
+ .resume = pxa_gpio_resume,
+};
+
+static int __init pxa_gpio_init(void)
+{
+ return sysdev_class_register(&pxa_gpio_sysclass);
+}
+
+core_initcall(pxa_gpio_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index b30f240a16c7..b3d10b0e52a0 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -16,6 +16,7 @@ extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq_gpio(int gpio_nr);
extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+extern void __init pxa_init_gpio(int gpio_nr);
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
@@ -52,3 +53,6 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
#define pxa3xx_get_clk_frequency_khz(x) (0)
#define pxa3xx_get_memclk_frequency_10khz() (0)
#endif
+
+extern struct sysdev_class pxa_irq_sysclass;
+extern struct sysdev_class pxa_gpio_sysclass;
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
new file mode 100644
index 000000000000..8638dd7dd076
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-pxa/gpio.c
+ *
+ * Generic PXA GPIO handling
+ *
+ * Author: Nicolas Pitre
+ * Created: Jun 15, 2001
+ * Copyright: MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#include "generic.h"
+
+
+struct pxa_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *regbase;
+};
+
+int pxa_last_gpio;
+
+/*
+ * Configure pins for GPIO or other functions
+ */
+int pxa_gpio_mode(int gpio_mode)
+{
+ unsigned long flags;
+ int gpio = gpio_mode & GPIO_MD_MASK_NR;
+ int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+ int gafr;
+
+ if (gpio > pxa_last_gpio)
+ return -EINVAL;
+
+ local_irq_save(flags);
+ if (gpio_mode & GPIO_DFLT_LOW)
+ GPCR(gpio) = GPIO_bit(gpio);
+ else if (gpio_mode & GPIO_DFLT_HIGH)
+ GPSR(gpio) = GPIO_bit(gpio);
+ if (gpio_mode & GPIO_MD_MASK_DIR)
+ GPDR(gpio) |= GPIO_bit(gpio);
+ else
+ GPDR(gpio) &= ~GPIO_bit(gpio);
+ gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+ GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(pxa_gpio_mode);
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 value;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ value = __raw_readl(gpdr);
+ value &= ~mask;
+ __raw_writel(value, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 tmp;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ __raw_writel(mask,
+ pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ tmp = __raw_readl(gpdr);
+ tmp |= mask;
+ __raw_writel(tmp, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/*
+ * Return GPIO level
+ */
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
+}
+
+/*
+ * Set output GPIO level
+ */
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ if (value)
+ __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
+ else
+ __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
+}
+
+static struct pxa_gpio_chip pxa_gpio_chip[] = {
+ [0] = {
+ .regbase = GPIO0_BASE,
+ .chip = {
+ .label = "gpio-0",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 0,
+ .ngpio = 32,
+ },
+ },
+ [1] = {
+ .regbase = GPIO1_BASE,
+ .chip = {
+ .label = "gpio-1",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 32,
+ .ngpio = 32,
+ },
+ },
+ [2] = {
+ .regbase = GPIO2_BASE,
+ .chip = {
+ .label = "gpio-2",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 64,
+ .ngpio = 32, /* 21 for PXA25x */
+ },
+ },
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ [3] = {
+ .regbase = GPIO3_BASE,
+ .chip = {
+ .label = "gpio-3",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 96,
+ .ngpio = 32,
+ },
+ },
+#endif
+};
+
+void __init pxa_init_gpio(int gpio_nr)
+{
+ int i;
+
+ /* add a GPIO chip for each register bank.
+ * the last PXA25x register only contains 21 GPIOs
+ */
+ for (i = 0; i < gpio_nr; i += 32) {
+ if (i+32 > gpio_nr)
+ pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
+ gpiochip_add(&pxa_gpio_chip[i/32].chip);
+ }
+}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 07acb45b16ea..36c6a68beca2 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -310,6 +311,8 @@ void __init pxa_init_irq_gpio(int gpio_nr)
/* Install handler for GPIO>=2 edge detect interrupts */
set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+
+ pxa_init_gpio(gpio_nr);
}
void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
@@ -321,3 +324,64 @@ void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
pxa_low_gpio_chip.set_wake = set_wake;
pxa_muxed_gpio_chip.set_wake = set_wake;
}
+
+#ifdef CONFIG_PM
+static unsigned long saved_icmr[2];
+
+static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+ switch (dev->id) {
+ case 0:
+ saved_icmr[0] = ICMR;
+ ICMR = 0;
+ break;
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ case 1:
+ saved_icmr[1] = ICMR2;
+ ICMR2 = 0;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pxa_irq_resume(struct sys_device *dev)
+{
+ switch (dev->id) {
+ case 0:
+ ICMR = saved_icmr[0];
+ ICLR = 0;
+ ICCR = 1;
+ break;
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ case 1:
+ ICMR2 = saved_icmr[1];
+ ICLR2 = 0;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+#define pxa_irq_suspend NULL
+#define pxa_irq_resume NULL
+#endif
+
+struct sysdev_class pxa_irq_sysclass = {
+ .name = "irq",
+ .suspend = pxa_irq_suspend,
+ .resume = pxa_irq_resume,
+};
+
+static int __init pxa_irq_init(void)
+{
+ return sysdev_class_register(&pxa_irq_sysclass);
+}
+
+core_initcall(pxa_irq_init);
diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
index ec1b2d8f61c4..f5809adce298 100644
--- a/arch/arm/mach-pxa/mfp.c
+++ b/arch/arm/mach-pxa/mfp.c
@@ -22,6 +22,7 @@
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
#include <asm/arch/mfp-pxa3xx.h>
+#include <asm/arch/pxa3xx-regs.h>
/* mfp_spin_lock is used to ensure that MFP register configuration
* (most likely a read-modify-write operation) is atomic, and that
@@ -223,11 +224,19 @@ static int pxa3xx_mfp_resume(struct sys_device *d)
struct pxa3xx_mfp_pin *p = &mfp_table[pin];
__mfp_config_run(p);
}
+
+ /* clear RDH bit when MFP settings are restored
+ *
+ * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
+ * preserve them here in case they will be referenced later
+ */
+ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+
return 0;
}
static struct sysdev_class mfp_sysclass = {
- set_kset_name("mfp"),
+ .name = "mfp",
.suspend = pxa3xx_mfp_suspend,
.resume = pxa3xx_mfp_resume,
};
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 540c3bba5f9a..c14696b9979d 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -29,6 +29,7 @@
#include <asm/mach/arch.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/pxa2xx_spi.h>
#include <asm/arch/pcm027.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index dd54496083cb..209eabf0ed3e 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -164,7 +164,7 @@ static struct resource poodlets_resources[] = {
},
};
-static unsigned long poodle_get_hsync_len(void)
+static unsigned long poodle_get_hsync_invperiod(void)
{
return 0;
}
@@ -174,9 +174,9 @@ static void poodle_null_hsync(void)
}
static struct corgits_machinfo poodle_ts_machinfo = {
- .get_hsync_len = poodle_get_hsync_len,
- .put_hsync = poodle_null_hsync,
- .wait_hsync = poodle_null_hsync,
+ .get_hsync_invperiod = poodle_get_hsync_invperiod,
+ .put_hsync = poodle_null_hsync,
+ .wait_hsync = poodle_null_hsync,
};
static struct platform_device poodle_ts_device = {
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index ddd05bf78e02..599e53fcc2c5 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
@@ -141,11 +142,6 @@ static struct clk pxa25x_clks[] = {
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-#define RESTORE_GPLEVEL(n) do { \
- GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
- GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
-} while (0)
-
/*
* List of global PXA peripheral registers to preserve.
* More ones like CP and general purpose register values are preserved
@@ -153,10 +149,6 @@ static struct clk pxa25x_clks[] = {
*/
enum { SLEEP_SAVE_START = 0,
- SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
- SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
- SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
- SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
@@ -165,7 +157,6 @@ enum { SLEEP_SAVE_START = 0,
SLEEP_SAVE_PSTR,
- SLEEP_SAVE_ICMR,
SLEEP_SAVE_CKEN,
SLEEP_SAVE_SIZE
@@ -174,17 +165,12 @@ enum { SLEEP_SAVE_START = 0,
static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
{
- SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
- SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
- SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
- SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
SAVE(GAFR0_L); SAVE(GAFR0_U);
SAVE(GAFR1_L); SAVE(GAFR1_U);
SAVE(GAFR2_L); SAVE(GAFR2_U);
- SAVE(ICMR); ICMR = 0;
SAVE(CKEN);
SAVE(PSTR);
@@ -198,22 +184,14 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
PSPR = 0;
/* restore registers */
- RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
- RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
- RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
- RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
PSSR = PSSR_RDH | PSSR_PH;
RESTORE(CKEN);
-
- ICLR = 0;
- ICCR = 1;
- RESTORE(ICMR);
RESTORE(PSTR);
}
@@ -304,9 +282,17 @@ static struct platform_device *pxa25x_devices[] __initdata = {
&pxa25x_device_assp,
};
+static struct sys_device pxa25x_sysdev[] = {
+ {
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .cls = &pxa_gpio_sysclass,
+ },
+};
+
static int __init pxa25x_init(void)
{
- int ret = 0;
+ int i, ret = 0;
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
if (cpu_is_pxa25x())
@@ -320,9 +306,18 @@ static int __init pxa25x_init(void)
pxa25x_init_pm();
+ for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) {
+ ret = sysdev_register(&pxa25x_sysdev[i]);
+ if (ret)
+ pr_err("failed to register sysdev[%d]\n", i);
+ }
+
ret = platform_add_devices(pxa25x_devices,
ARRAY_SIZE(pxa25x_devices));
+ if (ret)
+ return ret;
}
+
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
if (cpu_is_pxa25x())
ret = platform_device_register(&pxa_device_hwuart);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 96cf274ec7cb..46a951c3e5a0 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/platform_device.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -171,11 +172,6 @@ static struct clk pxa27x_clks[] = {
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-#define RESTORE_GPLEVEL(n) do { \
- GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
- GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
-} while (0)
-
/*
* List of global PXA peripheral registers to preserve.
* More ones like CP and general purpose register values are preserved
@@ -183,10 +179,6 @@ static struct clk pxa27x_clks[] = {
*/
enum { SLEEP_SAVE_START = 0,
- SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
- SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
- SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
- SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
@@ -196,7 +188,6 @@ enum { SLEEP_SAVE_START = 0,
SLEEP_SAVE_PSTR,
- SLEEP_SAVE_ICMR,
SLEEP_SAVE_CKEN,
SLEEP_SAVE_MDREFR,
@@ -208,10 +199,6 @@ enum { SLEEP_SAVE_START = 0,
void pxa27x_cpu_pm_save(unsigned long *sleep_save)
{
- SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3);
- SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3);
- SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3);
- SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3);
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3);
SAVE(GAFR0_L); SAVE(GAFR0_U);
@@ -223,12 +210,8 @@ void pxa27x_cpu_pm_save(unsigned long *sleep_save)
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
SAVE(PFER); SAVE(PKWR);
- SAVE(ICMR); ICMR = 0;
SAVE(CKEN);
SAVE(PSTR);
-
- /* Clear GPIO transition detect bits */
- GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3;
}
void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
@@ -237,15 +220,10 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
PSPR = 0;
/* restore registers */
- RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1);
- RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3);
- RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3);
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
RESTORE(GAFR3_L); RESTORE(GAFR3_U);
- RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3);
- RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3);
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3);
RESTORE(MDREFR);
@@ -256,9 +234,6 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
RESTORE(CKEN);
- ICLR = 0;
- ICCR = 1;
- RESTORE(ICMR);
RESTORE(PSTR);
}
@@ -409,9 +384,22 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_ssp3,
};
+static struct sys_device pxa27x_sysdev[] = {
+ {
+ .id = 0,
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .id = 1,
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .cls = &pxa_gpio_sysclass,
+ },
+};
+
static int __init pxa27x_init(void)
{
- int ret = 0;
+ int i, ret = 0;
+
if (cpu_is_pxa27x()) {
clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
@@ -420,8 +408,15 @@ static int __init pxa27x_init(void)
pxa27x_init_pm();
+ for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) {
+ ret = sysdev_register(&pxa27x_sysdev[i]);
+ if (ret)
+ pr_err("failed to register sysdev[%d]\n", i);
+ }
+
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
+
return ret;
}
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 5cbf057a1b32..e47e67c11afe 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/arch/pxa3xx-regs.h>
@@ -39,6 +40,7 @@
#define RO_CLK 60000000
#define ACCR_D0CS (1 << 26)
+#define ACCR_PCCE (1 << 11)
/* crystal frequency to static memory controller multiplier (SMCFS) */
static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
@@ -203,7 +205,6 @@ static struct clk pxa3xx_clks[] = {
};
#ifdef CONFIG_PM
-#define SLEEP_SAVE_SIZE 4
#define ISRAM_START 0x5c000000
#define ISRAM_SIZE SZ_256K
@@ -211,25 +212,29 @@ static struct clk pxa3xx_clks[] = {
static void __iomem *sram;
static unsigned long wakeup_src;
-static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
-{
- pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB);
+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
- if (CKENA & (1 << CKEN_USBH)) {
- printk(KERN_ERR "PM: USB host clock not stopped?\n");
- CKENA &= ~(1 << CKEN_USBH);
- }
-// CKENA |= 1 << (CKEN_ISC & 31);
+enum { SLEEP_SAVE_START = 0,
+ SLEEP_SAVE_CKENA,
+ SLEEP_SAVE_CKENB,
+ SLEEP_SAVE_ACCR,
- /*
- * Low power modes require the HSIO2 clock to be enabled.
- */
- CKENB |= 1 << (CKEN_HSIO2 & 31);
+ SLEEP_SAVE_SIZE,
+};
+
+static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
+{
+ SAVE(CKENA);
+ SAVE(CKENB);
+ SAVE(ACCR);
}
static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
{
- CKENB &= ~(1 << (CKEN_HSIO2 & 31));
+ RESTORE(ACCR);
+ RESTORE(CKENA);
+ RESTORE(CKENB);
}
/*
@@ -265,6 +270,46 @@ static void pxa3xx_cpu_standby(unsigned int pwrmode)
printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
}
+/*
+ * NOTE: currently, the OBM (OEM Boot Module) binary comes along with
+ * PXA3xx development kits assumes that the resuming process continues
+ * with the address stored within the first 4 bytes of SDRAM. The PSPR
+ * register is used privately by BootROM and OBM, and _must_ be set to
+ * 0x5c014000 for the moment.
+ */
+static void pxa3xx_cpu_pm_suspend(void)
+{
+ volatile unsigned long *p = (volatile void *)0xc0000000;
+ unsigned long saved_data = *p;
+
+ extern void pxa3xx_cpu_suspend(void);
+ extern void pxa3xx_cpu_resume(void);
+
+ /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
+ CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
+ CKENB |= 1 << (CKEN_HSIO2 & 0x1f);
+
+ /* clear and setup wakeup source */
+ AD3SR = ~0;
+ AD3ER = wakeup_src;
+ ASCR = ASCR;
+ ARSR = ARSR;
+
+ PCFR |= (1u << 13); /* L1_DIS */
+ PCFR &= ~((1u << 12) | (1u << 1)); /* L0_EN | SL_ROD */
+
+ PSPR = 0x5c014000;
+
+ /* overwrite with the resume address */
+ *p = virt_to_phys(pxa3xx_cpu_resume);
+
+ pxa3xx_cpu_suspend();
+
+ *p = saved_data;
+
+ AD3ER = 0;
+}
+
static void pxa3xx_cpu_pm_enter(suspend_state_t state)
{
/*
@@ -279,6 +324,7 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state)
break;
case PM_SUSPEND_MEM:
+ pxa3xx_cpu_pm_suspend();
break;
}
}
@@ -452,9 +498,21 @@ static struct platform_device *devices[] __initdata = {
&pxa3xx_device_ssp4,
};
+static struct sys_device pxa3xx_sysdev[] = {
+ {
+ .id = 0,
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .id = 1,
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .cls = &pxa_gpio_sysclass,
+ },
+};
+
static int __init pxa3xx_init(void)
{
- int ret = 0;
+ int i, ret = 0;
if (cpu_is_pxa3xx()) {
clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
@@ -464,9 +522,16 @@ static int __init pxa3xx_init(void)
pxa3xx_init_pm();
- return platform_add_devices(devices, ARRAY_SIZE(devices));
+ for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) {
+ ret = sysdev_register(&pxa3xx_sysdev[i]);
+ if (ret)
+ pr_err("failed to register sysdev[%d]\n", i);
+ }
+
+ ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
- return 0;
+
+ return ret;
}
subsys_initcall(pxa3xx_init);
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 14bb4a93ea52..784716eb7fc5 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -50,6 +50,108 @@ pxa_cpu_save_sp:
str r0, [r1]
ldr pc, [sp], #4
+#ifdef CONFIG_PXA3xx
+/*
+ * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
+ *
+ * NOTE: unfortunately, pxa_cpu_save_cp can not be reused here since
+ * the auxiliary control register address is different between pxa3xx
+ * and pxa{25x,27x}
+ */
+
+ENTRY(pxa3xx_cpu_suspend)
+
+#ifndef CONFIG_IWMMXT
+ mra r2, r3, acc0
+#endif
+ stmfd sp!, {r2 - r12, lr} @ save registers on stack
+
+ mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
+ mrc p15, 0, r4, c15, c1, 0 @ CP access reg
+ mrc p15, 0, r5, c13, c0, 0 @ PID
+ mrc p15, 0, r6, c3, c0, 0 @ domain ID
+ mrc p15, 0, r7, c2, c0, 0 @ translation table base addr
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
+
+ bic r3, r3, #2 @ clear frequency change bit
+
+ @ store them plus current virtual stack ptr on stack
+ mov r10, sp
+ stmfd sp!, {r3 - r10}
+
+ @ store physical address of stack pointer
+ mov r0, sp
+ bl sleep_phys_sp
+ ldr r1, =sleep_save_sp
+ str r0, [r1]
+
+ @ clean data cache
+ bl xsc3_flush_kern_cache_all
+
+ mov r0, #0x06 @ S2D3C4 mode
+ mcr p14, 0, r0, c7, c0, 0 @ enter sleep
+
+20: b 20b @ waiting for sleep
+
+ .data
+ .align 5
+/*
+ * pxa3xx_cpu_resume
+ */
+
+ENTRY(pxa3xx_cpu_resume)
+
+ mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+ msr cpsr_c, r0
+
+ ldr r0, sleep_save_sp @ stack phys addr
+ ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr
+
+ mov r1, #0
+ mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB
+ mcr p15, 0, r1, c7, c10, 4 @ drain write (&fill) buffer
+ mcr p15, 0, r1, c7, c5, 4 @ flush prefetch buffer
+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
+
+ mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode.
+ mcr p15, 0, r4, c15, c1, 0 @ CP access reg
+ mcr p15, 0, r5, c13, c0, 0 @ PID
+ mcr p15, 0, r6, c3, c0, 0 @ domain ID
+ mcr p15, 0, r7, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+
+ @ temporarily map resume_turn_on_mmu into the page table,
+ @ otherwise prefetch abort occurs after MMU is turned on
+ mov r1, r7
+ bic r1, r1, #0x00ff
+ bic r1, r1, #0x3f00
+ ldr r2, =0x542e
+
+ adr r3, resume_turn_on_mmu
+ mov r3, r3, lsr #20
+ orr r4, r2, r3, lsl #20
+ ldr r5, [r1, r3, lsl #2]
+ str r4, [r1, r3, lsl #2]
+
+ @ Mapping page table address in the page table
+ mov r6, r1, lsr #20
+ orr r7, r2, r6, lsl #20
+ ldr r8, [r1, r6, lsl #2]
+ str r7, [r1, r6, lsl #2]
+
+ ldr r2, =pxa3xx_resume_after_mmu @ absolute virtual address
+ b resume_turn_on_mmu @ cache align execution
+
+ .text
+pxa3xx_resume_after_mmu:
+ /* restore the temporary mapping */
+ str r5, [r1, r3, lsl #2]
+ str r8, [r1, r6, lsl #2]
+ b resume_after_mmu
+
+#endif /* CONFIG_PXA3xx */
+
#ifdef CONFIG_PXA27x
/*
* pxa27x_cpu_suspend()
diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c
new file mode 100644
index 000000000000..ad346addc028
--- /dev/null
+++ b/arch/arm/mach-pxa/smemc.c
@@ -0,0 +1,88 @@
+/*
+ * Static Memory Controller
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+
+#define SMEMC_PHYS_BASE (0x4A000000)
+#define SMEMC_PHYS_SIZE (0x90)
+
+#define MSC0 (0x08) /* Static Memory Controller Register 0 */
+#define MSC1 (0x0C) /* Static Memory Controller Register 1 */
+#define SXCNFG (0x1C) /* Synchronous Static Memory Control Register */
+#define MEMCLKCFG (0x68) /* Clock Configuration */
+#define CSADRCFG0 (0x80) /* Address Configuration Register for CS0 */
+#define CSADRCFG1 (0x84) /* Address Configuration Register for CS1 */
+#define CSADRCFG2 (0x88) /* Address Configuration Register for CS2 */
+#define CSADRCFG3 (0x8C) /* Address Configuration Register for CS3 */
+
+#ifdef CONFIG_PM
+static void __iomem *smemc_mmio_base;
+
+static unsigned long msc[2];
+static unsigned long sxcnfg, memclkcfg;
+static unsigned long csadrcfg[4];
+
+static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
+{
+ msc[0] = __raw_readl(smemc_mmio_base + MSC0);
+ msc[1] = __raw_readl(smemc_mmio_base + MSC1);
+ sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG);
+ memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG);
+ csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0);
+ csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1);
+ csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2);
+ csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3);
+
+ return 0;
+}
+
+static int pxa3xx_smemc_resume(struct sys_device *dev)
+{
+ __raw_writel(msc[0], smemc_mmio_base + MSC0);
+ __raw_writel(msc[1], smemc_mmio_base + MSC1);
+ __raw_writel(sxcnfg, smemc_mmio_base + SXCNFG);
+ __raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG);
+ __raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0);
+ __raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1);
+ __raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2);
+ __raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3);
+
+ return 0;
+}
+
+static struct sysdev_class smemc_sysclass = {
+ .name = "smemc",
+ .suspend = pxa3xx_smemc_suspend,
+ .resume = pxa3xx_smemc_resume,
+};
+
+static struct sys_device smemc_sysdev = {
+ .id = 0,
+ .cls = &smemc_sysclass,
+};
+
+static int __init smemc_init(void)
+{
+ int ret = 0;
+
+ if (cpu_is_pxa3xx()) {
+ smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE);
+ if (smemc_mmio_base == NULL)
+ return -ENODEV;
+
+ ret = sysdev_class_register(&smemc_sysclass);
+ if (ret)
+ return ret;
+
+ ret = sysdev_register(&smemc_sysdev);
+ }
+
+ return ret;
+}
+subsys_initcall(smemc_init);
+#endif
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 5078edeadf96..9e7773fca01c 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -36,6 +36,7 @@
#include <asm/mach/irq.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/irda.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 1a9c844ac7eb..9b26fa5edad6 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -29,6 +29,7 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/irda.h>
#include <asm/arch/mmc.h>
#include <asm/arch/udc.h>
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 35156ca39df7..39b3bb7f1020 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -7,24 +7,21 @@ config MACH_REALVIEW_EB
help
Include support for the ARM(R) RealView Emulation Baseboard platform.
-config REALVIEW_MPCORE
- bool "Support MPcore tile"
+config REALVIEW_EB_ARM11MP
+ bool "Support ARM11MPCore tile"
depends on MACH_REALVIEW_EB
select CACHE_L2X0
help
- Enable support for the MPCore tile on the Realview platform.
- Since there are device address and interrupt differences, a
- kernel built with this option enabled is not compatible with
- other tiles.
+ Enable support for the ARM11MPCore tile on the Realview platform.
-config REALVIEW_MPCORE_REVB
- bool "Support MPcore RevB tile"
- depends on REALVIEW_MPCORE
+config REALVIEW_EB_ARM11MP_REVB
+ bool "Support ARM11MPCore RevB tile"
+ depends on REALVIEW_EB_ARM11MP
default n
help
- Enable support for the MPCore RevB tile on the Realview platform.
- Since there are device address differences, a
+ Enable support for the ARM11MPCore RevB tile on the Realview
+ platform. Since there are device address differences, a
kernel built with this option enabled is not compatible with
- other tiles.
+ other revisions of the ARM11MPCore tile.
endmenu
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index 36e76ba937fc..ca1e390c3c28 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -4,6 +4,5 @@
obj-y := core.o clock.o
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
-obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 61d70218f1e8..98aefc9f4df3 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -25,6 +25,8 @@
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -37,7 +39,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
#include <asm/mach/map.h>
#include <asm/mach/mmc.h>
@@ -48,6 +49,9 @@
#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
+/* used by entry-macro.S */
+void __iomem *gic_cpu_base_addr;
+
/*
* This is the RealView sched_clock implementation. This has
* a resolution of 41.7ns, and a maximum value of about 179s.
@@ -121,26 +125,6 @@ struct platform_device realview_flash_device = {
.resource = &realview_flash_resource,
};
-static struct resource realview_smc91x_resources[] = {
- [0] = {
- .start = REALVIEW_ETH_BASE,
- .end = REALVIEW_ETH_BASE + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_ETH,
- .end = IRQ_ETH,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device realview_smc91x_device = {
- .name = "smc91x",
- .id = 0,
- .num_resources = ARRAY_SIZE(realview_smc91x_resources),
- .resource = realview_smc91x_resources,
-};
-
static struct resource realview_i2c_resource = {
.start = REALVIEW_I2C_BASE,
.end = REALVIEW_I2C_BASE + SZ_4K - 1,
@@ -484,45 +468,64 @@ void realview_leds_event(led_event_t ledevt)
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
#endif
-/*
- * Returns number of ms since last clock interrupt. Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long realview_gettimeoffset(void)
+static void timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
{
- unsigned long ticks1, ticks2, status;
+ unsigned long ctrl;
- /*
- * Get the current number of ticks. Note that there is a race
- * condition between us reading the timer and checking for
- * an interrupt. We get around this by ensuring that the
- * counter has not reloaded between our two reads.
- */
- ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
- do {
- ticks1 = ticks2;
- status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
- + ((IRQ_TIMERINT0_1 >> 5) << 2));
- ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
- } while (ticks2 > ticks1);
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
- /*
- * Number of ticks since last interrupt.
- */
- ticks1 = TIMER_RELOAD - ticks2;
+ ctrl = TIMER_CTRL_PERIODIC;
+ ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* period set, and timer enabled in 'next_event' hook */
+ ctrl = TIMER_CTRL_ONESHOT;
+ ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ ctrl = 0;
+ }
- /*
- * Interrupt pending? If so, we've reloaded once already.
- *
- * FIXME: Need to check this is effectively timer 0 that expires
- */
- if (status & IRQMASK_TIMERINT0_1)
- ticks1 += TIMER_RELOAD;
+ writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
+}
- /*
- * Convert the ticks to usecs
- */
- return TICKS2USECS(ticks1);
+static int timer_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
+
+ writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
+ writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
+
+ return 0;
+}
+
+static struct clock_event_device timer0_clockevent = {
+ .name = "timer0",
+ .shift = 32,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = timer_set_mode,
+ .set_next_event = timer_set_next_event,
+ .rating = 300,
+ .cpumask = CPU_MASK_ALL,
+};
+
+static void __init realview_clockevents_init(unsigned int timer_irq)
+{
+ timer0_clockevent.irq = timer_irq;
+ timer0_clockevent.mult =
+ div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
+ timer0_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &timer0_clockevent);
+ timer0_clockevent.min_delta_ns =
+ clockevent_delta2ns(0xf, &timer0_clockevent);
+
+ clockevents_register_device(&timer0_clockevent);
}
/*
@@ -530,15 +533,12 @@ static unsigned long realview_gettimeoffset(void)
*/
static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
{
- // ...clear the interrupt
+ struct clock_event_device *evt = &timer0_clockevent;
+
+ /* clear the interrupt */
writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
- timer_tick();
-
-#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
- smp_send_timer();
- update_process_times(user_mode(get_irq_regs()));
-#endif
+ evt->event_handler(evt);
return IRQ_HANDLED;
}
@@ -549,13 +549,49 @@ static struct irqaction realview_timer_irq = {
.handler = realview_timer_interrupt,
};
+static cycle_t realview_get_cycles(void)
+{
+ return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
+}
+
+static struct clocksource clocksource_realview = {
+ .name = "timer3",
+ .rating = 200,
+ .read = realview_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init realview_clocksource_init(void)
+{
+ /* setup timer 0 as free-running clocksource */
+ writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+ writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
+ writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
+ writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+ TIMER3_VA_BASE + TIMER_CTRL);
+
+ clocksource_realview.mult =
+ clocksource_khz2mult(1000, clocksource_realview.shift);
+ clocksource_register(&clocksource_realview);
+}
+
/*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up the clock source and clock events devices
*/
-static void __init realview_timer_init(void)
+void __init realview_timer_init(unsigned int timer_irq)
{
u32 val;
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+ /*
+ * The dummy clock device has to be registered before the main device
+ * so that the latter will broadcast the clock events
+ */
+ local_timer_setup(smp_processor_id());
+#endif
+
/*
* set clock frequency:
* REALVIEW_REFCLK is 32KHz
@@ -576,18 +612,11 @@ static void __init realview_timer_init(void)
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
- writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
- writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
- writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
- TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
-
/*
* Make irqs happen for the system timer
*/
- setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
-}
+ setup_irq(timer_irq, &realview_timer_irq);
-struct sys_timer realview_timer = {
- .init = realview_timer_init,
- .offset = realview_gettimeoffset,
-};
+ realview_clocksource_init();
+ realview_clockevents_init(timer_irq);
+}
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 2b53420f9c1b..492a14c0d604 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -27,8 +27,6 @@
#include <asm/leds.h>
#include <asm/io.h>
-extern struct sys_timer realview_timer;
-
#define AMBA_DEVICE(name,busid,base,plat) \
static struct amba_device name##_device = { \
.dev = { \
@@ -38,7 +36,7 @@ static struct amba_device name##_device = { \
}, \
.res = { \
.start = REALVIEW_##base##_BASE, \
- .end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\
+ .end = (REALVIEW_##base##_BASE) + SZ_4K - 1, \
.flags = IORESOURCE_MEM, \
}, \
.dma_mask = ~0, \
@@ -46,74 +44,19 @@ static struct amba_device name##_device = { \
/* .dma = base##_DMA,*/ \
}
-/*
- * These devices are connected via the core APB bridge
- */
-#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
-#define GPIO2_DMA { 0, 0 }
-#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
-#define GPIO3_DMA { 0, 0 }
-
-#define AACI_IRQ { IRQ_AACI, NO_IRQ }
-#define AACI_DMA { 0x80, 0x81 }
-#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B }
-#define MMCI0_DMA { 0x84, 0 }
-#define KMI0_IRQ { IRQ_KMI0, NO_IRQ }
-#define KMI0_DMA { 0, 0 }
-#define KMI1_IRQ { IRQ_KMI1, NO_IRQ }
-#define KMI1_DMA { 0, 0 }
-
-/*
- * These devices are connected directly to the multi-layer AHB switch
- */
-#define SMC_IRQ { NO_IRQ, NO_IRQ }
-#define SMC_DMA { 0, 0 }
-#define MPMC_IRQ { NO_IRQ, NO_IRQ }
-#define MPMC_DMA { 0, 0 }
-#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
-#define CLCD_DMA { 0, 0 }
-#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
-#define DMAC_DMA { 0, 0 }
-
-/*
- * These devices are connected via the core APB bridge
- */
-#define SCTL_IRQ { NO_IRQ, NO_IRQ }
-#define SCTL_DMA { 0, 0 }
-#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
-#define WATCHDOG_DMA { 0, 0 }
-#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
-#define GPIO0_DMA { 0, 0 }
-#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
-#define GPIO1_DMA { 0, 0 }
-#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
-#define RTC_DMA { 0, 0 }
-
-/*
- * These devices are connected via the DMA APB bridge
- */
-#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
-#define SCI_DMA { 7, 6 }
-#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
-#define UART0_DMA { 15, 14 }
-#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
-#define UART1_DMA { 13, 12 }
-#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
-#define UART2_DMA { 11, 10 }
-#define UART3_IRQ { IRQ_UART3, NO_IRQ }
-#define UART3_DMA { 0x86, 0x87 }
-#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
-#define SSP_DMA { 9, 8 }
-
-
extern struct platform_device realview_flash_device;
-extern struct platform_device realview_smc91x_device;
extern struct platform_device realview_i2c_device;
extern struct mmc_platform_data realview_mmc0_plat_data;
extern struct mmc_platform_data realview_mmc1_plat_data;
extern struct clk realview_clcd_clk;
extern struct clcd_board clcd_plat_data;
+extern void __iomem *gic_cpu_base_addr;
+#ifdef CONFIG_LOCAL_TIMERS
+extern void __iomem *twd_base_addr;
+extern unsigned int twd_size;
+#endif
extern void realview_leds_event(led_event_t ledevt);
+extern void realview_timer_init(unsigned int timer_irq);
#endif
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index c7bdf04ab094..50604360479f 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -14,19 +14,75 @@
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/jiffies.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
-#include <asm/mach/time.h>
#include <asm/hardware/arm_twd.h>
#include <asm/hardware/gic.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
-#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \
- ((cpu) * REALVIEW_TWD_SIZE))
+static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
+
+/*
+ * Used on SMP for either the local timer or IPI_TIMER
+ */
+void local_timer_interrupt(void)
+{
+ struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
+
+ clk->event_handler(clk);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size)
+
+/* set up by the platform code */
+void __iomem *twd_base_addr;
+unsigned int twd_size;
static unsigned long mpcore_timer_rate;
+static void local_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ void __iomem *base = TWD_BASE(smp_processor_id());
+ unsigned long ctrl;
+
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* timer load already set up */
+ ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
+ | TWD_TIMER_CONTROL_PERIODIC;
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* period set, and timer enabled in 'next_event' hook */
+ ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ ctrl = 0;
+ }
+
+ __raw_writel(ctrl, base + TWD_TIMER_CONTROL);
+}
+
+static int local_timer_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ void __iomem *base = TWD_BASE(smp_processor_id());
+ unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL);
+
+ __raw_writel(evt, base + TWD_TIMER_COUNTER);
+ __raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL);
+
+ return 0;
+}
+
/*
* local_timer_ack: checks for a local timer interrupt.
*
@@ -45,12 +101,11 @@ int local_timer_ack(void)
return 0;
}
-void __cpuinit local_timer_setup(unsigned int cpu)
+static void __cpuinit twd_calibrate_rate(unsigned int cpu)
{
void __iomem *base = TWD_BASE(cpu);
- unsigned int load, offset;
+ unsigned long load, count;
u64 waitjiffies;
- unsigned int count;
/*
* If this is the first time round, we need to work out how fast
@@ -88,36 +143,36 @@ void __cpuinit local_timer_setup(unsigned int cpu)
load = mpcore_timer_rate / HZ;
__raw_writel(load, base + TWD_TIMER_LOAD);
- __raw_writel(0x7, base + TWD_TIMER_CONTROL);
-
- /*
- * Now maneuver our local tick into the right part of the jiffy.
- * Start by working out where within the tick our local timer
- * interrupt should go.
- */
- offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1);
-
- /*
- * gettimeoffset() will return a number of us since the last tick.
- * Convert this number of us to a local timer tick count.
- * Be careful of integer overflow whilst keeping maximum precision.
- *
- * with HZ=100 and 1MHz (fpga) ~ 1GHz processor:
- * load = 1 ~ 10,000
- * mpcore_timer_rate/10000 = 100 ~ 100,000
- *
- * so the multiply value will be less than 10^9 always.
- */
- load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100;
-
- /* Add on our offset to get the load value */
- load = (load + offset) % (mpcore_timer_rate / HZ);
+}
- __raw_writel(load, base + TWD_TIMER_COUNTER);
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(unsigned int cpu)
+{
+ struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
+ unsigned long flags;
+
+ twd_calibrate_rate(cpu);
+
+ clk->name = "local_timer";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ clk->rating = 350;
+ clk->set_mode = local_timer_set_mode;
+ clk->set_next_event = local_timer_set_next_event;
+ clk->irq = IRQ_LOCALTIMER;
+ clk->cpumask = cpumask_of_cpu(cpu);
+ clk->shift = 20;
+ clk->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
+ clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
+ clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
/* Make sure our local interrupt controller has this enabled */
- __raw_writel(1 << IRQ_LOCALTIMER,
- __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET);
+ local_irq_save(flags);
+ get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
+ local_irq_restore(flags);
+
+ clockevents_register_device(clk);
}
/*
@@ -127,3 +182,26 @@ void __cpuexit local_timer_stop(unsigned int cpu)
{
__raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
}
+
+#else /* CONFIG_LOCAL_TIMERS */
+
+static void dummy_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+}
+
+void __cpuinit local_timer_setup(unsigned int cpu)
+{
+ struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
+
+ clk->name = "dummy_timer";
+ clk->features = CLOCK_EVT_FEAT_DUMMY;
+ clk->rating = 200;
+ clk->set_mode = dummy_timer_set_mode;
+ clk->broadcast = smp_timer_broadcast;
+ clk->cpumask = cpumask_of_cpu(cpu);
+
+ clockevents_register_device(clk);
+}
+
+#endif /* !CONFIG_LOCAL_TIMERS */
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index fce3596f9950..de2b7159557d 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -18,6 +18,7 @@
#include <asm/hardware/arm_scu.h>
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/mach-types.h>
extern void realview_secondary_startup(void);
@@ -31,9 +32,13 @@ static unsigned int __init get_core_count(void)
{
unsigned int ncores;
- ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG);
+ if (machine_is_realview_eb() && core_tile_eb11mp()) {
+ ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
+ ncores = (ncores & 0x03) + 1;
+ } else
+ ncores = 1;
- return (ncores & 0x03) + 1;
+ return ncores;
}
static DEFINE_SPINLOCK(boot_lock);
@@ -52,7 +57,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+ gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
/*
* let the primary processor know we're out of the
@@ -187,10 +192,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (max_cpus > ncores)
max_cpus = ncores;
+#ifdef CONFIG_LOCAL_TIMERS
/*
- * Enable the local timer for primary CPU
+ * Enable the local timer for primary CPU. If the device is
+ * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
+ * realview_timer_init
*/
- local_timer_setup(cpu);
+ if (machine_is_realview_eb() && core_tile_eb11mp())
+ local_timer_setup(cpu);
+#endif
/*
* Initialise the present map, which describes the set of CPUs
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index ecec2f85c4cd..60d9eb810246 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -36,7 +36,9 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/mmc.h>
+#include <asm/mach/time.h>
+#include <asm/arch/board-eb.h>
#include <asm/arch/irqs.h>
#include "core.h"
@@ -58,26 +60,7 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
.pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
.length = SZ_4K,
.type = MT_DEVICE,
- },
-#ifdef CONFIG_REALVIEW_MPCORE
- {
- .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
- .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
- .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
- .pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
- .length = SZ_8K,
- .type = MT_DEVICE,
- },
-#endif
- {
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
.pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
.length = SZ_4K,
@@ -103,11 +86,95 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
#endif
};
+static struct map_desc realview_eb11mp_io_desc[] __initdata = {
+ {
+ .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_EB11MP_L220_BASE),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }
+};
+
static void __init realview_eb_map_io(void)
{
iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
+ if (core_tile_eb11mp())
+ iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc));
}
+/*
+ * RealView EB AMBA devices
+ */
+
+/*
+ * These devices are connected via the core APB bridge
+ */
+#define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ }
+#define GPIO2_DMA { 0, 0 }
+#define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ }
+#define GPIO3_DMA { 0, 0 }
+
+#define AACI_IRQ { IRQ_EB_AACI, NO_IRQ }
+#define AACI_DMA { 0x80, 0x81 }
+#define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
+#define MMCI0_DMA { 0x84, 0 }
+#define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ }
+#define KMI0_DMA { 0, 0 }
+#define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ }
+#define KMI1_DMA { 0, 0 }
+
+/*
+ * These devices are connected directly to the multi-layer AHB switch
+ */
+#define SMC_IRQ { NO_IRQ, NO_IRQ }
+#define SMC_DMA { 0, 0 }
+#define MPMC_IRQ { NO_IRQ, NO_IRQ }
+#define MPMC_DMA { 0, 0 }
+#define CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
+#define CLCD_DMA { 0, 0 }
+#define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ }
+#define DMAC_DMA { 0, 0 }
+
+/*
+ * These devices are connected via the core APB bridge
+ */
+#define SCTL_IRQ { NO_IRQ, NO_IRQ }
+#define SCTL_DMA { 0, 0 }
+#define WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
+#define WATCHDOG_DMA { 0, 0 }
+#define GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
+#define GPIO0_DMA { 0, 0 }
+#define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ }
+#define GPIO1_DMA { 0, 0 }
+#define RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
+#define RTC_DMA { 0, 0 }
+
+/*
+ * These devices are connected via the DMA APB bridge
+ */
+#define SCI_IRQ { IRQ_EB_SCI, NO_IRQ }
+#define SCI_DMA { 7, 6 }
+#define UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
+#define UART0_DMA { 15, 14 }
+#define UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
+#define UART1_DMA { 13, 12 }
+#define UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
+#define UART2_DMA { 11, 10 }
+#define UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
+#define UART3_DMA { 0x86, 0x87 }
+#define SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
+#define SSP_DMA { 9, 8 }
+
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
@@ -153,38 +220,127 @@ static struct amba_device *amba_devs[] __initdata = {
&kmi1_device,
};
+/*
+ * RealView EB platform devices
+ */
+
+static struct resource realview_eb_smc91x_resources[] = {
+ [0] = {
+ .start = REALVIEW_ETH_BASE,
+ .end = REALVIEW_ETH_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_EB_ETH,
+ .end = IRQ_EB_ETH,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device realview_eb_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(realview_eb_smc91x_resources),
+ .resource = realview_eb_smc91x_resources,
+};
+
static void __init gic_init_irq(void)
{
-#ifdef CONFIG_REALVIEW_MPCORE
- unsigned int pldctrl;
- writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
- pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
- pldctrl |= 0x00800000; /* New irq mode */
- writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
- writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
+ if (core_tile_eb11mp()) {
+ unsigned int pldctrl;
+
+ /* new irq mode */
+ writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
+ pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
+ pldctrl |= 0x00800000;
+ writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
+ writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
+
+ /* core tile GIC, primary */
+ gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
+ gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
+ gic_cpu_init(0, gic_cpu_base_addr);
+
+#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
+ /* board GIC, secondary */
+ gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
+ gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
+ gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
#endif
- gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
- gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
-#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB)
- gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
- gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
- gic_cascade_irq(1, IRQ_EB_IRQ1);
+ } else {
+ /* board GIC, primary */
+ gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
+ gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
+ gic_cpu_init(0, gic_cpu_base_addr);
+ }
+}
+
+/*
+ * Fix up the IRQ numbers for the RealView EB/ARM11MPCore tile
+ */
+static void realview_eb11mp_fixup(void)
+{
+ /* AMBA devices */
+ dmac_device.irq[0] = IRQ_EB11MP_DMA;
+ uart0_device.irq[0] = IRQ_EB11MP_UART0;
+ uart1_device.irq[0] = IRQ_EB11MP_UART1;
+ uart2_device.irq[0] = IRQ_EB11MP_UART2;
+ uart3_device.irq[0] = IRQ_EB11MP_UART3;
+ clcd_device.irq[0] = IRQ_EB11MP_CLCD;
+ wdog_device.irq[0] = IRQ_EB11MP_WDOG;
+ gpio0_device.irq[0] = IRQ_EB11MP_GPIO0;
+ gpio1_device.irq[0] = IRQ_EB11MP_GPIO1;
+ gpio2_device.irq[0] = IRQ_EB11MP_GPIO2;
+ rtc_device.irq[0] = IRQ_EB11MP_RTC;
+ sci0_device.irq[0] = IRQ_EB11MP_SCI;
+ ssp0_device.irq[0] = IRQ_EB11MP_SSP;
+ aaci_device.irq[0] = IRQ_EB11MP_AACI;
+ mmc0_device.irq[0] = IRQ_EB11MP_MMCI0A;
+ mmc0_device.irq[1] = IRQ_EB11MP_MMCI0B;
+ kmi0_device.irq[0] = IRQ_EB11MP_KMI0;
+ kmi1_device.irq[0] = IRQ_EB11MP_KMI1;
+
+ /* platform devices */
+ realview_eb_smc91x_resources[1].start = IRQ_EB11MP_ETH;
+ realview_eb_smc91x_resources[1].end = IRQ_EB11MP_ETH;
+}
+
+static void __init realview_eb_timer_init(void)
+{
+ unsigned int timer_irq;
+
+ if (core_tile_eb11mp()) {
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
+ twd_size = REALVIEW_EB11MP_TWD_SIZE;
#endif
+ timer_irq = IRQ_EB11MP_TIMER0_1;
+ } else
+ timer_irq = IRQ_EB_TIMER0_1;
+
+ realview_timer_init(timer_irq);
}
+static struct sys_timer realview_eb_timer = {
+ .init = realview_eb_timer_init,
+};
+
static void __init realview_eb_init(void)
{
int i;
-#ifdef CONFIG_REALVIEW_MPCORE
- /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
- * Bits: .... ...0 0111 1001 0000 .... .... .... */
- l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
-#endif
+ if (core_tile_eb11mp()) {
+ realview_eb11mp_fixup();
+
+ /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+ * Bits: .... ...0 0111 1001 0000 .... .... .... */
+ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
+ }
+
clk_register(&realview_clcd_clk);
platform_device_register(&realview_flash_device);
- platform_device_register(&realview_smc91x_device);
+ platform_device_register(&realview_eb_smc91x_device);
platform_device_register(&realview_i2c_device);
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -204,6 +360,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
.boot_params = 0x00000100,
.map_io = realview_eb_map_io,
.init_irq = gic_init_irq,
- .timer = &realview_timer,
+ .timer = &realview_eb_timer,
.init_machine = realview_eb_init,
MACHINE_END
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 9e13c8358ea7..5c84c604ed86 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -470,7 +470,7 @@ void __init sa1110_mb_disable(void)
* If the system is going to use the SA-1111 DMA engines, set up
* the memory bus request/grant pins.
*/
-void __init sa1110_mb_enable(void)
+void __devinit sa1110_mb_enable(void)
{
unsigned long flags;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 75952779ce19..303a7ff6bfd2 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -162,7 +162,7 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
* Free the page table, if there was one.
*/
if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
- pte_free_kernel(pmd_page_vaddr(pmd));
+ pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
}
addr += PGDIR_SIZE;
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 50b9aed6000d..500c9610ab30 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -65,14 +65,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
return new_pgd;
no_pte:
- pmd_free(new_pmd);
+ pmd_free(mm, new_pmd);
no_pmd:
free_pages((unsigned long)new_pgd, 2);
no_pgd:
return NULL;
}
-void free_pgd_slow(pgd_t *pgd)
+void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
{
pmd_t *pmd;
struct page *pte;
@@ -94,8 +94,8 @@ void free_pgd_slow(pgd_t *pgd)
pmd_clear(pmd);
dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
pte_lock_deinit(pte);
- pte_free(pte);
- pmd_free(pmd);
+ pte_free(mm, pte);
+ pmd_free(mm, pmd);
free:
free_pages((unsigned long) pgd, 2);
}
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index ba3d21d8fba3..6fe481ff4fdf 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -57,8 +57,6 @@ unsigned long iop_gettimeoffset(void)
static irqreturn_t
iop_timer_interrupt(int irq, void *dev_id)
{
- write_seqlock(&xtime_lock);
-
write_tisr(1);
while ((signed long)(next_jiffy_time - read_tcr1())
@@ -67,8 +65,6 @@ iop_timer_interrupt(int irq, void *dev_id)
next_jiffy_time -= ticks_per_jiffy;
}
- write_sequnlock(&xtime_lock);
-
return IRQ_HANDLED;
}
diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
index 2ec1daaa0e53..766473b3f98b 100644
--- a/arch/arm/plat-s3c24xx/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -130,9 +130,7 @@ static unsigned long s3c2410_gettimeoffset (void)
static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id)
{
- write_seqlock(&xtime_lock);
timer_tick();
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c816f29154c9..28e0caf4156c 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -82,6 +82,7 @@ config PLATFORM_AT32AP
select SUBARCH_AVR32B
select MMU
select PERFORMANCE_COUNTERS
+ select HAVE_GPIO_LIB
#
# CPU types
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d61a02da898c..38a8fa31c0b5 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -24,11 +24,11 @@
#define MAX_NR_PIO_DEVICES 8
struct pio_device {
+ struct gpio_chip chip;
void __iomem *regs;
const struct platform_device *pdev;
struct clk *clk;
u32 pinmux_mask;
- u32 gpio_mask;
char name[8];
};
@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
goto fail;
}
- if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
+ || gpiochip_is_requested(&pio->chip, pin_index))) {
printk("%s: pin %u is busy\n", pio->name, pin_index);
goto fail;
}
@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask);
- /* gpio_request NOT allowed */
- set_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
pio_writel(pio, PER, mask);
- /* gpio_request now allowed */
- clear_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -166,96 +161,50 @@ fail:
/* GPIO API */
-int gpio_request(unsigned int gpio, const char *label)
+static int direction_input(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- pin = gpio & 0x1f;
- if (test_and_set_bit(pin, &pio->gpio_mask))
- return -EBUSY;
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ pio_writel(pio, ODR, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_request);
-void gpio_free(unsigned int gpio)
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
- pio = gpio_to_pio(gpio);
- if (!pio) {
- printk(KERN_ERR
- "gpio: attempted to free invalid pin %u\n", gpio);
- return;
- }
-
- pin = gpio & 0x1f;
- if (!test_and_clear_bit(pin, &pio->gpio_mask))
- printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
- pio->name, pin);
+ return (pio_readl(pio, PDSR) >> offset) & 1;
}
-EXPORT_SYMBOL(gpio_free);
-int gpio_direction_input(unsigned int gpio)
-{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
-
- pin = gpio & 0x1f;
- pio_writel(pio, ODR, 1 << pin);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
-int gpio_direction_output(unsigned int gpio, int value)
+static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- gpio_set_value(gpio, value);
-
- pin = gpio & 0x1f;
- pio_writel(pio, OER, 1 << pin);
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ gpio_set(chip, offset, value);
+ pio_writel(pio, OER, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_output);
-int gpio_get_value(unsigned int gpio)
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio = &pio_dev[gpio >> 5];
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned int gpio, int value)
-{
- struct pio_device *pio = &pio_dev[gpio >> 5];
- u32 mask;
-
- mask = 1 << (gpio & 0x1f);
if (value)
pio_writel(pio, SODR, mask);
else
pio_writel(pio, CODR, mask);
}
-EXPORT_SYMBOL(gpio_set_value);
/*--------------------------------------------------------------------------*/
@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
/*--------------------------------------------------------------------------*/
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+/*
+ * This shows more info than the generic gpio dump code:
+ * pullups, deglitching, open drain drive.
+ */
+static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
+ unsigned i;
+ u32 mask;
+ char bank;
+
+ psr = pio_readl(pio, PSR);
+ osr = pio_readl(pio, OSR);
+ imr = pio_readl(pio, IMR);
+ pdsr = pio_readl(pio, PDSR);
+ pusr = pio_readl(pio, PUSR);
+ ifsr = pio_readl(pio, IFSR);
+ mdsr = pio_readl(pio, MDSR);
+
+ bank = 'A' + pio->pdev->id;
+
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
+ const char *label;
+
+ label = gpiochip_is_requested(chip, i);
+ if (!label)
+ continue;
+
+ seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
+ chip->base + i, bank, i,
+ label,
+ (osr & mask) ? "out" : "in ",
+ (mask & pdsr) ? "hi" : "lo",
+ (mask & pusr) ? " " : "up");
+ if (ifsr & mask)
+ seq_printf(s, " deglitch");
+ if ((osr & mdsr) & mask)
+ seq_printf(s, " open-drain");
+ if (imr & mask)
+ seq_printf(s, " irq-%d edge-both",
+ gpio_to_irq(chip->base + i));
+ seq_printf(s, "\n");
+ }
+}
+
+#else
+#define pio_bank_show NULL
+#endif
+
+
+/*--------------------------------------------------------------------------*/
+
static int __init pio_probe(struct platform_device *pdev)
{
struct pio_device *pio = NULL;
@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
pio = &pio_dev[pdev->id];
BUG_ON(!pio->regs);
+ pio->chip.label = pio->name;
+ pio->chip.base = pdev->id * 32;
+ pio->chip.ngpio = 32;
+
+ pio->chip.direction_input = direction_input;
+ pio->chip.get = gpio_get;
+ pio->chip.direction_output = direction_output;
+ pio->chip.set = gpio_set;
+ pio->chip.dbg_show = pio_bank_show;
+
+ gpiochip_add(&pio->chip);
+
gpio_irq_setup(pio, irq, gpio_irq_base);
platform_set_drvdata(pdev, pio);
@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
pio->pdev = pdev;
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
- /*
- * request_gpio() is only valid for pins that have been
- * explicitly configured as GPIO and not previously requested
- */
- pio->gpio_mask = ~0UL;
-
/* start with irqs disabled and acked */
pio_writel(pio, IDR, ~0UL);
(void) pio_readl(pio, ISR);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 50fa3aca32c5..7795116a483a 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -19,7 +19,7 @@
#define PIO_OSR 0x0018
#define PIO_IFER 0x0020
#define PIO_IFDR 0x0024
-#define PIO_ISFR 0x0028
+#define PIO_IFSR 0x0028
#define PIO_SODR 0x0030
#define PIO_CODR 0x0034
#define PIO_ODSR 0x0038
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 56ff51bc8c21..fdd9bf43361e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -1373,7 +1373,7 @@ ENTRY(_sys_call_table)
.long _sys_epoll_pwait
.long _sys_utimensat
.long _sys_signalfd
- .long _sys_timerfd
+ .long _sys_ni_syscall
.long _sys_eventfd /* 350 */
.long _sys_pread64
.long _sys_pwrite64
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7f0be4cd5e9a..27b082ac7f11 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -150,6 +150,7 @@ config ETRAX_FLASH_BUSWIDTH
Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
source arch/cris/arch-v10/Kconfig
+source arch/cris/arch-v32/Kconfig
endmenu
@@ -157,8 +158,8 @@ source "net/Kconfig"
# bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces"
-# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
-source arch/cris/arch/drivers/Kconfig
+source arch/cris/arch-v10/drivers/Kconfig
+source arch/cris/arch-v32/drivers/Kconfig
endmenu
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index f1ce6f64401d..1d61faec77cd 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V10
+
# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
config CRIS_LOW_MAP
bool
@@ -451,3 +453,5 @@ config ETRAX_POWERBUTTON_BIT
default "25"
help
Configure where power button is connected.
+
+endif
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index e3c0f2928149..96740ef497d4 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V10
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V10
@@ -806,3 +808,5 @@ config ETRAX_DS1302_TRICKLE_CHARGE
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
4 = 1 diode, 8 = 2 diodes
Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
+
+endif
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ec62c951fa3c..d1361dc119e2 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -1167,7 +1167,7 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
index 4f79d8ed3e1c..d8acaa920e1c 100644
--- a/arch/cris/arch-v32/Kconfig
+++ b/arch/cris/arch-v32/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V32
+
config ETRAX_DRAM_VIRTUAL_BASE
hex
depends on ETRAX_ARCH_V32
@@ -294,3 +296,5 @@ config ETRAX_DEF_GIO_PE_OUT
help
Configures the initial data for the general port E bits. Most
products should use 00000 here.
+
+endif
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 9bccb5e2a960..c329cce2a0c3 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V32
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V32
@@ -610,3 +612,5 @@ config ETRAX_STREAMCOPROC
help
This option enables a driver for the stream co-processor
for cryptographic operations.
+
+endif
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index 66f9500fbc02..e0364654fc44 100644
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ b/arch/cris/arch-v32/drivers/pci/dma.c
@@ -93,7 +93,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
- goto out;
+ goto iounmap_out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
@@ -110,6 +110,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
free1_out:
kfree(dev->dma_mem);
+ iounmap_out:
+ iounmap(mem_base);
out:
return 0;
}
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index bf0468cbe713..96f7d70f4473 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -138,6 +138,15 @@ config UCPAGE_OFFSET_C0000000
endchoice
+config PAGE_OFFSET
+ hex
+ default 0x20000000 if UCPAGE_OFFSET_20000000
+ default 0x40000000 if UCPAGE_OFFSET_40000000
+ default 0x60000000 if UCPAGE_OFFSET_60000000
+ default 0x80000000 if UCPAGE_OFFSET_80000000
+ default 0xA0000000 if UCPAGE_OFFSET_A0000000
+ default 0xC0000000
+
config PROTECT_KERNEL
bool "Protect core kernel against userspace"
depends on !MMU
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index f42b328b1dd0..ef7527b8b0c7 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -13,7 +13,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4;
-__page_offset = 0xc0000000; /* start of area covered by struct pages */
+__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */
__kernel_image_start = __page_offset; /* address at which kernel image resides */
SECTIONS
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index 1530a4111e6d..81757d55a5b5 100644
--- a/arch/frv/mm/mmu-context.c
+++ b/arch/frv/mm/mmu-context.c
@@ -181,7 +181,7 @@ int cxn_pin_by_pid(pid_t pid)
/* get a handle on the mm_struct */
read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
+ tsk = find_task_by_vpid(pid);
if (tsk) {
ret = -EINVAL;
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 7787c3cc52c6..1a2e5c8d03a9 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -140,7 +140,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
/* in the non-PAE case, clear_page_tables() clears user pgd entries */
quicklist_free(0, pgd_dtor, pgd);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 8c0ae4f20f7e..a94445422cc6 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1265,7 +1265,7 @@ sba_fill_pdir(
* the sglist do both.
*/
static SBA_INLINE int
-sba_coalesce_chunks( struct ioc *ioc,
+sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
struct scatterlist *startsg,
int nents)
{
@@ -1275,6 +1275,7 @@ sba_coalesce_chunks( struct ioc *ioc,
struct scatterlist *dma_sg; /* next DMA stream head */
unsigned long dma_offset, dma_len; /* start/len of DMA stream */
int n_mappings = 0;
+ unsigned int max_seg_size = dma_get_max_seg_size(dev);
while (nents > 0) {
unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1314,6 +1315,9 @@ sba_coalesce_chunks( struct ioc *ioc,
> DMA_CHUNK_SIZE)
break;
+ if (dma_len + startsg->length > max_seg_size)
+ break;
+
/*
** Then look for virtually contiguous blocks.
**
@@ -1441,7 +1445,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
** w/o this association, we wouldn't have coherent DMA!
** Access to the virtual address is what forces a two pass algorithm.
*/
- coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+ coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
/*
** Program the I/O Pdir
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index c36f43c94600..f5d3efbfbeda 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1586,7 +1586,7 @@ sys_call_table:
data8 sys_epoll_pwait // 1305
data8 sys_utimensat
data8 sys_signalfd
- data8 sys_timerfd
+ data8 sys_ni_syscall
data8 sys_eventfd
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index ee3c8be12fa0..01d877c6868f 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -17,7 +17,7 @@ static int puts(const char *s)
return 0;
}
-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
#include <asm/m32r.h>
#include <asm/io.h>
@@ -52,7 +52,7 @@ static void putc(char c)
}
*BOOT_SIO0TXB = c;
}
-#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#else /* !(CONFIG_PLAT_M32700UT) */
#if defined(CONFIG_PLAT_MAPPI2)
#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8236e42ef711..ffabd01c45eb 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -577,20 +577,6 @@ config MAC_HID
depends on INPUT_ADBHID
default y
-config MAC_ADBKEYCODES
- bool "Support for ADB raw keycodes"
- depends on INPUT_ADBHID
- help
- This provides support for sending raw ADB keycodes to console
- devices. This is the default up to 2.4.0, but in future this may be
- phased out in favor of generic Linux keycodes. If you say Y here,
- you can dynamically switch via the
- /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
- sysctl and with the "keyboard_sends_linux_keycodes=" kernel
- argument.
-
- If unsure, say Y here.
-
config ADB_KEYBOARD
bool "Support for ADB keyboard (old driver)"
depends on MAC && !INPUT_ADBHID
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 4a1bd44ff162..2cba605cb59d 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -13,16 +13,15 @@
# Copyright (C) 1994 by Hamish Macdonald
#
-# test for cross compiling
-COMPILE_ARCH = $(shell uname -m)
-
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(COMPILE_ARCH),$(ARCH))
- # prefix for cross-compiling binaries
- CROSS_COMPILE = m68k-linux-gnu-
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, \
+ m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+ endif
endif
ifdef CONFIG_SUN3
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 8b415651edee..6a0d7650f980 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -2,6 +2,6 @@
# Makefile for Linux arch/m68k/amiga source directory
#
-obj-y := config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o
+obj-y := config.o amiints.o cia.o chipram.o amisound.o
obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
deleted file mode 100644
index 7fdcf6bf3ada..000000000000
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amipcmcia.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(amiga_model);
-EXPORT_SYMBOL(amiga_chipset);
-EXPORT_SYMBOL(amiga_hw_present);
-EXPORT_SYMBOL(amiga_eclock);
-EXPORT_SYMBOL(amiga_colorclock);
-EXPORT_SYMBOL(amiga_chip_alloc);
-EXPORT_SYMBOL(amiga_chip_free);
-EXPORT_SYMBOL(amiga_chip_avail);
-EXPORT_SYMBOL(amiga_chip_size);
-EXPORT_SYMBOL(amiga_audio_period);
-EXPORT_SYMBOL(amiga_audio_min_period);
-
-#ifdef CONFIG_AMIGA_PCMCIA
- EXPORT_SYMBOL(pcmcia_reset);
- EXPORT_SYMBOL(pcmcia_copy_tuple);
- EXPORT_SYMBOL(pcmcia_program_voltage);
- EXPORT_SYMBOL(pcmcia_access_speed);
- EXPORT_SYMBOL(pcmcia_write_enable);
- EXPORT_SYMBOL(pcmcia_write_disable);
-#endif
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 1f5bfb584297..61e5c54625ae 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -12,6 +12,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/amigahw.h>
@@ -21,7 +22,7 @@ static const signed char sine_data[] = {
0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
0, -39, -75, -103, -121, -127, -121, -103, -75, -39
};
-#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
+#define DATA_SIZE ARRAY_SIZE(sine_data)
#define custom amiga_custom
@@ -31,6 +32,7 @@ static const signed char sine_data[] = {
*/
volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
+EXPORT_SYMBOL(amiga_audio_min_period);
#define MAX_PERIOD (65535)
@@ -40,6 +42,7 @@ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
*/
unsigned short amiga_audio_period = MAX_PERIOD;
+EXPORT_SYMBOL(amiga_audio_period);
static unsigned long clock_constant;
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index fa015d801617..d10726f9038b 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -13,10 +13,13 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/module.h>
+
#include <asm/page.h>
#include <asm/amigahw.h>
unsigned long amiga_chip_size;
+EXPORT_SYMBOL(amiga_chip_size);
static struct resource chipram_res = {
.name = "Chip RAM", .start = CHIP_PHYSADDR
@@ -67,6 +70,7 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
#endif
return (void *)ZTWO_VADDR(res->start);
}
+EXPORT_SYMBOL(amiga_chip_alloc);
/*
@@ -120,6 +124,7 @@ void amiga_chip_free(void *ptr)
}
printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
}
+EXPORT_SYMBOL(amiga_chip_free);
unsigned long amiga_chip_avail(void)
@@ -129,3 +134,5 @@ unsigned long amiga_chip_avail(void)
#endif
return chipavail;
}
+EXPORT_SYMBOL(amiga_chip_avail);
+
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 35748531327d..50f5daab46b7 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/zorro.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -36,13 +37,24 @@
#include <asm/io.h>
unsigned long amiga_model;
+EXPORT_SYMBOL(amiga_model);
+
unsigned long amiga_eclock;
+EXPORT_SYMBOL(amiga_eclock);
+
unsigned long amiga_masterclock;
+
unsigned long amiga_colorclock;
+EXPORT_SYMBOL(amiga_colorclock);
+
unsigned long amiga_chipset;
+EXPORT_SYMBOL(amiga_chipset);
+
unsigned char amiga_vblank;
unsigned char amiga_psfreq;
+
struct amiga_hw_present amiga_hw_present;
+EXPORT_SYMBOL(amiga_hw_present);
static char s_a500[] __initdata = "A500";
static char s_a500p[] __initdata = "A500+";
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index 186662ca1a89..7106f0c3639b 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -15,6 +15,8 @@
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
+#include <linux/module.h>
+
#include <asm/amigayle.h>
#include <asm/amipcmcia.h>
@@ -30,6 +32,7 @@ void pcmcia_reset(void)
while (time_before(jiffies, reset_start_time + 1*HZ/100));
b = gayle_reset;
}
+EXPORT_SYMBOL(pcmcia_reset);
/* copy a tuple, including tuple header. return nb bytes copied */
@@ -61,6 +64,7 @@ int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
return 0;
}
+EXPORT_SYMBOL(pcmcia_copy_tuple);
void pcmcia_program_voltage(int voltage)
{
@@ -84,6 +88,7 @@ void pcmcia_program_voltage(int voltage)
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_program_voltage);
void pcmcia_access_speed(int speed)
{
@@ -101,13 +106,17 @@ void pcmcia_access_speed(int speed)
cfg_byte = (cfg_byte & 0xf3) | s;
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_access_speed);
void pcmcia_write_enable(void)
{
gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
}
+EXPORT_SYMBOL(pcmcia_write_enable);
void pcmcia_write_disable(void)
{
gayle.cardstatus = 0;
}
+EXPORT_SYMBOL(pcmcia_write_disable);
+
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 2cb86191f0aa..2cd905efe63a 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -3,7 +3,7 @@
#
obj-y := config.o time.o debug.o ataints.o stdma.o \
- atasound.o stram.o atari_ksyms.o
+ atasound.o stram.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_HADES) += hades-pci.o
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index b85ca22024c1..b45593a60bdd 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,6 +40,7 @@
#include <linux/kernel_stat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -446,6 +447,7 @@ unsigned long atari_register_vme_int(void)
free_vme_vec_bitmap |= 1 << i;
return VME_SOURCE_BASE + i;
}
+EXPORT_SYMBOL(atari_register_vme_int);
void atari_unregister_vme_int(unsigned long irq)
@@ -455,5 +457,6 @@ void atari_unregister_vme_int(unsigned long irq)
free_vme_vec_bitmap &= ~(1 << irq);
}
}
+EXPORT_SYMBOL(atari_unregister_vme_int);
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
deleted file mode 100644
index a04757151538..000000000000
--- a/arch/m68k/atari/atari_ksyms.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/module.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-extern void atari_microwire_cmd( int cmd );
-extern int atari_MFP_init_done;
-extern int atari_SCC_init_done;
-extern int atari_SCC_reset_done;
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_mch_type);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(atari_switches);
-EXPORT_SYMBOL(atari_dont_touch_floppy_select);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-EXPORT_SYMBOL(atari_stram_alloc);
-EXPORT_SYMBOL(atari_stram_free);
-
-EXPORT_SYMBOL(atari_MFP_init_done);
-EXPORT_SYMBOL(atari_SCC_init_done);
-EXPORT_SYMBOL(atari_SCC_reset_done);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index ee04250eb56b..d266fe89c125 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -22,6 +22,7 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/system.h>
@@ -43,6 +44,7 @@ void atari_microwire_cmd (int cmd)
while( tt_microwire.mask != 0x7ff)
;
}
+EXPORT_SYMBOL(atari_microwire_cmd);
/* PSG base frequency */
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index e40e5dcaa347..5945e1505558 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -31,6 +31,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/vt_kern.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -43,10 +44,20 @@
#include <asm/io.h>
u_long atari_mch_cookie;
+EXPORT_SYMBOL(atari_mch_cookie);
+
u_long atari_mch_type;
+EXPORT_SYMBOL(atari_mch_type);
+
struct atari_hw_present atari_hw_present;
+EXPORT_SYMBOL(atari_hw_present);
+
u_long atari_switches;
+EXPORT_SYMBOL(atari_switches);
+
int atari_dont_touch_floppy_select;
+EXPORT_SYMBOL(atari_dont_touch_floppy_select);
+
int atari_rtc_year_offset;
/* local function prototypes */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index fbeed8c8ecbc..043ddbc61c7b 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -15,17 +15,23 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
/* Flag that Modem1 port is already initialized and used */
int atari_MFP_init_done;
+EXPORT_SYMBOL(atari_MFP_init_done);
+
/* Flag that Modem1 port is already initialized and used */
int atari_SCC_init_done;
+EXPORT_SYMBOL(atari_SCC_init_done);
+
/* Can be set somewhere, if a SCC master reset has already be done and should
* not be repeated; used by kgdb */
int atari_SCC_reset_done;
+EXPORT_SYMBOL(atari_SCC_reset_done);
static struct console atari_console_driver = {
.name = "debug",
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
index bee2b1443e36..2bbabc008708 100644
--- a/arch/m68k/atari/hades-pci.c
+++ b/arch/m68k/atari/hades-pci.c
@@ -376,8 +376,8 @@ struct pci_bus_info * __init init_hades_pci(void)
*/
bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
- if (!bus)
- return NULL;
+ if (unlikely(!bus))
+ goto iounmap_base_virt;
/*
* Claim resources. The m68k has no separate I/O space, both
@@ -385,43 +385,25 @@ struct pci_bus_info * __init init_hades_pci(void)
* the I/O resources are requested in memory space as well.
*/
- if (request_resource(&iomem_resource, &config_space) != 0)
- {
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
+ goto free_bus;
- if (request_resource(&iomem_resource, &io_space) != 0)
- {
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
+ goto release_config_space;
bus->mem_space.start = HADES_MEM_BASE;
bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
bus->mem_space.name = pci_mem_name;
#if 1
- if (request_resource(&iomem_resource, &bus->mem_space) != 0)
- {
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
+ goto release_io_space;
#endif
bus->io_space.start = pci_io_base_virt;
bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
bus->io_space.name = pci_io_name;
#if 1
- if (request_resource(&ioport_resource, &bus->io_space) != 0)
- {
- release_resource(&bus->mem_space);
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
+ goto release_bus_mem_space;
#endif
/*
* Set hardware dependent functions.
@@ -438,5 +420,21 @@ struct pci_bus_info * __init init_hades_pci(void)
tt_mfp.active_edge &= ~0x27;
return bus;
+
+release_bus_mem_space:
+ release_resource(&bus->mem_space);
+release_io_space:
+ release_resource(&io_space);
+release_config_space:
+ release_resource(&config_space);
+free_bus:
+ kfree(bus);
+iounmap_base_virt:
+ iounmap((void *)pci_io_base_virt);
+
+ for (i = 0; i < N_SLOTS; i++)
+ iounmap((void *)pci_conf_base_virt[i]);
+
+ return NULL;
}
#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ab3fd5202b24..d1bd029a34ac 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -91,6 +92,7 @@ void stdma_lock(irq_handler_t handler, void *data)
stdma_isr_data = data;
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_lock);
/*
@@ -117,6 +119,7 @@ void stdma_release(void)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_release);
/*
@@ -134,6 +137,7 @@ int stdma_others_waiting(void)
{
return waitqueue_active(&stdma_wait);
}
+EXPORT_SYMBOL(stdma_others_waiting);
/*
@@ -155,6 +159,7 @@ int stdma_islocked(void)
{
return stdma_locked;
}
+EXPORT_SYMBOL(stdma_islocked);
/*
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index bf4588cbe371..8dda6515887a 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
#include <linux/bootmem.h>
#include <linux/mount.h>
#include <linux/blkdev.h>
+#include <linux/module.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -208,6 +209,7 @@ void *atari_stram_alloc(long size, const char *owner)
}
return( addr );
}
+EXPORT_SYMBOL(atari_stram_alloc);
void atari_stram_free( void *addr )
@@ -237,6 +239,7 @@ void atari_stram_free( void *addr )
printk( KERN_ERR "atari_stram_free: cannot free block at %p "
"(called from %p)\n", addr, __builtin_return_address(0) );
}
+EXPORT_SYMBOL(atari_stram_free);
/* ------------------------------------------------------------------------ */
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 15b80abfe94a..ff9dffa5b860 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -678,7 +678,6 @@ CONFIG_LOGO_MAC_CLUT224=y
#
CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
-CONFIG_MAC_ADBKEYCODES=y
CONFIG_SERIAL_CONSOLE=y
#
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
index 288b9c67c9bf..96d4244c82fd 100644
--- a/arch/m68k/hp300/Makefile
+++ b/arch/m68k/hp300/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/hp300 source directory
#
-obj-y := ksyms.o config.o time.o reboot.o
+obj-y := config.o time.o reboot.o
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
deleted file mode 100644
index 8202830763d1..000000000000
--- a/arch/m68k/hp300/ksyms.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * linux/arch/m68k/hp300/ksyms.c
- *
- * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
- *
- * This file contains the HP300-specific kernel symbols. None yet. :-)
- */
-
-#include <linux/module.h>
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 918f5dbeaef6..6dfa3b3c0e2a 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -742,7 +742,7 @@ sys_call_table:
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 995a09d912f5..1d265ba365ad 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -3,4 +3,4 @@
#
obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
- baboon.o macboing.o debug.o misc.o mac_ksyms.o
+ baboon.o macboing.o debug.o misc.o
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 01b468b9392e..735a49b4b936 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -58,8 +58,6 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
extern struct mem_info m68k_ramdisk;
-extern char m68k_command_line[CL_SIZE];
-
void *mac_env; /* Loaded by the boot asm */
/* The phys. video addr. - might be bogus on some machines */
diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c
deleted file mode 100644
index 6e37ceb0f3b5..000000000000
--- a/arch/m68k/mac/mac_ksyms.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-
-/* Says whether we're using A/UX interrupts or not */
-extern int via_alt_mapping;
-
-EXPORT_SYMBOL(via_alt_mapping);
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 8df270e950fa..fa485df4160e 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -41,7 +42,9 @@ volatile __u8 *via1, *via2;
/* See note in mac_via.h about how this is possibly not useful */
volatile long *via_memory_bogon=(long *)&via_memory_bogon;
#endif
-int rbv_present, via_alt_mapping;
+int rbv_present;
+int via_alt_mapping;
+EXPORT_SYMBOL(via_alt_mapping);
__u8 rbv_clear;
/*
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 950e82f21640..edb3f6e6ee6a 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/mvme16x source directory
#
-obj-y := config.o rtc.o mvme16x_ksyms.o
+obj-y := config.o rtc.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index daa785161401..24cbc3030454 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -25,6 +25,7 @@
#include <linux/genhd.h>
#include <linux/rtc.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -58,6 +59,7 @@ static irq_handler_t tick_handler;
unsigned short mvme16x_config;
+EXPORT_SYMBOL(mvme16x_config);
int mvme16x_parse_bootinfo(const struct bi_record *bi)
diff --git a/arch/m68k/mvme16x/mvme16x_ksyms.c b/arch/m68k/mvme16x/mvme16x_ksyms.c
deleted file mode 100644
index 4a8a3634bb47..000000000000
--- a/arch/m68k/mvme16x/mvme16x_ksyms.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/mvme16xhw.h>
-
-EXPORT_SYMBOL(mvme16x_config);
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
index 9ff47bd09aee..ed6d9a83bfdb 100644
--- a/arch/m68knommu/Kconfig.debug
+++ b/arch/m68knommu/Kconfig.debug
@@ -21,13 +21,6 @@ config BOOTPARAM_STRING
default 'console=ttyS0,19200'
depends on BOOTPARAM
-config DUMPTOFLASH
- bool "Panic/Dump to FLASH"
- depends on COLDFIRE
- help
- Dump any panic of trap output into a flash memory segment
- for later analysis.
-
config NO_KERNEL_MSG
bool "Suppress Kernel BUG Messages"
help
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 5a0ecaaee3b0..648113075f97 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -597,7 +597,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
# CONFIG_BOOTPARAM is not set
-# CONFIG_DUMPTOFLASH is not set
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f795062aba1e..53fad1490282 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -24,14 +24,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(ip_fast_csum);
@@ -46,9 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
it's OK to leave it out of version control. */
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 332345d7675d..81507c53d4a9 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -64,9 +64,6 @@ void (*mach_power_off)(void);
#ifdef CONFIG_M68VZ328
#define CPU "MC68VZ328"
#endif
-#ifdef CONFIG_M68332
- #define CPU "MC68332"
-#endif
#ifdef CONFIG_M68360
#define CPU "MC68360"
#endif
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 9620093514bc..1b02b8820068 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -336,7 +336,7 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 82480a1717d8..f798139e888e 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -660,7 +660,7 @@ einval: li v0, -EINVAL
sys sys_ioprio_get 2 /* 4315 */
sys sys_utimensat 4
sys sys_signalfd 3
- sys sys_timerfd 4
+ sys sys_ni_syscall 0
sys sys_eventfd 1
sys sys_fallocate 6 /* 4320 */
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index c2c10876da2e..a626be6baea3 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -475,7 +475,7 @@ sys_call_table:
PTR sys_ioprio_get
PTR sys_utimensat /* 5275 */
PTR sys_signalfd
- PTR sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 01993ec3368b..9d5bcaf1b389 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -401,7 +401,7 @@ EXPORT(sysn32_call_table)
PTR sys_ioprio_get
PTR compat_sys_utimensat
PTR compat_sys_signalfd /* 5280 */
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index dd68afce7da5..fd2019c1ec2d 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -523,7 +523,7 @@ sys_call_table:
PTR sys_ioprio_get /* 4315 */
PTR compat_sys_utimensat
PTR compat_sys_signalfd
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys32_fallocate /* 4320 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b94d4502a477..cf030b004415 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -256,6 +256,9 @@ config IOMMU_VMERGE
Most drivers don't have this problem; it is safe to say Y here.
+config IOMMU_HELPER
+ def_bool PPC64
+
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 84239076a5b8..3a317cb0636a 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -31,8 +31,8 @@ static inline unsigned long device_to_mask(struct device *dev)
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
- device_to_mask(dev), flag,
+ return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
+ dma_handle, device_to_mask(dev), flag,
dev->archdata.numa_node);
}
@@ -52,7 +52,7 @@ static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(dev->archdata.dma_data, vaddr, size,
+ return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
device_to_mask(dev), direction);
}
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
+ return iommu_map_sg(dev, sglist, nelems,
device_to_mask(dev), direction);
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a3c406aca664..8f1f4e539c4b 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/dma-mapping.h>
#include <linux/bitops.h>
+#include <linux/iommu-helper.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
@@ -81,17 +82,19 @@ static int __init setup_iommu(char *str)
__setup("protect4gb=", setup_protect4gb);
__setup("iommu=", setup_iommu);
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
unsigned long npages,
unsigned long *handle,
unsigned long mask,
unsigned int align_order)
{
- unsigned long n, end, i, start;
+ unsigned long n, end, start;
unsigned long limit;
int largealloc = npages > 15;
int pass = 0;
unsigned long align_mask;
+ unsigned long boundary_size;
align_mask = 0xffffffffffffffffl >> (64 - align_order);
@@ -136,14 +139,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
start &= mask;
}
- n = find_next_zero_bit(tbl->it_map, limit, start);
-
- /* Align allocation */
- n = (n + align_mask) & ~align_mask;
-
- end = n + npages;
+ if (dev)
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ 1 << IOMMU_PAGE_SHIFT);
+ else
+ boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
+ /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
- if (unlikely(end >= limit)) {
+ n = iommu_area_alloc(tbl->it_map, limit, start, npages,
+ tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
+ align_mask);
+ if (n == -1) {
if (likely(pass < 2)) {
/* First failure, just rescan the half of the table.
* Second failure, rescan the other half of the table.
@@ -158,14 +164,7 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- for (i = n; i < end; i++)
- if (test_bit(i, tbl->it_map)) {
- start = i+1;
- goto again;
- }
-
- for (i = n; i < end; i++)
- __set_bit(i, tbl->it_map);
+ end = n + npages;
/* Bump the hint to a new block for small allocs. */
if (largealloc) {
@@ -184,16 +183,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return n;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
- unsigned int npages, enum dma_data_direction direction,
- unsigned long mask, unsigned int align_order)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *page, unsigned int npages,
+ enum dma_data_direction direction,
+ unsigned long mask, unsigned int align_order)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
spin_lock_irqsave(&(tbl->it_lock), flags);
- entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
+ entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -224,7 +224,6 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry, free_entry;
- unsigned long i;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
free_entry = entry - tbl->it_offset;
@@ -246,9 +245,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
}
ppc_md.tce_free(tbl, entry, npages);
-
- for (i = 0; i < npages; i++)
- __clear_bit(free_entry+i, tbl->it_map);
+ iommu_area_free(tbl->it_map, free_entry, npages);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -270,16 +267,18 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
-int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, unsigned long mask,
enum dma_data_direction direction)
{
+ struct iommu_table *tbl = dev->archdata.dma_data;
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
int outcount, incount, i;
unsigned int align;
unsigned long handle;
+ unsigned int max_seg_size;
BUG_ON(direction == DMA_NONE);
@@ -298,6 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
spin_lock_irqsave(&(tbl->it_lock), flags);
+ max_seg_size = dma_get_max_seg_size(dev);
for_each_sg(sglist, s, nelems, i) {
unsigned long vaddr, npages, entry, slen;
@@ -314,7 +314,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- entry = iommu_range_alloc(tbl, npages, &handle,
+ entry = iommu_range_alloc(dev, tbl, npages, &handle,
mask >> IOMMU_PAGE_SHIFT, align);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -344,7 +344,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
/* We cannot merge if:
* - allocated dma_addr isn't contiguous to previous allocation
*/
- if (novmerge || (dma_addr != dma_next)) {
+ if (novmerge || (dma_addr != dma_next) ||
+ (outs->dma_length + s->length > max_seg_size)) {
/* Can't merge: create a new segment */
segstart = s;
outcount++;
@@ -452,9 +453,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
{
unsigned long sz;
- unsigned long start_index, end_index;
- unsigned long entries_per_4g;
- unsigned long index;
static int welcomed = 0;
struct page *page;
@@ -476,6 +474,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
#ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
+ unsigned long index;
unsigned long tceval;
unsigned long tcecount = 0;
@@ -506,23 +505,6 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
#endif
- /*
- * DMA cannot cross 4 GB boundary. Mark last entry of each 4
- * GB chunk as reserved.
- */
- if (protect4gb) {
- entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
-
- /* Mark the last bit before a 4GB boundary as used */
- start_index = tbl->it_offset | (entries_per_4g - 1);
- start_index -= tbl->it_offset;
-
- end_index = tbl->it_size;
-
- for (index = start_index; index < end_index - 1; index += entries_per_4g)
- __set_bit(index, tbl->it_map);
- }
-
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");
@@ -570,9 +552,9 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
-dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, unsigned long mask,
- enum dma_data_direction direction)
+dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, size_t size, unsigned long mask,
+ enum dma_data_direction direction)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -589,7 +571,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
((unsigned long)vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
mask >> IOMMU_PAGE_SHIFT, align);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
@@ -621,8 +603,9 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
+void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
+ size_t size, dma_addr_t *dma_handle,
+ unsigned long mask, gfp_t flag, int node)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -656,7 +639,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
/* Set up tces to cover the allocated range */
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
- mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
+ mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
mask >> IOMMU_PAGE_SHIFT, io_order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 64488723162a..f80f90c4d58b 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -86,7 +86,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -123,7 +123,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -131,7 +131,7 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, struct page *ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 6a0c6f6675cd..11fa3c772ed5 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -199,7 +199,7 @@ static struct iommu_table vio_iommu_table;
void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
DMA_32BIT_MASK, flag, -1);
}
EXPORT_SYMBOL_GPL(iseries_hv_alloc);
@@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(iseries_hv_free);
dma_addr_t iseries_hv_map(void *vaddr, size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(&vio_iommu_table, vaddr, size,
+ return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
DMA_32BIT_MASK, direction);
}
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index fadacfd18806..409fcaa4994a 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -74,7 +74,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -111,7 +111,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -119,7 +119,7 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, struct page *ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 82cbffd03654..92a4f7b4323a 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT
config STACKTRACE_SUPPORT
def_bool y
+config HAVE_LATENCYTOP_SUPPORT
+ def_bool y
+
config RWSEM_GENERIC_SPINLOCK
bool
@@ -47,6 +50,11 @@ config NO_IOMEM
config NO_DMA
def_bool y
+config GENERIC_LOCKBREAK
+ bool
+ default y
+ depends on SMP && PREEMPT
+
mainmenu "Linux Kernel Configuration"
config S390
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 2283933a9a93..4599fa06bd82 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -6,4 +6,12 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug"
+config DEBUG_PAGEALLOC
+ bool "Debug page memory allocations"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a slowdown, but helps to find certain types of
+ memory corruptions.
+
endmenu
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 6ee1bedbd1bf..062c3d4c0394 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1698,14 +1698,6 @@ compat_sys_signalfd_wrapper:
llgfr %r4,%r4 # compat_size_t
jg compat_sys_signalfd
- .globl compat_sys_timerfd_wrapper
-compat_sys_timerfd_wrapper:
- lgfr %r2,%r2 # int
- lgfr %r3,%r3 # int
- lgfr %r4,%r4 # int
- llgtr %r5,%r5 # struct compat_itimerspec *
- jg compat_sys_timerfd
-
.globl sys_eventfd_wrapper
sys_eventfd_wrapper:
llgfr %r2,%r2 # unsigned int
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1a6dac8df6fb..6766e37fe8ea 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -830,9 +831,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -845,9 +844,7 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index a3e47b893f07..efde6e178f6c 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -801,9 +802,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -814,9 +813,7 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index db28cca81fef..60acdc266db1 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -439,7 +439,7 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}
-static int ipl_init(void)
+static int __init ipl_init(void)
{
int rc;
@@ -471,8 +471,11 @@ out:
return 0;
}
-static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
- ipl_init};
+static struct shutdown_action __refdata ipl_action = {
+ .name = SHUTDOWN_ACTION_IPL_STR,
+ .fn = ipl_run,
+ .init = ipl_init,
+};
/*
* reipl shutdown action: Reboot Linux on shutdown.
@@ -792,7 +795,7 @@ static int __init reipl_fcp_init(void)
return 0;
}
-static int reipl_init(void)
+static int __init reipl_init(void)
{
int rc;
@@ -819,8 +822,11 @@ static int reipl_init(void)
return 0;
}
-static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
- reipl_run, reipl_init};
+static struct shutdown_action __refdata reipl_action = {
+ .name = SHUTDOWN_ACTION_REIPL_STR,
+ .fn = reipl_run,
+ .init = reipl_init,
+};
/*
* dump shutdown action: Dump Linux on shutdown.
@@ -998,7 +1004,7 @@ static int __init dump_fcp_init(void)
return 0;
}
-static int dump_init(void)
+static int __init dump_init(void)
{
int rc;
@@ -1020,8 +1026,11 @@ static int dump_init(void)
return 0;
}
-static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
- dump_run, dump_init};
+static struct shutdown_action __refdata dump_action = {
+ .name = SHUTDOWN_ACTION_DUMP_STR,
+ .fn = dump_run,
+ .init = dump_init,
+};
/*
* vmcmd shutdown action: Trigger vm command on shutdown.
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 766c783bd7a7..29ae165d1749 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -77,7 +77,7 @@ unsigned long machine_flags = 0;
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
static unsigned long __initdata memory_end;
@@ -145,7 +145,7 @@ __setup("condev=", condev_setup);
static int __init conmode_setup(char *str)
{
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
SET_CONSOLE_SCLP;
#endif
@@ -183,7 +183,7 @@ static void __init conmode_default(void)
*/
cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
return;
@@ -193,7 +193,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#elif defined(CONFIG_TN3215_CONSOLE)
SET_CONSOLE_3215;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
} else if (strncmp(ptr + 8, "3215", 4) == 0) {
@@ -201,7 +201,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3215;
#elif defined(CONFIG_TN3270_CONSOLE)
SET_CONSOLE_3270;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -212,7 +212,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#endif
} else {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -528,7 +528,7 @@ static void __init setup_memory_end(void)
memory_size = 0;
memory_end &= PAGE_MASK;
- max_mem = memory_end ? min(VMALLOC_START, memory_end) : VMALLOC_START;
+ max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS;
memory_end = min(max_mem, memory_end);
/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index aa37fa154512..85060659fb12 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -225,12 +225,11 @@ EXPORT_SYMBOL(smp_call_function_single);
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
-int
-smp_call_function_mask(cpumask_t mask,
- void (*func)(void *), void *info,
- int wait)
+int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
+ int wait)
{
preempt_disable();
+ cpu_clear(smp_processor_id(), mask);
__smp_call_function_map(func, info, 0, wait, mask);
preempt_enable();
return 0;
@@ -1008,7 +1007,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
.notifier_call = smp_cpu_notify,
};
-static int smp_add_present_cpu(int cpu)
+static int __devinit smp_add_present_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
@@ -1036,8 +1035,8 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t rescan_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref rescan_store(struct sys_device *dev,
+ const char *buf, size_t count)
{
cpumask_t newcpus;
int cpu;
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index da6924729964..85e46a5d0e08 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -14,7 +14,8 @@
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
unsigned long low,
- unsigned long high)
+ unsigned long high,
+ int savesched)
{
struct stack_frame *sf;
struct pt_regs *regs;
@@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace,
return sp;
regs = (struct pt_regs *)sp;
addr = regs->psw.addr & PSW_ADDR_INSN;
- if (!trace->skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- trace->skip--;
+ if (savesched || !in_sched_functions(addr)) {
+ if (!trace->skip)
+ trace->entries[trace->nr_entries++] = addr;
+ else
+ trace->skip--;
+ }
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace)
orig_sp = sp & PSW_ADDR_INSN;
new_sp = save_context_stack(trace, orig_sp,
S390_lowcore.panic_stack - PAGE_SIZE,
- S390_lowcore.panic_stack);
+ S390_lowcore.panic_stack, 1);
if (new_sp != orig_sp)
return;
new_sp = save_context_stack(trace, new_sp,
S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
+ S390_lowcore.async_stack, 1);
if (new_sp != orig_sp)
return;
save_context_stack(trace, new_sp,
S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+ S390_lowcore.thread_info + THREAD_SIZE, 1);
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+ unsigned long sp, low, high;
+
+ sp = tsk->thread.ksp & PSW_ADDR_INSN;
+ low = (unsigned long) task_stack_page(tsk);
+ high = (unsigned long) task_pt_regs(tsk);
+ save_context_stack(trace, sp, low, high, 0);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 9e26ed9fe4e7..25eac7802fc4 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -325,5 +325,5 @@ SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
-SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
+NI_SYSCALL /* 317 old sys_timer_fd */
SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 52b8342c6bf2..1a2fdb6991df 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -271,7 +271,10 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- printk("SMP");
+ printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 7d43c3cd3ef3..b4607155e8d0 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -35,7 +35,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x0700
+ } :text = 0x0700
_etext = .; /* End of text section */
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b234bb4a6da7..983ec6ec0e7c 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -167,6 +167,33 @@ void __init mem_init(void)
PFN_ALIGN((unsigned long)&_eshared) - 1);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long address;
+ int i;
+
+ for (i = 0; i < numpages; i++) {
+ address = page_to_phys(page + i);
+ pgd = pgd_offset_k(address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ pte = pte_offset_kernel(pmd, address);
+ if (!enable) {
+ ptep_invalidate(address, pte);
+ continue;
+ }
+ *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+ /* Flush cpu write queue. */
+ mb();
+ }
+}
+#endif
+
void free_initmem(void)
{
unsigned long addr;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 79d13a166a3d..7c1287ccf788 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -62,7 +62,7 @@ void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
}
}
-static void __init_refok *vmem_alloc_pages(unsigned int order)
+static void __ref *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
@@ -250,7 +250,7 @@ static int insert_memory_segment(struct memory_segment *seg)
{
struct memory_segment *tmp;
- if (seg->start + seg->size >= VMALLOC_START ||
+ if (seg->start + seg->size >= VMEM_MAX_PHYS ||
seg->start + seg->size < seg->start)
return -ERANGE;
@@ -360,7 +360,6 @@ void __init vmem_map_init(void)
{
int i;
- BUILD_BUG_ON((unsigned long)VMEM_MAP + VMEM_MAP_SIZE > VMEM_MAP_MAX);
NODE_DATA(0)->node_mem_map = VMEM_MAP;
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 55722840859c..ee010f4532a0 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -79,7 +79,7 @@ sys_call_table:
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 070a4846c0cb..4b9115a4d92e 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -580,7 +580,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
/* Step 1: Prepare scatter list. */
- npages = prepare_sg(sglist, nelems);
+ npages = prepare_sg(dev, sglist, nelems);
/* Step 2: Allocate a cluster and context, if necessary. */
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index efd5dff85f60..72a4acfe8c7b 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -4,6 +4,7 @@
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
+#include <linux/dma-mapping.h>
#include "iommu_common.h"
/* You are _strongly_ advised to enable the following debugging code
@@ -201,21 +202,24 @@ void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int np
}
#endif
-unsigned long prepare_sg(struct scatterlist *sg, int nents)
+unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
{
struct scatterlist *dma_sg = sg;
unsigned long prev;
u32 dent_addr, dent_len;
+ unsigned int max_seg_size;
prev = (unsigned long) sg_virt(sg);
prev += (unsigned long) (dent_len = sg->length);
dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
+ max_seg_size = dma_get_max_seg_size(dev);
while (--nents) {
unsigned long addr;
sg = sg_next(sg);
addr = (unsigned long) sg_virt(sg);
- if (! VCONTIG(prev, addr)) {
+ if (! VCONTIG(prev, addr) ||
+ dent_len + sg->length > max_seg_size) {
dma_sg->dma_address = dent_addr;
dma_sg->dma_length = dent_len;
dma_sg = sg_next(dma_sg);
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 75b5a5814522..a90d046e8024 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/device.h>
#include <asm/iommu.h>
#include <asm/scatterlist.h>
@@ -46,4 +47,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int
#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \
(((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
-extern unsigned long prepare_sg(struct scatterlist *sg, int nents);
+extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 1aa8e044b105..5ea2eab1ccda 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -490,7 +490,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
goto bad;
/* Step 1: Prepare scatter list. */
- npages = prepare_sg(sglist, nelems);
+ npages = prepare_sg(dev, sglist, nelems);
/* Step 2: Allocate a cluster and context, if necessary. */
spin_lock_irqsave(&iommu->lock, flags);
@@ -625,8 +625,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
/* XXX register error interrupt handlers XXX */
}
-static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
- struct iommu *iommu)
+static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
+ struct iommu *iommu)
{
struct iommu_arena *arena = &iommu->arena;
unsigned long i, cnt = 0;
@@ -653,7 +653,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
return cnt;
}
-static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
+static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct iommu *iommu = pbm->iommu;
struct property *prop;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 06d10907d8ce..b8058906e727 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -80,7 +80,7 @@ sys_call_table32:
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate
+/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
#endif /* CONFIG_COMPAT */
@@ -152,7 +152,7 @@ sys_call_table:
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 55945db1313c..99e51d059a02 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD
bool
default y
+config HZ
+ int
+ default 100
+
menu "UML-specific options"
config STATIC_LINK
@@ -95,23 +99,6 @@ config LD_SCRIPT_DYN
default y
depends on !LD_SCRIPT_STATIC
-config NET
- bool "Networking support"
- help
- Unless you really know what you are doing, you should say Y here.
- The reason is that some programs need kernel networking support even
- when running on a stand-alone machine that isn't connected to any
- other computer. If you are upgrading from an older kernel, you
- should consider updating your networking tools too because changes
- in the kernel and the tools often go hand in hand. The tools are
- contained in the package net-tools, the location and version number
- of which are given in <file:Documentation/Changes>.
-
- For a general introduction to Linux networking, it is highly
- recommended to read the NET-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-
source "fs/Kconfig.binfmt"
config HOSTFS
@@ -145,7 +132,7 @@ config HPPFS
by removing or changing anything in /proc which gives away the
identity of a UML.
- See <http://user-mode-linux.sf.net/hppfs.html> for more information.
+ See <http://user-mode-linux.sf.net/old/hppfs.html> for more information.
You only need this if you are setting up a UML honeypot. Otherwise,
it is safe to say 'N' here.
@@ -189,8 +176,7 @@ config MAGIC_SYSRQ
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
- #SMP_BROKEN is for x86_64.
- depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
+ depends on BROKEN
help
This option enables UML SMP support.
It is NOT related to having a real SMP box. Not directly, at least.
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 9a78d354f0b4..3a4b396d7979 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -18,7 +18,7 @@ config SSL
lines on the UML that are usually made to show up on the host as
ttys or ptys.
- See <http://user-mode-linux.sourceforge.net/input.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/input.html> for more
information and command line examples of how to use this facility.
Unless you have a specific reason for disabling this, say Y.
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 1f6462ffd3e8..8fce5e536b0f 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -4,12 +4,12 @@ source "lib/Kconfig.debug"
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO
+ depends on DEBUG_INFO && FRAME_POINTER
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gprof,
@@ -22,7 +22,7 @@ config GCOV
This option allows developers to retrieve coverage data from a UML
session.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gcov,
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 66e50026ade9..9e9a4aaa703d 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -14,7 +14,7 @@ config UML_NET
For more information, including explanations of the networking and
sample configurations, see
- <http://user-mode-linux.sourceforge.net/networking.html>.
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
If you'd like to be able to enable networking in the User-Mode
linux environment, say Y; otherwise say N. Note that you must
@@ -38,7 +38,7 @@ config UML_NET_ETHERTAP
CONFIG_NETLINK_DEV configured as Y or M.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Ethertap
networking.
@@ -72,7 +72,7 @@ config UML_NET_SLIP
To use this, your host must support slip devices.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html>. That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
has examples of the UML command line to use to enable slip
networking, and details of a few quirks with it.
@@ -96,7 +96,7 @@ config UML_NET_DAEMON
networking daemon on the host.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Daemon
networking.
@@ -144,7 +144,7 @@ config UML_NET_MCAST
To use this, your host kernel(s) must support IP Multicasting.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Multicast
networking, and notes about the security of this approach.
@@ -165,7 +165,7 @@ config UML_NET_PCAP
installed in order to build the pcap transport into UML.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable this option.
If you intend to use UML as a network monitor for the host, say
diff --git a/arch/um/Makefile b/arch/um/Makefile
index ba6813a4aa37..cb4af9bf2074 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -49,7 +49,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
#
# These apply to USER_CFLAGS to.
-KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Din6addr_loopback=kernel_in6addr_loopback \
-Din6addr_any=kernel_in6addr_any
@@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
- -D_FILE_OFFSET_BITS=64
+ $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -130,7 +130,9 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
# The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
-CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
+LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
+
+CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
define cmd_vmlinux__
$(CC) $(CFLAGS_vmlinux) -o $@ \
-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
@@ -158,7 +160,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
else
- $(Q)cd $(TOPDIR)/$(dir $@) ; \
+ $(Q)cd $(srctree)/$(dir $@) ; \
ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
endif
@@ -168,7 +170,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
else
- $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
+ $(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
endif
$(objtree)/$(ARCH_DIR)/include:
diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
deleted file mode 100644
index 03f7b10cfd0b..000000000000
--- a/arch/um/Makefile-tt
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
-#
-
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f609edede065..86db2862f222 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -77,7 +77,7 @@ CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
-# CONFIG_HOSTFS is not set
+CONFIG_HOSTFS=y
# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
@@ -188,7 +188,7 @@ CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pts"
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LEGACY_PTY_COUNT=32
# CONFIG_WATCHDOG is not set
CONFIG_UML_SOUND=m
CONFIG_SOUND=m
@@ -508,7 +508,7 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
-CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SLAB_LEAK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83bf15a3dda8..2c898c4d6b6a 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,6 +8,7 @@
#include "chan_kern.h"
#include "irq_kern.h"
#include "irq_user.h"
+#include "kern_util.h"
#include "os.h"
#define LINE_BUFSIZE 4096
@@ -48,7 +49,7 @@ static int write_room(struct line *line)
n = line->head - line->tail;
if (n <= 0)
- n = LINE_BUFSIZE + n; /* The other case */
+ n += LINE_BUFSIZE; /* The other case */
return n - 1;
}
@@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty)
unsigned long flags;
int room;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
room = write_room(line);
spin_unlock_irqrestore(&line->lock, flags);
- /*XXX: Warning to remove */
- if (0 == room)
- printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
- __FUNCTION__,tty->name);
return room;
}
@@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty)
int ret;
spin_lock_irqsave(&line->lock, flags);
-
- /*write_room subtracts 1 for the needed NULL, so we readd it.*/
+ /* write_room subtracts 1 for the needed NULL, so we readd it.*/
ret = LINE_BUFSIZE - (write_room(line) + 1);
spin_unlock_irqrestore(&line->lock, flags);
@@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty)
unsigned long flags;
int err;
- /*XXX: copied from line_write, verify if it is correct!*/
- if (tty->stopped)
- return;
-
spin_lock_irqsave(&line->lock, flags);
err = flush_buffer(line);
spin_unlock_irqrestore(&line->lock, flags);
@@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
unsigned long flags;
int n, ret = 0;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
if (line->head != line->tail)
ret = buffer_data(line, buf, len);
@@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data)
tty = winch->tty;
if (tty != NULL) {
line = tty->driver_data;
- chan_window_size(&line->chan_list, &tty->winsize.ws_row,
- &tty->winsize.ws_col);
- kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ if (line != NULL) {
+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+ &tty->winsize.ws_col);
+ kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ }
}
out:
if (winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 0f3c7d14a6e3..ebb265c07e4d 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,23 +1,25 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/console.h"
-#include "linux/ctype.h"
-#include "linux/interrupt.h"
-#include "linux/list.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/notifier.h"
-#include "linux/reboot.h"
-#include "linux/proc_fs.h"
-#include "linux/slab.h"
-#include "linux/syscalls.h"
-#include "linux/utsname.h"
-#include "linux/workqueue.h"
-#include "asm/uaccess.h"
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
#include "init.h"
#include "irq_kern.h"
#include "irq_user.h"
@@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req)
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
os_set_fd_block(req->originating_fd, 1);
mconsole_reply(req, "stopped", 0, 0);
- while (mconsole_get_request(req->originating_fd, req)) {
+ for (;;) {
+ if (!mconsole_get_request(req->originating_fd, req))
+ continue;
if (req->cmd->handler == mconsole_go)
break;
if (req->cmd->handler == mconsole_stop) {
@@ -358,7 +362,7 @@ struct unplugged_pages {
void *pages[UNPLUGGED_PER_PAGE];
};
-static DECLARE_MUTEX(plug_mem_mutex);
+static DEFINE_MUTEX(plug_mem_mutex);
static unsigned long long unplugged_pages_count = 0;
static LIST_HEAD(unplugged_pages);
static int unplug_index = UNPLUGGED_PER_PAGE;
@@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out)
diff /= PAGE_SIZE;
- down(&plug_mem_mutex);
+ mutex_lock(&plug_mem_mutex);
for (i = 0; i < diff; i++) {
struct unplugged_pages *unplugged;
void *addr;
@@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out)
err = 0;
out_unlock:
- up(&plug_mem_mutex);
+ mutex_unlock(&plug_mem_mutex);
out:
return err;
}
@@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req)
{
char *ptr = req->request.data;
int pid_requested= -1;
- struct task_struct *from = NULL;
struct task_struct *to = NULL;
/*
@@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req)
return;
}
- from = current;
-
- to = find_task_by_pid(pid_requested);
+ to = find_task_by_pid_ns(pid_requested, &init_pid_ns);
if ((to == NULL) || (pid_requested == 0)) {
mconsole_reply(req, "Couldn't find that pid", 1, 0);
return;
@@ -795,6 +796,8 @@ static int __init mconsole_init(void)
printk(KERN_ERR "Failed to initialize management console\n");
return 1;
}
+ if (os_set_fd_block(sock, 0))
+ goto out;
register_reboot_notifier(&reboot_notifier);
@@ -803,7 +806,7 @@ static int __init mconsole_init(void)
"mconsole", (void *)sock);
if (err) {
printk(KERN_ERR "Failed to get IRQ for management console\n");
- return 1;
+ goto out;
}
if (notify_socket != NULL) {
@@ -819,6 +822,10 @@ static int __init mconsole_init(void)
printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
MCONSOLE_VERSION, mconsole_socket_name);
return 0;
+
+ out:
+ os_close_file(sock);
+ return 1;
}
__initcall(mconsole_init);
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 430c024a19b0..13af2f03ed84 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -83,9 +83,8 @@ int mconsole_get_request(int fd, struct mc_request *req)
int len;
req->originlen = sizeof(req->origin);
- req->len = recvfrom(fd, &req->request, sizeof(req->request),
- MSG_DONTWAIT, (struct sockaddr *) req->origin,
- &req->originlen);
+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
+ (struct sockaddr *) req->origin, &req->originlen);
if (req->len < 0)
return 0;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 3c6c44ca1ffa..1e8f41a99511 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -318,7 +318,7 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
if (str == NULL)
goto random;
- for (i = 0;i < 6; i++) {
+ for (i = 0; i < 6; i++) {
addr[i] = simple_strtoul(str, &end, 16);
if ((end == str) ||
((*end != ':') && (*end != ',') && (*end != '\0'))) {
@@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
}
if (!is_local_ether_addr(addr)) {
printk(KERN_WARNING
- "Warning: attempt to assign a globally valid ethernet "
+ "Warning: Assigning a globally valid ethernet "
"address to a device\n");
- printk(KERN_WARNING "You should better enable the 2nd "
- "rightmost bit in the first byte of the MAC,\n");
+ printk(KERN_WARNING "You should set the 2nd rightmost bit in "
+ "the first byte of the MAC,\n");
printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
addr[5]);
- goto random;
}
return;
@@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = {
.name = DRIVER_NAME,
},
};
-static int driver_registered;
static void net_device_release(struct device *dev)
{
@@ -383,6 +381,12 @@ static void net_device_release(struct device *dev)
free_netdev(netdev);
}
+/*
+ * Ensures that platform_driver_register is called only once by
+ * eth_configure. Will be set in an initcall.
+ */
+static int driver_registered;
+
static void eth_configure(int n, void *init, char *mac,
struct transport *transport)
{
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 29185cad9fff..abf2653f5517 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
close(fds[1]);
if (pid > 0)
- helper_wait(pid, 0, "change_tramp");
+ helper_wait(pid);
return pid;
}
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 330543b3129b..19930081d3d8 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -6,6 +6,7 @@
#include "linux/completion.h"
#include "linux/interrupt.h"
#include "linux/list.h"
+#include "linux/mutex.h"
#include "asm/atomic.h"
#include "init.h"
#include "irq_kern.h"
@@ -120,7 +121,7 @@ static int port_accept(struct port_list *port)
return 0;
}
-static DECLARE_MUTEX(ports_sem);
+static DEFINE_MUTEX(ports_mutex);
static LIST_HEAD(ports);
static void port_work_proc(struct work_struct *unused)
@@ -161,7 +162,7 @@ void *port_data(int port_num)
struct port_dev *dev = NULL;
int fd;
- down(&ports_sem);
+ mutex_lock(&ports_mutex);
list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
if (port->port == port_num)
@@ -216,7 +217,7 @@ void *port_data(int port_num)
out_free:
kfree(port);
out:
- up(&ports_sem);
+ mutex_unlock(&ports_mutex);
return dev;
}
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index e942e836f995..71f0959c1535 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -5,6 +5,7 @@
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
+#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index b8711e50da80..8b80505a3fb0 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -109,7 +109,7 @@ static int slip_tramp(char **argv, int fd)
read_output(fds[0], output, output_len);
printk("%s", output);
- err = helper_wait(pid, 0, argv[0]);
+ err = helper_wait(pid);
close(fds[0]);
out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 89c1be225fda..a0ada8fec72a 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -98,7 +98,7 @@ static void slirp_close(int fd, void *data)
"(%d)\n", pri->pid, errno);
}
#endif
- err = helper_wait(pri->pid, 1, "slirp_close");
+ err = helper_wait(pri->pid);
if (err < 0)
return;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 875d60d0c6a2..f1786e64607f 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -15,7 +15,6 @@
#include "line.h"
#include "ssl.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "kern.h"
#include "init.h"
#include "irq_user.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 656036e90b19..cec0c33cdd39 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -22,7 +22,6 @@
#include "stdio_console.h"
#include "line.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 99f9f9605e9c..be3a2797dac4 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,6 +49,7 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "ubd_user.h"
+#include "kern_util.h"
#include "os.h"
#include "mem.h"
#include "mem_kern.h"
@@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count,
return len;
}
-static void make_ide_entries(char *dev_name)
+static void make_ide_entries(const char *dev_name)
{
struct proc_dir_entry *dir, *ent;
char name[64];
@@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name)
ent->data = NULL;
ent->read_proc = proc_ide_read_media;
ent->write_proc = NULL;
- sprintf(name,"ide0/%s", dev_name);
+ snprintf(name, sizeof(name), "ide0/%s", dev_name);
proc_symlink(dev_name, proc_ide_root, name);
}
@@ -437,7 +438,10 @@ __uml_help(ubd_setup,
" machine by running 'dd' on the device. <n> must be in the range\n"
" 0 to 7. Appending an 'r' to the number will cause that device\n"
" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
-" an 's' will cause data to be written to disk on the host immediately.\n\n"
+" an 's' will cause data to be written to disk on the host immediately.\n"
+" 'c' will cause the device to be treated as being shared between multiple\n"
+" UMLs and file locking will be turned off - this is appropriate for a\n"
+" cluster filesystem and inappropriate at almost all other times.\n\n"
);
static int udb_setup(char *str)
@@ -456,20 +460,6 @@ __uml_help(udb_setup,
" in the boot output.\n\n"
);
-static int fakehd_set = 0;
-static int fakehd(char *str)
-{
- printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
- fakehd_set = 1;
- return 1;
-}
-
-__setup("fakehd", fakehd);
-__uml_help(fakehd,
-"fakehd\n"
-" Change the ubd device name to \"hd\".\n\n"
-);
-
static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
@@ -718,8 +708,10 @@ static int ubd_add(int n, char **error_out)
ubd_disk_register(fake_major, ubd_dev->size, n,
&fake_gendisk[n]);
- /* perhaps this should also be under the "if (fake_major)" above */
- /* using the fake_disk->disk_name and also the fakehd_set name */
+ /*
+ * Perhaps this should also be under the "if (fake_major)" above
+ * using the fake_disk->disk_name
+ */
if (fake_ide)
make_ide_entries(ubd_gendisk[n]->disk_name);
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 48fc7452bc1d..b591bb9c41dd 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
#include <sys/mman.h>
#include <sys/param.h>
#include "asm/types.h"
-#include "kern_util.h"
#include "user.h"
#include "ubd_user.h"
#include "os.h"
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index d9941fe5f931..56533db25343 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -80,7 +80,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
if (vpri->args == NULL) {
- printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
+ printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
"allocation failed");
return;
}
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 49c601ff2bac..2de92a08a76b 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -10,6 +10,6 @@
extern void arch_check_bugs(void);
extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
-extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
+extern void arch_examine_signal(int sig, struct uml_pt_regs *regs);
#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index a5cdf953e04a..606bb5c7fdf6 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -10,23 +10,31 @@
#include "kern_constants.h"
/*
- * Assembly doesn't want any casting, but C does, so define these
- * without casts here, and define new symbols with casts inside the C
- * section.
+ * Stolen from linux/const.h, which can't be directly included since
+ * this is used in userspace code, which has no access to the kernel
+ * headers. Changed to be suitable for adding casts to the start,
+ * rather than "UL" to the end.
*/
-#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
-#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
-#define ASM_STUB_START ASM_STUB_CODE
-/*
- * This file is included by the assembly stubs, which just want the
- * definitions above.
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally. We
+ * use the following macros to deal with this.
*/
-#ifndef __ASSEMBLY__
-#define STUB_CODE ((unsigned long) ASM_STUB_CODE)
-#define STUB_DATA ((unsigned long) ASM_STUB_DATA)
-#define STUB_START ((unsigned long) ASM_STUB_START)
+#ifdef __ASSEMBLY__
+#define _AC(X, Y) (Y)
+#else
+#define __AC(X, Y) (X (Y))
+#define _AC(X, Y) __AC(X, Y)
+#endif
+
+#define STUB_START _AC(, 0x100000)
+#define STUB_CODE _AC((unsigned long), STUB_START)
+#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
+#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
+
+#ifndef __ASSEMBLY__
#include "sysdep/ptrace.h"
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 5a2263e05bb2..9b9ced85b703 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -48,7 +48,7 @@ extern void register_winch_irq(int fd, int tty_fd, int pid,
#define __channel_help(fn, prefix) \
__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
" Attach a console or serial line to a host channel. See\n" \
-" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \
+" http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
" description of this switch.\n\n" \
);
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 0edab695ed4e..b54bd35585c2 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -18,6 +18,7 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
DEFINE_STR(UM_KERN_INFO, KERN_INFO);
DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+DEFINE_STR(UM_KERN_CONT, KERN_CONT);
DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index cebc6cae9190..b00a95741d41 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -40,6 +40,20 @@
typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);
+#ifndef __KERNEL__
+#ifndef __section
+# define __section(S) __attribute__ ((__section__(#S)))
+#endif
+
+#if __GNUC_MINOR__ >= 3
+# define __used __attribute__((__used__))
+#else
+# define __used __attribute__((__unused__))
+#endif
+
+#else
+#include <linux/compiler.h>
+#endif
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text)
@@ -127,14 +141,3 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
#endif
#endif /* _LINUX_UML_INIT_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 884a9c17eea0..e60b31873de1 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -14,7 +14,6 @@ struct irq_fd {
int fd;
int type;
int irq;
- int pid;
int events;
int current_events;
};
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 74ce8e5370a6..3c341222d252 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -9,107 +9,61 @@
#include "sysdep/ptrace.h"
#include "sysdep/faultinfo.h"
-typedef void (*kern_hndl)(int, struct uml_pt_regs *);
-
-struct kern_handlers {
- kern_hndl relay_signal;
- kern_hndl winch;
- kern_hndl bus_handler;
- kern_hndl page_fault;
- kern_hndl sigio_handler;
- kern_hndl timer_handler;
-};
-
-extern const struct kern_handlers handlinfo_kern;
+extern int uml_exitcode;
extern int ncpus;
-extern char *gdb_init;
extern int kmalloc_ok;
-extern int jail;
-extern int nsyscalls;
-#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define UML_ROUND_UP(addr) \
- UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
+ ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
-extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
-extern int kernel_thread_proc(void *data);
-extern void syscall_segv(int sig);
-extern int current_pid(void);
extern unsigned long alloc_stack(int order, int atomic);
+extern void free_stack(unsigned long stack, int order);
+
extern int do_signal(void);
-extern int is_stack_fault(unsigned long sp);
+extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void interrupt_end(void);
+extern void relay_signal(int sig, struct uml_pt_regs *regs);
+
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
int is_user, struct uml_pt_regs *regs);
extern int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out);
-extern void syscall_ready(void);
-extern void set_tracing(void *t, int tracing);
-extern int is_tracing(void *task);
-extern int segv_syscall(void);
-extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
-extern unsigned long page_mask(void);
-extern int need_finish_fork(void);
-extern void free_stack(unsigned long stack, int order);
-extern void add_input_request(int op, void (*proc)(int), void *arg);
-extern char *current_cmd(void);
-extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern int set_signals(int enable);
-extern int pid_to_processor_id(int pid);
-extern void deliver_signals(void *t);
-extern int next_trap_index(int max);
-extern void default_idle(void);
-extern void finish_fork(void);
-extern void paging_init(void);
-extern void init_flush_vm(void);
-extern void *syscall_sp(void *t);
-extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
-extern void interrupt_end(void);
-extern void initial_thread_cb(void (*proc)(void *), void *arg);
-extern int debugger_signal(int status, int pid);
-extern void debugger_parent_signal(int status, int pid);
-extern void child_signal(int pid, int status);
-extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
-extern int init_parent_proxy(int pid);
-extern int singlestepping(void *t);
-extern void check_stack_overflow(void *ptr);
-extern void relay_signal(int sig, struct uml_pt_regs *regs);
-extern int user_context(unsigned long sp);
-extern void timer_irq(struct uml_pt_regs *regs);
-extern void do_uml_exitcalls(void);
-extern int attach_debugger(int idle_pid, int pid, int stop);
-extern int config_gdb(char *str);
-extern int remove_gdb(void);
-extern char *uml_strdup(char *string);
-extern void unprotect_kernel_mem(void);
-extern void protect_kernel_mem(void);
-extern void uml_cleanup(void);
-extern void lock_signalled_task(void *t);
-extern void IPI_handler(int cpu);
-extern int jail_setup(char *line, int *add);
-extern void *get_init_task(void);
-extern int clear_user_proc(void *buf, int size);
-extern int copy_to_user_proc(void *to, void *from, int size);
-extern int copy_from_user_proc(void *to, void *from, int size);
-extern int strlen_user_proc(char *str);
-extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
-extern void *get_current(void);
-extern struct task_struct *get_task(int pid, int require);
-extern void machine_halt(void);
+extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int is_syscall(unsigned long addr);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void free_irq(unsigned int, void *);
-extern int cpu(void);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void time_init_kern(void);
+extern int start_uml(void);
+extern void paging_init(void);
-/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
+extern void uml_cleanup(void);
+extern void do_uml_exitcalls(void);
+
+/*
+ * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
+ * GFP_ATOMIC.
+ */
extern int __cant_sleep(void);
-extern void sigio_handler(int sig, struct uml_pt_regs *regs);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void *get_current(void);
+extern int copy_from_user_proc(void *to, void *from, int size);
+extern int cpu(void);
+extern char *uml_strdup(const char *string);
+
extern unsigned long to_irq_stack(unsigned long *mask_out);
-unsigned long from_irq_stack(int nested);
-extern int start_uml(void);
+extern unsigned long from_irq_stack(int nested);
+
+extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+extern int singlestepping(void *t);
+
+extern void segv_handler(int sig, struct uml_pt_regs *regs);
+extern void bus_handler(int sig, struct uml_pt_regs *regs);
+extern void winch(int sig, struct uml_pt_regs *regs);
+extern void fatal_sigsegv(void) __attribute__ ((noreturn));
+
+
#endif
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index a54514d2cc3a..46384acd547b 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -46,9 +46,6 @@ extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
-extern unsigned long host_task_size;
-extern unsigned long task_size;
-
extern int init_mem_user(void);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
@@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable,
unsigned long len, unsigned long long highmem);
extern void add_iomem(char *name, int fd, unsigned long size);
extern unsigned long phys_offset(unsigned long phys);
-extern void unmap_physmem(void);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
-extern unsigned long get_kmem_end(void);
#endif
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
deleted file mode 100644
index 989bc08de36e..000000000000
--- a/arch/um/include/misc_constants.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MISC_CONSTANT_H_
-#define __MISC_CONSTANT_H_
-
-#include <user_constants.h>
-
-#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 6f0d1c741bca..0b6b62733303 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -8,7 +8,6 @@
#include <stdarg.h>
#include "irq_user.h"
-#include "kern_util.h"
#include "longjmp.h"
#include "mm_id.h"
#include "sysdep/tls.h"
@@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags)
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
-extern int os_get_exec_close(int fd, int *close_on_exec);
extern int os_set_exec_close(int fd);
extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
-extern int os_set_owner(int fd, int pid);
extern int os_mode_fd(int fd, int mode);
extern int os_seek_file(int fd, unsigned long long offset);
-extern int os_open_file(char *file, struct openflags flags, int mode);
+extern int os_open_file(const char *file, struct openflags flags, int mode);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
-extern int os_file_size(char *file, unsigned long long *size_out);
-extern int os_file_modtime(char *file, unsigned long *modtime);
+extern int os_file_size(const char *file, unsigned long long *size_out);
+extern int os_file_modtime(const char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
-extern int os_set_fd_async(int fd, int owner);
+extern int os_set_fd_async(int fd);
extern int os_clear_fd_async(int fd);
extern int os_set_fd_block(int fd, int blocking);
extern int os_accept_connection(int fd);
-extern int os_create_unix_socket(char *file, int len, int close_on_exec);
+extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
extern int os_shutdown_socket(int fd, int r, int w);
extern void os_close_file(int fd);
extern int os_rcv_fd(int fd, int *helper_pid_out);
extern int create_unix_socket(char *file, int len, int close_on_exec);
-extern int os_connect_socket(char *name);
+extern int os_connect_socket(const char *name);
extern int os_file_type(char *file);
-extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_file_mode(const char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
extern void os_flush_stdout(void);
extern int os_stat_filesystem(char *path, long *bsize_out,
@@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
-extern int can_do_skas(void);
+extern void can_do_skas(void);
extern void os_check_bugs(void);
extern void check_host_supports_tls(int *supports_tls, int *tls_min);
-/* Make sure they are clear when running in TT mode. Required by
- * SEGV_MAYBE_FIXABLE */
-#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
-
/* mem.c */
extern int create_mem_file(unsigned long long len);
@@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
extern int run_helper_thread(int (*proc)(void *), void *arg,
unsigned int flags, unsigned long *stack_out);
-extern int helper_wait(int pid, int nohang, char *pname);
+extern int helper_wait(int pid);
/* tls.c */
@@ -237,16 +230,12 @@ extern void unblock_signals(void);
extern int get_signals(void);
extern int set_signals(int enable);
-/* trap.c */
-extern void os_fill_handlinfo(struct kern_handlers h);
-
/* util.c */
extern void stack_protections(unsigned long address);
extern int raw(int fd);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(char *buf, int len);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
-extern void os_dump_core(void);
+extern void os_dump_core(void) __attribute__ ((noreturn));
/* time.c */
extern void idle_sleep(unsigned long long nsecs);
@@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
extern void userspace(struct uml_pt_regs *regs);
-extern void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack);
+extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
extern void switch_threads(jmp_buf *me, jmp_buf *you);
extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
@@ -298,16 +285,12 @@ extern void os_free_irq_later(struct irq_fd *active_fds,
extern int os_get_pollfd(int i);
extern void os_set_pollfd(int i, int fd);
extern void os_set_ioignore(void);
-extern void init_irq_signals(int on_sigstack);
/* sigio.c */
extern int add_sigio_fd(int fd);
extern int ignore_sigio_fd(int fd);
extern void maybe_sigio_broken(int fd, int read);
-/* skas/trap */
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
-
/* sys-x86_64/prctl.c */
extern int os_arch_prctl(int pid, int code, unsigned long *addr);
diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h
index f3450e6bc18d..4bce6e012889 100644
--- a/arch/um/include/ptrace_user.h
+++ b/arch/um/include/ptrace_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -10,12 +10,6 @@
extern int ptrace_getregs(long pid, unsigned long *regs_out);
extern int ptrace_setregs(long pid, unsigned long *regs_in);
-extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
-extern int ptrace_setfpregs(long pid, unsigned long *regs);
-extern void arch_enter_kernel(void *task, int pid);
-extern void arch_leave_kernel(void *task, int pid);
-extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
-
/* syscall emulation path in ptrace */
@@ -54,7 +48,8 @@ extern int sysemu_supported;
(((int[3][3] ) { \
{ PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
{ PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
- { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \
+ { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
+ PTRACE_SYSEMU_SINGLESTEP } }) \
[sysemu_mode][singlestep_mode])
#endif
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 0e27406a43a4..9ea1ae3c8f46 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,14 +9,13 @@
#include "sysdep/ptrace.h"
#include "sysdep/archsetjmp.h"
-extern void init_thread_registers(struct uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern int save_fpx_registers(int pid, unsigned long *fp_regs);
extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
-extern void init_registers(int pid);
+extern int save_registers(int pid, struct uml_pt_regs *regs);
+extern int restore_registers(int pid, struct uml_pt_regs *regs);
+extern int init_registers(int pid);
extern void get_safe_registers(unsigned long *regs);
extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h
deleted file mode 100644
index aeb5d5ab1dfd..000000000000
--- a/arch/um/include/signal_kern.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SIGNAL_KERN_H__
-#define __SIGNAL_KERN_H__
-
-extern int have_signals(void *t);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
deleted file mode 100644
index e065feb000df..000000000000
--- a/arch/um/include/skas/mode-skas.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_SKAS_H__
-#define __MODE_SKAS_H__
-
-extern void kill_off_processes_skas(void);
-
-#endif
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 57bd79efbee3..905698197e35 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386;
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
- ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+ ((long (*)(struct syscall_args)) \
+ (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index c978b589df41..a307237b7964 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -17,16 +17,7 @@
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem));
-#define __NO_STUBS 1
-#undef __SYSCALL
-#undef _ASM_X86_64_UNISTD_H_
-#define __SYSCALL(nr, sym) [nr] = 1,
-static char syscalls[] = {
-#include <asm/arch/unistd.h>
-};
-
void foo(void)
{
#include <common-offsets.h>
-DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1);
}
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index cf72256609e4..7cfb0b085655 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -30,6 +30,4 @@ extern long old_mmap(unsigned long addr, unsigned long len,
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_arch_prctl;
-#define NR_syscalls (UM_NR_syscall_max + 1)
-
#endif
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 8855d8df512f..82865fcf6872 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -12,10 +12,6 @@
typedef struct mm_context {
struct mm_id id;
- unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
- unsigned long last_pmd;
-#endif
struct uml_ldt ldt;
} mm_context_t;
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index fdfc06b85605..2b6fc8e0f071 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -6,7 +6,9 @@
#ifndef __ARCH_UM_UACCESS_H
#define __ARCH_UM_UACCESS_H
-#include "asm/fixmap.h"
+#include <asm/elf.h>
+#include <asm/fixmap.h>
+#include "sysdep/archsetjmp.h"
#define __under_task_size(addr, size) \
(((unsigned long) (addr) < TASK_SIZE) && \
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8196450451cd..76a62c0cb2bc 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -19,12 +19,13 @@
void flush_thread(void)
{
void *data = NULL;
- unsigned long end = proc_mm ? task_size : STUB_START;
int ret;
arch_flush_thread(&current->thread.arch);
- ret = unmap(&current->mm->context.id, 0, end, 1, &data);
+ ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
+ ret = ret || unmap(&current->mm->context.id, STUB_END,
+ TASK_SIZE - STUB_END, 1, &data);
if (ret) {
printk(KERN_ERR "flush_thread - clearing address space failed, "
"err = %d\n", ret);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index c716b5a6db13..984f80e668ca 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,15 +1,17 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/init.h"
-#include "linux/ctype.h"
-#include "linux/proc_fs.h"
-#include "asm/uaccess.h"
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
-/* If read and write race, the read will still atomically read a valid
+/*
+ * If read and write race, the read will still atomically read a valid
* value.
*/
int uml_exitcode = 0;
@@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
{
int len, val;
- /* Save uml_exitcode in a local so that we don't need to guarantee
+ /*
+ * Save uml_exitcode in a local so that we don't need to guarantee
* that sprintf accesses it atomically.
*/
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count)
+ if (len <= off+count)
*eof = 1;
*start = page + off;
- if(len > count)
+ if (len > count)
len = count;
- if(len < 0)
+ if (len < 0)
len = 0;
return len;
}
@@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
char *end, buf[sizeof("nnnnn\0")];
int tmp;
- if(copy_from_user(buf, buffer, count))
+ if (copy_from_user(buf, buffer, count))
return -EFAULT;
tmp = simple_strtol(buf, &end, 0);
- if((*end != '\0') && !isspace(*end))
+ if ((*end != '\0') && !isspace(*end))
return -EINVAL;
uml_exitcode = tmp;
@@ -57,7 +60,7 @@ static int make_proc_exitcode(void)
struct proc_dir_entry *ent;
ent = create_proc_entry("exitcode", 0600, &proc_root);
- if(ent == NULL){
+ if (ent == NULL) {
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
return 0;
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 734f873cab12..72eccd2a4113 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,12 +8,13 @@
extern void __bb_init_func(void *) __attribute__((weak));
EXPORT_SYMBOL(__bb_init_func);
-/* This is defined (and referred to in profiling stub code) only by some GCC
+/*
+ * This is defined (and referred to in profiling stub code) only by some GCC
* versions in libgcov.
*
* Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which will
- * be overridden by any other one.
+ * So, unconditionally export it. But also give it a weak declaration, which
+ * will be overridden by any other one.
*/
extern void __gcov_init(void *) __attribute__((weak));
diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c
index 9244f018d44c..e2f043d0de6c 100644
--- a/arch/um/kernel/gprof_syms.c
+++ b/arch/um/kernel/gprof_syms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,14 +7,3 @@
extern void mcount(void);
EXPORT_SYMBOL(mcount);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 16dc43e9d940..fa015565001b 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,7 +7,6 @@
#include "linux/bootmem.h"
#include "linux/initrd.h"
#include "asm/types.h"
-#include "kern_util.h"
#include "initrd.h"
#include "init.h"
#include "os.h"
@@ -21,18 +20,27 @@ static int __init read_initrd(void)
long long size;
int err;
- if(initrd == NULL)
+ if (initrd == NULL)
return 0;
err = os_file_size(initrd, &size);
- if(err)
+ if (err)
return 0;
+ /*
+ * This is necessary because alloc_bootmem craps out if you
+ * ask for no memory.
+ */
+ if (size == 0) {
+ printk(KERN_ERR "\"%\" is a zero-size initrd\n");
+ return 0;
+ }
+
area = alloc_bootmem(size);
- if(area == NULL)
+ if (area == NULL)
return 0;
- if(load_initrd(initrd, area, size) == -1)
+ if (load_initrd(initrd, area, size) == -1)
return 0;
initrd_start = (unsigned long) area;
@@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size)
int fd, n;
fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ if (fd < 0) {
+ printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
+ -fd);
return -1;
}
n = os_read_file(fd, buf, size);
- if(n != size){
- printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ if (n != size) {
+ printk(KERN_ERR "Read of %d bytes from '%s' failed, "
+ "err = %d\n", size,
filename, -n);
return -1;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index ba11ccd6a8a3..91587f8db340 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -107,10 +107,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
struct pollfd *tmp_pfd;
struct irq_fd *new_fd, *irq_fd;
unsigned long flags;
- int pid, events, err, n;
+ int events, err, n;
- pid = os_getpid();
- err = os_set_fd_async(fd, pid);
+ err = os_set_fd_async(fd);
if (err < 0)
goto out;
@@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.fd = fd,
.type = type,
.irq = irq,
- .pid = pid,
.events = events,
.current_events = 0 } );
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7c7142ba3bd7..5311ee93ede3 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -18,15 +18,11 @@ EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(task_size);
EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
-EXPORT_SYMBOL(get_kmem_end);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(um_virt_to_phys);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
@@ -40,7 +36,6 @@ EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
EXPORT_SYMBOL(os_access);
-EXPORT_SYMBOL(os_get_exec_close);
EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
EXPORT_SYMBOL(os_open_file);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 59822dee438a..d872fdce1d7e 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,49 +1,41 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/mm.h"
-#include "linux/bootmem.h"
-#include "linux/swap.h"
-#include "linux/highmem.h"
-#include "linux/gfp.h"
-#include "asm/page.h"
-#include "asm/fixmap.h"
-#include "asm/pgalloc.h"
-#include "kern_util.h"
+#include <linux/stddef.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
#include "as-layout.h"
+#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
-#include "um_uaccess.h"
#include "os.h"
-#include "linux/types.h"
-#include "linux/string.h"
-#include "init.h"
-#include "kern_constants.h"
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL;
/* allocated in paging_init and unchanged thereafter */
unsigned long *empty_bad_page = NULL;
+
+/*
+ * Initialized during boot, and readonly for initializing page tables
+ * afterwards
+ */
pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* Initialized at boot time, and readonly after that */
unsigned long long highmem;
int kmalloc_ok = 0;
+/* Used during early boot */
static unsigned long brk_end;
-void unmap_physmem(void)
-{
- os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
-
-static void map_cb(void *unused)
-{
- map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
-}
-
#ifdef CONFIG_HIGHMEM
static void setup_highmem(unsigned long highmem_start,
unsigned long highmem_len)
@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
int i;
highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
- for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+ for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
page = &mem_map[highmem_pfn + i];
ClearPageReserved(page);
init_page_count(page);
@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
void __init mem_init(void)
{
/* clear the zero-page */
- memset((void *) empty_zero_page, 0, PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
/* Map in the area just after the brk now that kmalloc is about
* to be turned on.
*/
brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
- map_cb(NULL);
- initial_thread_cb(map_cb, NULL);
+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
@@ -85,7 +76,7 @@ void __init mem_init(void)
#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
- printk(KERN_INFO "Memory: %luk available\n",
+ printk(KERN_INFO "Memory: %luk available\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
kmalloc_ok = 1;
@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
#endif
}
-static void __init fixrange_init(unsigned long start, unsigned long end,
+static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
if (pud_none(*pud))
one_md_table_init(pud);
pmd = pmd_offset(pud, vaddr);
- for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
- (vaddr)), (vaddr))
+ (vaddr)), (vaddr))
static void __init kmap_init(void)
{
@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long paddr, vaddr = FIXADDR_USER_START;
+ phys_t p;
+ unsigned long v, vaddr = FIXADDR_USER_START;
- if ( ! size )
+ if (!size)
return;
fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
- paddr = (unsigned long)alloc_bootmem_low_pages( size);
- memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
- paddr = __pa(paddr);
- for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
+ v = (unsigned long) alloc_bootmem_low_pages(size);
+ memcpy((void *) v , (void *) FIXADDR_USER_START, size);
+ p = __pa(v);
+ for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
+ p += PAGE_SIZE) {
pgd = swapper_pg_dir + pgd_index(vaddr);
pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
- pte_set_val( (*pte), paddr, PAGE_READONLY);
+ pte_set_val(*pte, p, PAGE_READONLY);
}
#endif
}
@@ -223,7 +216,7 @@ void __init paging_init(void)
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
- for(i = 0; i < ARRAY_SIZE(zones_size); i++)
+ for (i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
int i;
again:
- if(page == NULL)
+ if (page == NULL)
return page;
- if(PageHighMem(page))
+ if (PageHighMem(page))
return page;
addr = (unsigned long) page_address(page);
- for(i = 0; i < (1 << order); i++){
+ for (i = 0; i < (1 << order); i++) {
current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void __user *) addr, &zero,
+ if (__do_copy_to_user((void __user *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
- &current->thread.fault_catcher)){
- if(!(mask & __GFP_WAIT))
+ &current->thread.fault_catcher)) {
+ if (!(mask & __GFP_WAIT))
return NULL;
else break;
}
addr += PAGE_SIZE;
}
- if(i == (1 << order))
+ if (i == (1 << order))
return page;
page = alloc_pages(mask, order);
goto again;
}
-/* This can't do anything because nothing in the kernel image can be freed
+/*
+ * This can't do anything because nothing in the kernel image can be freed
* since it's not in kernel physical memory.
*/
@@ -290,8 +284,8 @@ void free_initmem(void)
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
- printk ("Freeing initrd memory: %ldk freed\n",
- (end - start) >> 10);
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+ (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
@@ -308,32 +302,31 @@ void show_mem(void)
int highmem = 0;
struct page *page;
- printk("Mem-info:\n");
+ printk(KERN_INFO "Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Free swap: %6ldkB\n",
+ nr_swap_pages<<(PAGE_SHIFT-10));
pfn = max_mapnr;
- while(pfn-- > 0) {
+ while (pfn-- > 0) {
page = pfn_to_page(pfn);
total++;
- if(PageHighMem(page))
+ if (PageHighMem(page))
highmem++;
- if(PageReserved(page))
+ if (PageReserved(page))
reserved++;
- else if(PageSwapCache(page))
+ else if (PageSwapCache(page))
cached++;
- else if(page_count(page))
+ else if (page_count(page))
shared += page_count(page) - 1;
}
- printk("%d pages of RAM\n", total);
- printk("%d pages of HIGHMEM\n", highmem);
- printk("%d reserved pages\n", reserved);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
}
-/*
- * Allocate and free page tables.
- */
+/* Allocate and free page tables. */
pgd_t *pgd_alloc(struct mm_struct *mm)
{
@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
@@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
+
+#ifdef CONFIG_3_LEVEL_PGTABLES
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd)
+ memset(pmd, 0, PAGE_SIZE);
+
+ return pmd;
+}
+#endif
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index e66432f42485..9757085a0220 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -55,16 +55,6 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
return 0;
}
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
- if (kmem_top == 0)
- kmem_top = host_task_size - 1024 * 1024;
- return kmem_top;
-}
-
void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
int r, int w, int x)
{
@@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem,
* setup_iomem, both of which run during early boot. Afterwards, it's
* unchanged.
*/
-struct iomem_region *iomem_regions = NULL;
+struct iomem_region *iomem_regions;
-/* Initialized in parse_iomem */
-int iomem_size = 0;
+/* Initialized in parse_iomem and unchanged thereafter */
+int iomem_size;
unsigned long find_iomem(char *driver, unsigned long *len_out)
{
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 0eae00b3e588..c07961bedb75 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -4,19 +4,21 @@
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/err.h"
-#include "linux/hardirq.h"
-#include "linux/mm.h"
-#include "linux/personality.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/sched.h"
-#include "linux/tick.h"
-#include "linux/threads.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/threads.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
@@ -30,7 +32,7 @@
*/
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-static inline int external_pid(struct task_struct *task)
+static inline int external_pid(void)
{
/* FIXME: Need to look up userspace_pid by cpu */
return userspace_pid[0];
@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
{
int i;
- for(i = 0; i < ncpus; i++) {
+ for (i = 0; i < ncpus; i++) {
if (cpu_tasks[i].pid == pid)
return i;
}
@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
if (atomic)
flags = GFP_ATOMIC;
page = __get_free_pages(flags, order);
- if (page == 0)
- return 0;
return page;
}
@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
static inline void set_current(struct task_struct *task)
{
cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
- { external_pid(task), task });
+ { external_pid(), task });
}
-extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to(struct task_struct *to);
void *_switch_to(void *prev, void *next, void *last)
{
struct task_struct *from = prev;
- struct task_struct *to= next;
+ struct task_struct *to = next;
to->thread.prev_sched = from;
set_current(to);
@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
switch_threads(&from->thread.switch_buf,
&to->thread.switch_buf);
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
if (current->thread.saved_task)
show_regs(&(current->thread.regs));
- next= current->thread.saved_task;
- prev= current;
- } while(current->thread.saved_task);
+ to = current->thread.saved_task;
+ from = current;
+ } while (current->thread.saved_task);
return current->thread.prev_sched;
@@ -163,8 +163,6 @@ void new_thread_handler(void)
void fork_handler(void)
{
force_flush_all();
- if (current->thread.prev_sched == NULL)
- panic("blech");
schedule_tail(current->thread.prev_sched);
@@ -173,7 +171,7 @@ void fork_handler(void)
* arch_switch_to isn't needed. We could want to apply this to
* improve performance. -bb
*/
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
current->thread.prev_sched = NULL;
@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
arch_copy_thread(&current->thread.arch, &p->thread.arch);
}
else {
- init_thread_registers(&p->thread.regs.regs);
+ get_safe_registers(p->thread.regs.regs.gp);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
@@ -237,7 +235,7 @@ void default_idle(void)
{
unsigned long long nsecs;
- while(1) {
+ while (1) {
/* endless idle loop with no priority at all */
/*
@@ -256,53 +254,10 @@ void default_idle(void)
void cpu_idle(void)
{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
+ cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
default_idle();
}
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t ptent;
-
- if (task->mm == NULL)
- return ERR_PTR(-EINVAL);
- pgd = pgd_offset(task->mm, addr);
- if (!pgd_present(*pgd))
- return ERR_PTR(-EINVAL);
-
- pud = pud_offset(pgd, addr);
- if (!pud_present(*pud))
- return ERR_PTR(-EINVAL);
-
- pmd = pmd_offset(pud, addr);
- if (!pmd_present(*pmd))
- return ERR_PTR(-EINVAL);
-
- pte = pte_offset_kernel(pmd, addr);
- ptent = *pte;
- if (!pte_present(ptent))
- return ERR_PTR(-EINVAL);
-
- if (pte_out != NULL)
- *pte_out = ptent;
- return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
- return "(Unknown)";
-#else
- void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
- return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
void dump_thread(struct pt_regs *regs, struct user *u)
{
}
@@ -317,7 +272,7 @@ int user_context(unsigned long sp)
unsigned long stack;
stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
- return stack != (unsigned long) current_thread;
+ return stack != (unsigned long) current_thread_info();
}
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -331,7 +286,7 @@ void do_uml_exitcalls(void)
(*call)();
}
-char *uml_strdup(char *string)
+char *uml_strdup(const char *string)
{
return kstrdup(string, GFP_KERNEL);
}
@@ -359,7 +314,7 @@ int strlen_user_proc(char __user *str)
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
- int cpu = current_thread->cpu;
+ int cpu = current_thread_info()->cpu;
IPI_handler(cpu);
if (cpu != 0)
return 1;
@@ -369,7 +324,7 @@ int smp_sigio_handler(void)
int cpu(void)
{
- return current_thread->cpu;
+ return current_thread_info()->cpu;
}
static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -435,7 +390,7 @@ int singlestepping(void * t)
{
struct task_struct *task = t ? t : current;
- if ( ! (task->ptrace & PT_DTRACE) )
+ if (!(task->ptrace & PT_DTRACE))
return 0;
if (task->thread.singlestep_syscall)
@@ -459,3 +414,46 @@ unsigned long arch_align_stack(unsigned long sp)
return sp & ~0xf;
}
#endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long stack_page, sp, ip;
+ bool seen_sched = 0;
+
+ if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
+ return 0;
+
+ stack_page = (unsigned long) task_stack_page(p);
+ /* Bail if the process has no kernel stack for some reason */
+ if (stack_page == 0)
+ return 0;
+
+ sp = p->thread.switch_buf->JB_SP;
+ /*
+ * Bail if the stack pointer is below the bottom of the kernel
+ * stack for some reason
+ */
+ if (sp < stack_page)
+ return 0;
+
+ while (sp < stack_page + THREAD_SIZE) {
+ ip = *((unsigned long *) sp);
+ if (in_sched_functions(ip))
+ /* Ignore everything until we're above the scheduler */
+ seen_sched = 1;
+ else if (kernel_text_address(ip) && seen_sched)
+ return ip;
+
+ sp += sizeof(unsigned long);
+ }
+
+ return 0;
+}
+
+int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+{
+ int cpu = current_thread_info()->cpu;
+
+ return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+}
+
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 04cebcf0679f..00197d3d21ec 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
*/
#include "linux/sched.h"
+#include "kern_util.h"
#include "os.h"
#include "skas.h"
@@ -11,7 +12,7 @@ void (*pm_power_off)(void);
static void kill_off_processes(void)
{
- if(proc_mm)
+ if (proc_mm)
/*
* FIXME: need to loop over userspace_pids
*/
@@ -21,8 +22,8 @@ static void kill_off_processes(void)
int pid, me;
me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
+ for_each_process(p) {
+ if (p->mm == NULL)
continue;
pid = p->mm->context.id.u.pid;
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 89f9866a1354..2b272b63b514 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -1,18 +1,12 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/list.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "init.h"
-#include "sigio.h"
-#include "irq_user.h"
+#include <linux/interrupt.h>
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
@@ -33,9 +27,9 @@ int write_sigio_irq(int fd)
err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
NULL);
- if(err){
- printk("write_sigio_irq : um_request_irq failed, err = %d\n",
- err);
+ if (err) {
+ printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
+ "err = %d\n", err);
return -1;
}
sigio_irq_fd = fd;
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 19cb97733937..b0fce720c4d0 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/module.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "asm/siginfo.h"
-#include "asm/signal.h"
-#include "asm/unistd.h"
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+#include <asm/unistd.h>
#include "frame_kern.h"
#include "kern_util.h"
#include "sigcontext.h"
@@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs)
/* Did we come from a system call? */
if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
/* Restart the system call - no handlers present */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 8d07a7acb909..2c8583c1a344 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -1,17 +1,20 @@
-#include <sched.h>
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#include <signal.h>
-#include <sys/mman.h>
-#include <sys/time.h>
+#include <sched.h>
#include <asm/unistd.h>
+#include <sys/time.h>
#include "as-layout.h"
+#include "kern_constants.h"
#include "ptrace_user.h"
-#include "skas.h"
#include "stub-data.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
-#include "kern_constants.h"
-/* This is in a separate file because it needs to be compiled with any
+/*
+ * This is in a separate file because it needs to be compiled with any
* extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
*
* Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
@@ -26,25 +29,26 @@ stub_clone_handler(void)
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
- if(err != 0)
+ if (err != 0)
goto out;
err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
- if(err)
+ if (err)
goto out;
- err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
+ err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
(long) &data->timer, 0);
- if(err)
+ if (err)
goto out;
remap_stack(data->fd, data->offset);
goto done;
out:
- /* save current result.
- * Parent: pid;
- * child: retcode of mmap already saved and it jumps around this
+ /*
+ * save current result.
+ * Parent: pid;
+ * child: retcode of mmap already saved and it jumps around this
* assignment
*/
data->err = err;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index f859ec306cd5..78b3e9f69d57 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -34,33 +34,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;
- /*
- * There's an interaction between the skas0 stub pages, stack
- * randomization, and the BUG at the end of exit_mmap. exit_mmap
- * checks that the number of page tables freed is the same as had
- * been allocated. If the stack is on the last page table page,
- * then the stack pte page will be freed, and if not, it won't. To
- * avoid having to know where the stack is, or if the process mapped
- * something at the top of its address space for some other reason,
- * we set TASK_SIZE to end at the start of the last page table.
- * This keeps exit_mmap off the last page, but introduces a leak
- * of that page. So, we hang onto it here and free it in
- * destroy_context_skas.
- */
-
- mm->context.last_page_table = pmd_page_vaddr(*pmd);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
-#endif
-
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
return 0;
out_pmd:
- pud_free(pud);
+ pud_free(mm, pud);
out_pte:
- pmd_free(pmd);
+ pmd_free(mm, pmd);
out:
return -ENOMEM;
}
@@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
stack = get_zeroed_page(GFP_KERNEL);
if (stack == 0)
goto out;
-
- /*
- * This zeros the entry that pgd_alloc didn't, needed since
- * we are about to reinitialize it, and want mm.nr_ptes to
- * be accurate.
- */
- mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
-
- ret = init_stub_pte(mm, STUB_CODE,
- (unsigned long) &__syscall_stub_start);
- if (ret)
- goto out_free;
-
- ret = init_stub_pte(mm, STUB_DATA, stack);
- if (ret)
- goto out_free;
-
- mm->nr_ptes--;
}
to_mm->id.stack = stack;
@@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
to_mm->id.u.pid = copy_context_skas0(stack,
from_mm->id.u.pid);
else to_mm->id.u.pid = start_userspace(stack);
+
+ if (to_mm->id.u.pid < 0) {
+ ret = to_mm->id.u.pid;
+ goto out_free;
+ }
}
ret = init_new_ldt(to_mm, from_mm);
@@ -132,24 +100,87 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
return ret;
}
+void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+{
+ struct page **pages;
+ int err, ret;
+
+ if (!skas_needs_stub)
+ return;
+
+ ret = init_stub_pte(mm, STUB_CODE,
+ (unsigned long) &__syscall_stub_start);
+ if (ret)
+ goto out;
+
+ ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
+ if (ret)
+ goto out;
+
+ pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL) {
+ printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
+ "pointers\n");
+ goto out;
+ }
+
+ pages[0] = virt_to_page(&__syscall_stub_start);
+ pages[1] = virt_to_page(mm->context.id.stack);
+
+ /* dup_mmap already holds mmap_sem */
+ err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
+ VM_READ | VM_MAYREAD | VM_EXEC |
+ VM_MAYEXEC | VM_DONTCOPY, pages);
+ if (err) {
+ printk(KERN_ERR "install_special_mapping returned %d\n", err);
+ goto out_free;
+ }
+ return;
+
+out_free:
+ kfree(pages);
+out:
+ force_sigsegv(SIGSEGV, current);
+}
+
+void arch_exit_mmap(struct mm_struct *mm)
+{
+ pte_t *pte;
+
+ pte = virt_to_pte(mm, STUB_CODE);
+ if (pte != NULL)
+ pte_clear(mm, STUB_CODE, pte);
+
+ pte = virt_to_pte(mm, STUB_DATA);
+ if (pte == NULL)
+ return;
+
+ pte_clear(mm, STUB_DATA, pte);
+}
+
void destroy_context(struct mm_struct *mm)
{
struct mm_context *mmu = &mm->context;
if (proc_mm)
os_close_file(mmu->id.u.mm_fd);
- else
+ else {
+ /*
+ * If init_new_context wasn't called, this will be
+ * zero, resulting in a kill(0), which will result in the
+ * whole UML suddenly dying. Also, cover negative and
+ * 1 cases, since they shouldn't happen either.
+ */
+ if (mmu->id.u.pid < 2) {
+ printk(KERN_ERR "corrupt mm_context - pid = %d\n",
+ mmu->id.u.pid);
+ return;
+ }
os_kill_ptraced_process(mmu->id.u.pid, 1);
+ }
- if (!proc_mm || !ptrace_faultinfo) {
+ if (skas_needs_stub)
free_page(mmu->id.stack);
- pte_lock_deinit(virt_to_page(mmu->last_page_table));
- pte_free_kernel((pte_t *) mmu->last_page_table);
- dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- pmd_free((pmd_t *) mmu->last_pmd);
-#endif
- }
free_ldt(mmu);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index fce389c2342f..2e9852c0d487 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -6,19 +6,25 @@
#include "linux/init.h"
#include "linux/sched.h"
#include "as-layout.h"
+#include "kern.h"
#include "os.h"
#include "skas.h"
int new_mm(unsigned long stack)
{
- int fd;
+ int fd, err;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
if (fd < 0)
return fd;
- if (skas_needs_stub)
- map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (skas_needs_stub) {
+ err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (err) {
+ os_close_file(fd);
+ return err;
+ }
+ }
return fd;
}
@@ -49,8 +55,14 @@ int __init start_uml(void)
{
stack_protections((unsigned long) &cpu0_irqstack);
set_sigstack(cpu0_irqstack, THREAD_SIZE);
- if (proc_mm)
+ if (proc_mm) {
userspace_pid[0] = start_userspace(0);
+ if (userspace_pid[0] < 0) {
+ printf("start_uml - start_userspace returned %d\n",
+ userspace_pid[0]);
+ exit(1);
+ }
+ }
init_new_thread_signals();
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 50b476f2b38d..4e3b820bd2be 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -9,6 +9,9 @@
#include "sysdep/ptrace.h"
#include "sysdep/syscalls.h"
+extern int syscall_table_size;
+#define NR_syscalls (syscall_table_size / sizeof(void *))
+
void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
@@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r)
syscall_trace(r, 0);
- current->thread.nsyscalls++;
- nsyscalls++;
-
/*
* This should go in the declaration of syscall, but when I do that,
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 1d8b119f2d0e..e22c96993db3 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -3,128 +3,130 @@
* Licensed under the GPL
*/
-#include "linux/err.h"
-#include "linux/highmem.h"
-#include "linux/mm.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
+#include <linux/err.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
#include "kern_util.h"
#include "os.h"
-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out);
-
-static unsigned long maybe_map(unsigned long virt, int is_write)
+pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
{
- pte_t pte;
- int err;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ if (mm == NULL)
+ return NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (!pgd_present(*pgd))
+ return NULL;
+
+ pud = pud_offset(pgd, addr);
+ if (!pud_present(*pud))
+ return NULL;
- void *phys = um_virt_to_phys(current, virt, &pte);
- int dummy_code;
+ pmd = pmd_offset(pud, addr);
+ if (!pmd_present(*pmd))
+ return NULL;
+
+ return pte_offset_kernel(pmd, addr);
+}
+
+static pte_t *maybe_map(unsigned long virt, int is_write)
+{
+ pte_t *pte = virt_to_pte(current->mm, virt);
+ int err, dummy_code;
- if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
+ if ((pte == NULL) || !pte_present(*pte) ||
+ (is_write && !pte_write(*pte))) {
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
if (err)
- return -1UL;
- phys = um_virt_to_phys(current, virt, NULL);
+ return NULL;
+ pte = virt_to_pte(current->mm, virt);
}
- if (IS_ERR(phys))
- phys = (void *) -1;
+ if (!pte_present(*pte))
+ pte = NULL;
- return (unsigned long) phys;
+ return pte;
}
static int do_op_one_page(unsigned long addr, int len, int is_write,
int (*op)(unsigned long addr, int len, void *arg), void *arg)
{
+ jmp_buf buf;
struct page *page;
- int n;
+ pte_t *pte;
+ int n, faulted;
- addr = maybe_map(addr, is_write);
- if (addr == -1UL)
+ pte = maybe_map(addr, is_write);
+ if (pte == NULL)
return -1;
- page = phys_to_page(addr);
+ page = pte_page(*pte);
addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
(addr & ~PAGE_MASK);
- n = (*op)(addr, len, arg);
+ current->thread.fault_catcher = &buf;
+
+ faulted = UML_SETJMP(&buf);
+ if (faulted == 0)
+ n = (*op)(addr, len, arg);
+ else
+ n = -1;
+
+ current->thread.fault_catcher = NULL;
kunmap_atomic(page, KM_UML_USERCOPY);
return n;
}
-static void do_buffer_op(void *jmpbuf, void *arg_ptr)
+static int buffer_op(unsigned long addr, int len, int is_write,
+ int (*op)(unsigned long, int, void *), void *arg)
{
- va_list args;
- unsigned long addr;
- int len, is_write, size, remain, n;
- int (*op)(unsigned long, int, void *);
- void *arg;
- int *res;
-
- va_copy(args, *(va_list *)arg_ptr);
- addr = va_arg(args, unsigned long);
- len = va_arg(args, int);
- is_write = va_arg(args, int);
- op = va_arg(args, void *);
- arg = va_arg(args, void *);
- res = va_arg(args, int *);
- va_end(args);
+ int size, remain, n;
+
size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
remain = len;
- current->thread.fault_catcher = jmpbuf;
n = do_op_one_page(addr, size, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += size;
remain -= size;
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
- while(addr < ((addr + remain) & PAGE_MASK)) {
+ while (addr < ((addr + remain) & PAGE_MASK)) {
n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += PAGE_SIZE;
remain -= PAGE_SIZE;
}
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
n = do_op_one_page(addr, remain, is_write, op, arg);
- if (n != 0)
- *res = (n < 0 ? remain : 0);
- else *res = 0;
- out:
- current->thread.fault_catcher = NULL;
-}
-
-static int buffer_op(unsigned long addr, int len, int is_write,
- int (*op)(unsigned long addr, int len, void *arg),
- void *arg)
-{
- int faulted, res;
-
- faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
- &res);
- if (!faulted)
- return res;
+ if (n != 0) {
+ remain = (n < 0 ? remain : 0);
+ goto out;
+ }
- return addr + len - (unsigned long) current->thread.fault_addr;
+ return 0;
+ out:
+ return remain;
}
static int copy_chunk_from_user(unsigned long from, int len, void *arg)
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 36d89cf8d20b..e1062ec36d40 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
#include "asm/smp.h"
#include "asm/processor.h"
#include "asm/spinlock.h"
-#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "os.h"
@@ -61,7 +60,7 @@ void smp_send_stop(void)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
- printk(KERN_INFO "done\n");
+ printk(KERN_CONT "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -75,8 +74,7 @@ static int idle_proc(void *cpup)
if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
- os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
@@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- os_set_fd_async(cpu_data[me].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[me].ipi_pipe[0]);
for (cpu = 1; cpu < ncpus; cpu++) {
printk(KERN_INFO "Booting processor %d...\n", cpu);
@@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
cpu_relax();
- if (cpu_isset(cpu, cpu_callin_map))
- printk(KERN_INFO "done\n");
- else printk(KERN_INFO "failed\n");
+ printk(KERN_INFO "%s\n",
+ cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
}
}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index b9d92b2089ae..9cffc628a37e 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,9 +13,6 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
-/* Unlocked, I don't care if this is a bit off */
-int nsyscalls = 0;
-
long sys_fork(void)
{
long ret;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 93263571d813..56d43d0a3960 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -1,38 +1,37 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/kallsyms.h"
-#include "asm/page.h"
-#include "asm/processor.h"
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
#include "sysrq.h"
/* Catch non-i386 SUBARCH's. */
#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
void show_trace(struct task_struct *task, unsigned long * stack)
{
- unsigned long addr;
+ unsigned long addr;
- if (!stack) {
+ if (!stack) {
stack = (unsigned long*) &stack;
WARN_ON(1);
}
- printk("Call Trace: \n");
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- addr = *stack;
+ printk(KERN_INFO "Call Trace: \n");
+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack;
if (__kernel_text_address(addr)) {
- printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
- print_symbol(" %s", addr);
- printk("\n");
- }
- stack++;
- }
- printk("\n");
+ printk(KERN_INFO "%08lx: [<%08lx>]",
+ (unsigned long) stack, addr);
+ print_symbol(KERN_CONT " %s", addr);
+ printk(KERN_CONT "\n");
+ }
+ stack++;
+ }
+ printk(KERN_INFO "\n");
}
#endif
@@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp)
}
stack = esp;
- for(i = 0; i < kstack_depth_to_print; i++) {
+ for (i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(stack))
break;
if (i && ((i % 8) == 0))
- printk("\n ");
+ printk("\n" KERN_INFO " ");
printk("%08lx ", *stack++);
}
- printk("Call Trace: \n");
show_trace(task, esp);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 1ac746a9eae1..e066e84493b1 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/clockchips.h"
-#include "linux/interrupt.h"
-#include "linux/jiffies.h"
-#include "linux/threads.h"
-#include "asm/irq.h"
-#include "asm/param.h"
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+#include <asm/param.h>
#include "kern_util.h"
#include "os.h"
@@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs)
static void itimer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- switch(mode) {
+ switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
set_interval();
break;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f4a0e407eee4..d175d0566af0 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -3,9 +3,10 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/pgtable.h"
-#include "asm/tlbflush.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "as-layout.h"
#include "mem_user.h"
#include "os.h"
@@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
for (i = 0; i < end && !ret; i++) {
op = &hvc->ops[i];
- switch(op->type) {
+ switch (op->type) {
case MMAP:
ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
op->u.mmap.prot, op->u.mmap.fd,
@@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
pte = pte_offset_kernel(pmd, addr);
do {
+ if ((addr >= STUB_START) && (addr < STUB_END))
+ continue;
+
r = pte_read(*pte);
w = pte_write(*pte);
x = pte_exec(*pte);
if (!pte_young(*pte)) {
r = 0;
w = 0;
- } else if (!pte_dirty(*pte)) {
+ } else if (!pte_dirty(*pte))
w = 0;
- }
+
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
if (hvc->force || pte_newpage(*pte)) {
if (pte_present(*pte))
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, prot, hvc);
- else ret = add_munmap(addr, PAGE_SIZE, hvc);
- }
- else if (pte_newprot(*pte))
+ else
+ ret = add_munmap(addr, PAGE_SIZE, hvc);
+ } else if (pte_newprot(*pte))
ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
*pte = pte_mkuptodate(*pte);
- } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
+ } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
return ret;
}
@@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
}
}
else ret = update_pte_range(pmd, addr, next, hvc);
- } while (pmd++, addr = next, ((addr != end) && !ret));
+ } while (pmd++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
}
}
else ret = update_pmd_range(pud, addr, next, hvc);
- } while (pud++, addr = next, ((addr != end) && !ret));
+ } while (pud++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
}
}
else ret = update_pud_range(pgd, addr, next, &hvc);
- } while (pgd++, addr = next, ((addr != end_addr) && !ret));
+ } while (pgd++, addr = next, ((addr < end_addr) && !ret));
if (!ret)
ret = do_ops(&hvc, hvc.index, 1);
@@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
- if (!proc_mm && (end_addr > STUB_START))
- end_addr = STUB_START;
-
fix_range_common(mm, start_addr, end_addr, force);
}
@@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
else fix_range(vma->vm_mm, start, end, 0);
}
-void flush_tlb_mm(struct mm_struct *mm)
+void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
{
- unsigned long end;
-
/*
* Don't bother flushing if this address space is about to be
* destroyed.
@@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm)
if (atomic_read(&mm->mm_users) == 0)
return;
- end = proc_mm ? task_size : STUB_START;
- fix_range(mm, 0, end, 0);
+ fix_range(mm, start, end, 0);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ struct vm_area_struct *vma = mm->mmap;
+
+ while (vma != NULL) {
+ fix_range(mm, vma->vm_start, vma->vm_end, 0);
+ vma = vma->vm_next;
+ }
}
void force_flush_all(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index cb3321f8e0a9..44e490419495 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -13,6 +13,7 @@
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
+#include "skas.h"
#include "sysdep/sigcontext.h"
/*
@@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
force_sig_info(SIGSEGV, &si, current);
}
-static void segv_handler(int sig, struct uml_pt_regs *regs)
+void fatal_sigsegv(void)
+{
+ force_sigsegv(SIGSEGV, current);
+ do_signal();
+ /*
+ * This is to tell gcc that we're not returning - do_signal
+ * can, in general, return, but in this case, it's not, since
+ * we just got a fatal SIGSEGV queued.
+ */
+ os_dump_core();
+}
+
+void segv_handler(int sig, struct uml_pt_regs *regs)
{
struct faultinfo * fi = UPT_FAULTINFO(regs);
@@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
void relay_signal(int sig, struct uml_pt_regs *regs)
{
- if (arch_handle_signal(sig, regs))
- return;
-
if (!UPT_IS_USER(regs)) {
if (sig == SIGBUS)
printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -226,31 +236,24 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
panic("Kernel mode signal %d", sig);
}
+ arch_examine_signal(sig, regs);
+
current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
-static void bus_handler(int sig, struct uml_pt_regs *regs)
+void bus_handler(int sig, struct uml_pt_regs *regs)
{
if (current->thread.fault_catcher != NULL)
UML_LONGJMP(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
-static void winch(int sig, struct uml_pt_regs *regs)
+void winch(int sig, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
}
-const struct kern_handlers handlinfo_kern = {
- .relay_signal = relay_signal,
- .winch = winch,
- .bus_handler = bus_handler,
- .page_fault = segv_handler,
- .sigio_handler = sigio_handler,
- .timer_handler = timer_handler
-};
-
void trap_init(void)
{
}
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index d7436aacd26f..f0f4b040d7c5 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -1,10 +1,11 @@
/*
* Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-/* These are here rather than tt/uaccess.c because skas mode needs them in
+/*
+ * These are here rather than tt/uaccess.c because skas mode needs them in
* order to do SIGBUS recovery when a tmpfs mount runs out of room.
*/
@@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n,
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
- if(!faulted) return(0);
- else return(n - (fault - (unsigned long) to));
+ if (!faulted)
+ return 0;
+ else
+ return n - (fault - (unsigned long) to);
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index f1c71393f578..468aba990dbd 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -3,22 +3,23 @@
* Licensed under the GPL
*/
-#include "linux/delay.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/seq_file.h"
-#include "linux/string.h"
-#include "linux/utsname.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/setup.h"
-#include "arch.h"
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/utsname.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
#include "as-layout.h"
+#include "arch.h"
#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
#include "os.h"
-#include "skas.h"
#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = {
};
/* Set in linux_main */
-unsigned long host_task_size;
-unsigned long task_size;
unsigned long uml_physmem;
unsigned long uml_reserved; /* Also modified in mem_init */
unsigned long start_vm;
@@ -197,20 +196,19 @@ __uml_setup("--help", Usage,
" Prints this message.\n\n"
);
-static int __init uml_checksetup(char *line, int *add)
+static void __init uml_checksetup(char *line, int *add)
{
struct uml_param *p;
p = &__uml_setup_start;
- while(p < &__uml_setup_end) {
+ while (p < &__uml_setup_end) {
int n;
n = strlen(p->str);
if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
- return 1;
+ return;
p++;
}
- return 0;
}
static void __init uml_postsetup(void)
@@ -218,13 +216,30 @@ static void __init uml_postsetup(void)
initcall_t *p;
p = &__uml_postsetup_start;
- while(p < &__uml_postsetup_end) {
+ while (p < &__uml_postsetup_end) {
(*p)();
p++;
}
return;
}
+static int panic_exit(struct notifier_block *self, unsigned long unused1,
+ void *unused2)
+{
+ bust_spinlocks(1);
+ show_regs(&(current->thread.regs));
+ bust_spinlocks(0);
+ uml_exitcode = 1;
+ os_dump_core();
+ return 0;
+}
+
+static struct notifier_block panic_exit_notifier = {
+ .notifier_call = panic_exit,
+ .next = NULL,
+ .priority = 0
+};
+
/* Set during early boot */
unsigned long brk_start;
unsigned long end_iomem;
@@ -234,20 +249,6 @@ EXPORT_SYMBOL(end_iomem);
extern char __binary_start;
-static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
-{
- /* Round up to the nearest 4M */
- unsigned long host_task_size = ROUND_4M((unsigned long)
- &host_task_size);
-
- if (!skas_needs_stub)
- *task_size_out = host_task_size;
- else
- *task_size_out = STUB_START & PGDIR_MASK;
-
- return host_task_size;
-}
-
int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -278,13 +279,6 @@ int __init linux_main(int argc, char **argv)
printf("UML running in %s mode\n", mode);
- host_task_size = set_task_sizes_skas(&task_size);
-
- /*
- * Setting up handlers to 'sig_info' struct
- */
- os_fill_handlinfo(handlinfo_kern);
-
brk_start = (unsigned long) sbrk(0);
/*
@@ -309,7 +303,7 @@ int __init linux_main(int argc, char **argv)
highmem = 0;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
- max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+ max_physmem = CONFIG_TOP_ADDR - uml_physmem - iomem_size - MIN_VMALLOC;
/*
* Zones have to begin on a 1 << MAX_ORDER page boundary,
@@ -341,7 +335,7 @@ int __init linux_main(int argc, char **argv)
}
virtmem_size = physmem_size;
- avail = get_kmem_end() - start_vm;
+ avail = CONFIG_TOP_ADDR - start_vm;
if (physmem_size > avail)
virtmem_size = avail;
end_vm = start_vm + virtmem_size;
@@ -350,6 +344,9 @@ int __init linux_main(int argc, char **argv)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
+
uml_postsetup();
stack_protections((unsigned long) &init_thread_info);
@@ -358,29 +355,8 @@ int __init linux_main(int argc, char **argv)
return start_uml();
}
-extern int uml_exitcode;
-
-static int panic_exit(struct notifier_block *self, unsigned long unused1,
- void *unused2)
-{
- bust_spinlocks(1);
- show_regs(&(current->thread.regs));
- bust_spinlocks(0);
- uml_exitcode = 1;
- os_dump_core();
- return 0;
-}
-
-static struct notifier_block panic_exit_notifier = {
- .notifier_call = panic_exit,
- .next = NULL,
- .priority = 0
-};
-
void __init setup_arch(char **cmdline_p)
{
- atomic_notifier_chain_register(&panic_notifier_list,
- &panic_exit_notifier);
paging_init();
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 039e16efcd55..81e07e2be3ae 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -1,13 +1,12 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "asm/errno.h"
+#include <asm/errno.h>
#include "init.h"
-#include "os.h"
#include "kern.h"
-#include "linux/kernel.h"
+#include "os.h"
/* Changed by set_umid_arg */
static int umid_inited = 0;
@@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add)
{
int err;
- if(umid_inited){
+ if (umid_inited) {
printf("umid already set\n");
return 0;
}
*add = 0;
err = set_umid(name);
- if(err == -EEXIST)
+ if (err == -EEXIST)
printf("umid '%s' already in use\n", name);
- else if(!err)
+ else if (!err)
umid_inited = 1;
return 0;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 8e129af8170d..8a48d6a30064 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,7 +4,7 @@
#
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
- registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
+ registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
- trap.o tty.o tls.o uaccess.o umid.o util.o
+ tty.o tls.o uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 93dc0c80ebaf..b8d8c9ca8d4a 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -12,6 +12,7 @@
#include "aio.h"
#include "init.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 07ca0cb472ac..6fb0b174f538 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -131,7 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
}
if (c != 1) {
printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
- err = helper_wait(pid, 0, "uml_net");
+ err = helper_wait(pid);
}
return err;
}
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 1037a3b6386e..2448be03fd7a 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -14,6 +14,7 @@
#include <sys/wait.h>
#include <sys/uio.h>
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "tuntap.h"
#include "user.h"
@@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
"errno = %d\n", errno);
return err;
}
- helper_wait(pid, 0, "tuntap_open_tramp");
+ helper_wait(pid);
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
@@ -148,7 +149,7 @@ static int tuntap_open(void *data)
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
- if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) {
+ if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
err = -errno;
printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
errno);
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f83462758627..b5afcfd0f861 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,18 +8,16 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
-#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "kern_constants.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
-static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
{
*dst = ((struct uml_stat) {
.ust_dev = src->st_dev, /* device */
@@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
int err;
CATCH_EINTR(err = fstat64(fd, &sbuf));
- if(err < 0)
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
@@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
struct stat64 sbuf;
int err;
- do {
- err = stat64(file_name, &sbuf);
- } while((err < 0) && (errno == EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = stat64(file_name, &sbuf));
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
-int os_access(const char* file, int mode)
+int os_access(const char *file, int mode)
{
int amode, err;
- amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
- (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+ amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
+ (mode & OS_ACC_W_OK ? W_OK : 0) |
+ (mode & OS_ACC_X_OK ? X_OK : 0) |
+ (mode & OS_ACC_F_OK ? F_OK : 0);
err = access(file, amode);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
@@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
int err;
err = ioctl(fd, cmd, arg);
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
@@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
- if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+ if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
return -errno;
return 0;
@@ -108,37 +105,22 @@ int os_set_slip(int fd)
int disc, sencap;
disc = N_SLIP;
- if(ioctl(fd, TIOCSETD, &disc) < 0)
+ if (ioctl(fd, TIOCSETD, &disc) < 0)
return -errno;
sencap = 0;
- if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+ if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
return -errno;
return 0;
}
-int os_set_owner(int fd, int pid)
-{
- if(fcntl(fd, F_SETOWN, pid) < 0){
- int save_errno = errno;
-
- if(fcntl(fd, F_GETOWN, 0) != pid)
- return -save_errno;
- }
-
- return 0;
-}
-
int os_mode_fd(int fd, int mode)
{
int err;
- do {
- err = fchmod(fd, mode);
- } while((err < 0) && (errno==EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = fchmod(fd, mode));
+ if (err < 0)
return -errno;
return 0;
@@ -150,64 +132,73 @@ int os_file_type(char *file)
int err;
err = os_stat_file(file, &buf);
- if(err < 0)
+ if (err < 0)
return err;
- if(S_ISDIR(buf.ust_mode))
+ if (S_ISDIR(buf.ust_mode))
return OS_TYPE_DIR;
- else if(S_ISLNK(buf.ust_mode))
+ else if (S_ISLNK(buf.ust_mode))
return OS_TYPE_SYMLINK;
- else if(S_ISCHR(buf.ust_mode))
+ else if (S_ISCHR(buf.ust_mode))
return OS_TYPE_CHARDEV;
- else if(S_ISBLK(buf.ust_mode))
+ else if (S_ISBLK(buf.ust_mode))
return OS_TYPE_BLOCKDEV;
- else if(S_ISFIFO(buf.ust_mode))
+ else if (S_ISFIFO(buf.ust_mode))
return OS_TYPE_FIFO;
- else if(S_ISSOCK(buf.ust_mode))
+ else if (S_ISSOCK(buf.ust_mode))
return OS_TYPE_SOCK;
else return OS_TYPE_FILE;
}
-int os_file_mode(char *file, struct openflags *mode_out)
+int os_file_mode(const char *file, struct openflags *mode_out)
{
int err;
*mode_out = OPENFLAGS();
err = access(file, W_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_write(*mode_out);
err = access(file, R_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_read(*mode_out);
return err;
}
-int os_open_file(char *file, struct openflags flags, int mode)
+int os_open_file(const char *file, struct openflags flags, int mode)
{
int fd, err, f = 0;
- if(flags.r && flags.w) f = O_RDWR;
- else if(flags.r) f = O_RDONLY;
- else if(flags.w) f = O_WRONLY;
+ if (flags.r && flags.w)
+ f = O_RDWR;
+ else if (flags.r)
+ f = O_RDONLY;
+ else if (flags.w)
+ f = O_WRONLY;
else f = 0;
- if(flags.s) f |= O_SYNC;
- if(flags.c) f |= O_CREAT;
- if(flags.t) f |= O_TRUNC;
- if(flags.e) f |= O_EXCL;
+ if (flags.s)
+ f |= O_SYNC;
+ if (flags.c)
+ f |= O_CREAT;
+ if (flags.t)
+ f |= O_TRUNC;
+ if (flags.e)
+ f |= O_EXCL;
+ if (flags.a)
+ f |= O_APPEND;
fd = open64(file, f, mode);
- if(fd < 0)
+ if (fd < 0)
return -errno;
- if(flags.cl && fcntl(fd, F_SETFD, 1)){
+ if (flags.cl && fcntl(fd, F_SETFD, 1)) {
err = -errno;
close(fd);
return err;
@@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode)
return fd;
}
-int os_connect_socket(char *name)
+int os_connect_socket(const char *name)
{
struct sockaddr_un sock;
int fd, err;
@@ -225,13 +216,13 @@ int os_connect_socket(char *name)
snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
goto out;
}
err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
- if(err) {
+ if (err) {
err = -errno;
goto out_close;
}
@@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset)
unsigned long long actual;
actual = lseek64(fd, offset, SEEK_SET);
- if(actual != offset)
+ if (actual != offset)
return -errno;
return 0;
}
@@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len)
{
int n = read(fd, buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
@@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len)
{
int n = write(fd, (void *) buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
-int os_file_size(char *file, unsigned long long *size_out)
+int os_file_size(const char *file, unsigned long long *size_out)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
- if(S_ISBLK(buf.ust_mode)){
+ if (S_ISBLK(buf.ust_mode)) {
int fd;
long blocks;
fd = open(file, O_RDONLY, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
- printk("Couldn't open \"%s\", errno = %d\n", file,
- errno);
+ printk(UM_KERN_ERR "Couldn't open \"%s\", "
+ "errno = %d\n", file, errno);
return err;
}
- if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
+ if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
err = -errno;
- printk("Couldn't get the block size of \"%s\", "
- "errno = %d\n", file, errno);
+ printk(UM_KERN_ERR "Couldn't get the block size of "
+ "\"%s\", errno = %d\n", file, errno);
close(fd);
return err;
}
@@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out)
return 0;
}
-int os_file_modtime(char *file, unsigned long *modtime)
+int os_file_modtime(const char *file, unsigned long *modtime)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
@@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime)
return 0;
}
-int os_get_exec_close(int fd, int *close_on_exec)
-{
- int ret;
-
- CATCH_EINTR(ret = fcntl(fd, F_GETFD));
-
- if(ret < 0)
- return -errno;
-
- *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
- return ret;
-}
-
int os_set_exec_close(int fd)
{
int err;
CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
}
@@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
err = socketpair(AF_UNIX, type, 0, fds);
- if(err < 0)
+ if (err < 0)
return -errno;
- if(!close_on_exec)
+ if (!close_on_exec)
return 0;
err = os_set_exec_close(fds[0]);
- if(err < 0)
+ if (err < 0)
goto error;
err = os_set_exec_close(fds[1]);
- if(err < 0)
+ if (err < 0)
goto error;
return 0;
error:
- printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+ printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
+ -err);
close(fds[1]);
close(fds[0]);
return err;
}
-int os_set_fd_async(int fd, int owner)
+int os_set_fd_async(int fd)
{
- int err;
+ int err, flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- /* XXX This should do F_GETFL first */
- if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
+ flags |= O_ASYNC | O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) < 0) {
err = -errno;
- printk("os_set_fd_async : failed to set O_ASYNC and "
- "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
+ "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
return err;
}
-#ifdef notdef
- if(fcntl(fd, F_SETFD, 1) < 0){
- printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
- "errno = %d\n", errno);
- }
-#endif
- if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
- (fcntl(fd, F_SETOWN, owner) < 0)){
+ if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
+ (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
err = -errno;
- printk("os_set_fd_async : Failed to fcntl F_SETOWN "
- "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
- owner, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
+ "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
return err;
}
@@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner)
int os_clear_fd_async(int fd)
{
- int flags = fcntl(fd, F_GETFL);
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
flags &= ~(O_ASYNC | O_NONBLOCK);
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
}
@@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking)
int flags;
flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- if(blocking) flags &= ~O_NONBLOCK;
- else flags |= O_NONBLOCK;
+ if (blocking)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
@@ -441,7 +427,7 @@ int os_accept_connection(int fd)
int new;
new = accept(fd, NULL, 0);
- if(new < 0)
+ if (new < 0)
return -errno;
return new;
}
@@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w)
{
int what, err;
- if(r && w) what = SHUT_RDWR;
- else if(r) what = SHUT_RD;
- else if(w) what = SHUT_WR;
- else {
- printk("os_shutdown_socket : neither r or w was set\n");
+ if (r && w)
+ what = SHUT_RDWR;
+ else if (r)
+ what = SHUT_RD;
+ else if (w)
+ what = SHUT_WR;
+ else
return -EINVAL;
- }
+
err = shutdown(fd, what);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
}
@@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out)
msg.msg_flags = 0;
n = recvmsg(fd, &msg, 0);
- if(n < 0)
+ if (n < 0)
return -errno;
- else if(n != iov.iov_len)
+ else if (n != iov.iov_len)
*helper_pid_out = -1;
cmsg = CMSG_FIRSTHDR(&msg);
- if(cmsg == NULL){
- printk("rcv_fd didn't receive anything, error = %d\n", errno);
+ if (cmsg == NULL) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
+ "error = %d\n", errno);
return -1;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
- (cmsg->cmsg_type != SCM_RIGHTS)){
- printk("rcv_fd didn't receive a descriptor\n");
+ if ((cmsg->cmsg_level != SOL_SOCKET) ||
+ (cmsg->cmsg_type != SCM_RIGHTS)) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
return -1;
}
@@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out)
return new;
}
-int os_create_unix_socket(char *file, int len, int close_on_exec)
+int os_create_unix_socket(const char *file, int len, int close_on_exec)
{
struct sockaddr_un addr;
int sock, err;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if(sock < 0)
+ if (sock < 0)
return -errno;
- if(close_on_exec) {
+ if (close_on_exec) {
err = os_set_exec_close(sock);
- if(err < 0)
- printk("create_unix_socket : close_on_exec failed, "
- "err = %d", -err);
+ if (err < 0)
+ printk(UM_KERN_ERR "create_unix_socket : "
+ "close_on_exec failed, err = %d", -err);
}
addr.sun_family = AF_UNIX;
- /* XXX Be more careful about overflow */
snprintf(addr.sun_path, len, "%s", file);
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
- if(err < 0)
+ if (err < 0)
return -errno;
return sock;
@@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl)
int err, save;
err = fcntl(fd, F_SETLK, &lock);
- if(!err)
+ if (!err)
goto out;
save = -errno;
err = fcntl(fd, F_GETLK, &lock);
- if(err){
+ if (err) {
err = -errno;
goto out;
}
- printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+ printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
+ lock.l_pid);
err = save;
out:
return err;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index fba3f0fefeef..f4bd349d4412 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -1,22 +1,19 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
-#include <limits.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
#include <sys/socket.h>
-#include "user.h"
+#include <sys/wait.h>
+#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
struct helper_data {
void (*pre_exec)(void*);
@@ -30,21 +27,19 @@ static int helper_child(void *arg)
{
struct helper_data *data = arg;
char **argv = data->argv;
- int errval;
+ int err;
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
- errval = execvp_noalloc(data->buf, argv[0], argv);
- printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
- -errval);
- write(data->fd, &errval, sizeof(errval));
- kill(os_getpid(), SIGKILL);
+ err = execvp_noalloc(data->buf, argv[0], argv);
+
+ /* If the exec succeeds, we don't get here */
+ write(data->fd, &err, sizeof(err));
+
return 0;
}
-/* Returns either the pid of the child process we run or -E* on failure.
- * XXX The alloc_stack here breaks if this is called in the tracing thread, so
- * we need to receive a preallocated stack (a local buffer is ok). */
+/* Returns either the pid of the child process we run or -E* on failure. */
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
{
struct helper_data data;
@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (ret < 0) {
ret = -errno;
- printk("run_helper : pipe failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n",
+ errno);
goto out_free;
}
ret = os_set_exec_close(fds[1]);
if (ret < 0) {
- printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
- -ret);
+ printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, "
+ "ret = %d\n", -ret);
goto out_close;
}
@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
if (pid < 0) {
ret = -errno;
- printk("run_helper : clone failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n",
+ errno);
goto out_free2;
}
@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
} else {
if (n < 0) {
n = -errno;
- printk("run_helper : read on pipe failed, ret = %d\n",
- -n);
+ printk(UM_KERN_ERR "run_helper : read on pipe failed, "
+ "ret = %d\n", -n);
ret = n;
- kill(pid, SIGKILL);
}
CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
}
@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
pid = clone(proc, (void *) sp, flags, arg);
if (pid < 0) {
err = -errno;
- printk("run_helper_thread : clone failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread : clone failed, "
+ "errno = %d\n", errno);
return err;
}
if (stack_out == NULL) {
CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
if (pid < 0) {
err = -errno;
- printk("run_helper_thread - wait failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread - wait failed, "
+ "errno = %d\n", errno);
pid = err;
}
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- printk("run_helper_thread - thread returned status "
- "0x%x\n", status);
+ printk(UM_KERN_ERR "run_helper_thread - thread "
+ "returned status 0x%x\n", status);
free_stack(stack, 0);
} else
*stack_out = stack;
return pid;
}
-int helper_wait(int pid, int nohang, char *pname)
+int helper_wait(int pid)
{
int ret, status;
int wflags = __WCLONE;
- if (nohang)
- wflags |= WNOHANG;
-
- if (!pname)
- pname = "helper_wait";
-
CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
- printk(UM_KERN_ERR "%s : waitpid process %d failed, "
- "errno = %d\n", pname, pid, errno);
+ printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, "
+ "errno = %d\n", pid, errno);
return -errno;
- } else if (nohang && ret == 0) {
- printk(UM_KERN_ERR "%s : process %d has not exited\n",
- pname, pid);
- return -ECHILD;
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- printk(UM_KERN_ERR "%s : process %d didn't exit with "
- "status 0\n", pname, pid);
+ printk(UM_KERN_ERR "helper_wait : process %d exited with "
+ "status 0x%x\n", pid, status);
return -ECHILD;
} else
return 0;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 6aa6f95d6524..0348b975e81c 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -1,23 +1,19 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
+#include <poll.h>
#include <signal.h>
#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
#include "irq_user.h"
+#include "kern_constants.h"
#include "os.h"
+#include "process.h"
#include "um_malloc.h"
+#include "user.h"
/*
* Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd
@@ -36,7 +32,7 @@ int os_waiting_for_events(struct irq_fd *active_fds)
if (n < 0) {
err = -errno;
if (errno != EINTR)
- printk("sigio_handler: os_waiting_for_events:"
+ printk(UM_KERN_ERR "os_waiting_for_events:"
" poll returned %d, errno = %d\n", n, errno);
return err;
}
@@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
struct irq_fd *old_fd = *prev;
if ((pollfds[i].fd != -1) &&
(pollfds[i].fd != (*prev)->fd)) {
- printk("os_free_irq_by_cb - mismatch between "
- "active_fds and pollfds, fd %d vs %d\n",
+ printk(UM_KERN_ERR "os_free_irq_by_cb - "
+ "mismatch between active_fds and "
+ "pollfds, fd %d vs %d\n",
(*prev)->fd, pollfds[i].fd);
goto out;
}
pollfds_num--;
- /* This moves the *whole* array after pollfds[i]
+ /*
+ * This moves the *whole* array after pollfds[i]
* (though it doesn't spot as such)!
*/
memmove(&pollfds[i], &pollfds[i + 1],
(pollfds_num - i) * sizeof(pollfds[0]));
- if(*last_irq_ptr2 == &old_fd->next)
+ if (*last_irq_ptr2 == &old_fd->next)
*last_irq_ptr2 = prev;
*prev = (*prev)->next;
- if(old_fd->type == IRQ_WRITE)
+ if (old_fd->type == IRQ_WRITE)
ignore_sigio_fd(old_fd->fd);
kfree(old_fd);
continue;
@@ -138,14 +136,3 @@ void os_set_ioignore(void)
{
signal(SIGIO, SIG_IGN);
}
-
-void init_irq_signals(int on_sigstack)
-{
- int flags;
-
- flags = on_sigstack ? SA_ONSTACK : 0;
-
- set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- signal(SIGWINCH, SIG_IGN);
-}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 82c3778627b8..abb9b0ffd960 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -73,7 +73,7 @@ static void install_fatal_handler(int sig)
action.sa_handler = last_ditch_exit;
if (sigaction(sig, &action, NULL) < 0) {
printf("failed to install handler for signal %d - errno = %d\n",
- errno);
+ sig, errno);
exit(1);
}
}
@@ -92,7 +92,8 @@ static void setup_env_path(void)
* just use the default + /usr/lib/uml
*/
if (!old_path || (path_len = strlen(old_path)) == 0) {
- putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+ if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH))
+ perror("couldn't putenv");
return;
}
@@ -100,15 +101,16 @@ static void setup_env_path(void)
path_len += strlen("PATH=" UML_LIB_PATH) + 1;
new_path = malloc(path_len);
if (!new_path) {
- perror("coudn't malloc to set a new PATH");
+ perror("couldn't malloc to set a new PATH");
return;
}
snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
- putenv(new_path);
+ if (putenv(new_path)) {
+ perror("couldn't putenv to set a new PATH");
+ free(new_path);
+ }
}
-extern int uml_exitcode;
-
extern void scan_elf_aux( char **envp);
int __init main(int argc, char **argv, char **envp)
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 436f8d20b20f..eedc2d88ef8a 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -9,7 +9,6 @@
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/statfs.h>
-#include "kern_util.h"
#include "user.h"
#include "mem_user.h"
#include "init.h"
@@ -30,7 +29,7 @@ static char *tempdir = NULL;
static void __init find_tempdir(void)
{
- char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+ const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
int i;
char *dir = NULL;
@@ -59,9 +58,10 @@ static void __init find_tempdir(void)
* read the file as needed. If there's an error, -errno is returned;
* if the end of the file is reached, 0 is returned.
*/
-static int next(int fd, char *buf, int size, char c)
+static int next(int fd, char *buf, size_t size, char c)
{
- int n, len;
+ ssize_t n;
+ size_t len;
char *ptr;
while((ptr = strchr(buf, c)) == NULL){
@@ -172,13 +172,15 @@ int __init make_tempfile(const char *template, char **out_tempname,
which_tmpdir();
tempname = malloc(MAXPATHLEN);
+ if (!tempname)
+ goto out;
find_tempdir();
if (template[0] != '/')
strcpy(tempname, tempdir);
else
tempname[0] = '\0';
- strcat(tempname, template);
+ strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
@@ -268,6 +270,7 @@ void __init check_tmpexec(void)
if(addr == MAP_FAILED){
err = errno;
perror("failed");
+ close(fd);
if(err == EPERM)
printf("%s must be not mounted noexec\n",tempdir);
exit(1);
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index bda5c3150d6c..abf6beae3df1 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -249,7 +249,10 @@ void init_new_thread_signals(void)
SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(1);
+ set_handler(SIGIO, (__sighandler_t) sig_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
+ SIGVTALRM, -1);
+ signal(SIGWINCH, SIG_IGN);
}
int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index a32ba6ab1211..830fe6a1518a 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -8,47 +8,41 @@
#include <string.h>
#include <sys/ptrace.h>
#include "sysdep/ptrace.h"
-#include "user.h"
-/* This is set once at boot time and not changed thereafter */
-
-static unsigned long exec_regs[MAX_REG_NR];
-
-void init_thread_registers(struct uml_pt_regs *to)
-{
- memcpy(to->gp, exec_regs, sizeof(to->gp));
-}
-
-void save_registers(int pid, struct uml_pt_regs *regs)
+int save_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("save_registers - saving registers failed, errno = %d\n",
- errno);
+ return -errno;
+ return 0;
}
-void restore_registers(int pid, struct uml_pt_regs *regs)
+int restore_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", errno);
+ return -errno;
+ return 0;
}
-void init_registers(int pid)
+/* This is set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[MAX_REG_NR];
+
+int init_registers(int pid)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
- if (err)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
+ if (err < 0)
+ return -errno;
arch_init_registers(pid);
+ return 0;
}
void get_safe_registers(unsigned long *regs)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index dc03e9cccb63..abf47a7c4abd 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,34 +1,33 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <unistd.h>
-#include <stdlib.h>
-#include <termios.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
#include <pty.h>
+#include <sched.h>
#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
#include <string.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include "init.h"
-#include "user.h"
+#include "kern_constants.h"
#include "kern_util.h"
-#include "sigio.h"
+#include "init.h"
#include "os.h"
+#include "sigio.h"
#include "um_malloc.h"
-#include "init.h"
+#include "user.h"
-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
+/*
+ * Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1;
static unsigned long write_sigio_stack;
-/* These arrays are initialized before the sigio thread is started, and
+/*
+ * These arrays are initialized before the sigio thread is started, and
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
@@ -43,7 +42,8 @@ struct pollfds {
int used;
};
-/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
+/*
+ * Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
static struct pollfds current_poll;
@@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
- signal(SIGWINCH, SIG_IGN);
+ signal(SIGWINCH, SIG_IGN);
fds = &current_poll;
- while(1){
+ while (1) {
n = poll(fds->poll, fds->used, -1);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("write_sigio_thread : poll returned %d, "
- "errno = %d\n", n, errno);
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+ printk(UM_KERN_ERR "write_sigio_thread : poll returned "
+ "%d, errno = %d\n", n, errno);
}
- for(i = 0; i < fds->used; i++){
+ for (i = 0; i < fds->used; i++) {
p = &fds->poll[i];
- if(p->revents == 0) continue;
- if(p->fd == sigio_private[1]){
+ if (p->revents == 0)
+ continue;
+ if (p->fd == sigio_private[1]) {
CATCH_EINTR(n = read(sigio_private[1], &c,
sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : "
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR
+ "write_sigio_thread : "
"read on socket failed, "
"err = %d\n", errno);
tmp = current_poll;
@@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused)
}
CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : write on socket "
- "failed, err = %d\n", errno);
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR "write_sigio_thread : "
+ "write on socket failed, err = %d\n",
+ errno);
}
}
@@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n)
{
struct pollfd *new;
- if(n <= polls->size)
+ if (n <= polls->size)
return 0;
new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
- if(new == NULL){
- printk("need_poll : failed to allocate new pollfds\n");
+ if (new == NULL) {
+ printk(UM_KERN_ERR "need_poll : failed to allocate new "
+ "pollfds\n");
return -ENOMEM;
}
@@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n)
return 0;
}
-/* Must be called with sigio_lock held, because it's needed by the marked
+/*
+ * Must be called with sigio_lock held, because it's needed by the marked
* critical section.
*/
static void update_thread(void)
@@ -129,15 +135,17 @@ static void update_thread(void)
char c;
flags = set_signals(0);
- n = write(sigio_private[0], &c, sizeof(c));
- if(n != sizeof(c)){
- printk("update_thread : write failed, err = %d\n", errno);
+ CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
+ errno);
goto fail;
}
CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
- if(n != sizeof(c)){
- printk("update_thread : read failed, err = %d\n", errno);
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
+ errno);
goto fail;
}
@@ -164,23 +172,23 @@ int add_sigio_fd(int fd)
int err = 0, i, n;
sigio_lock();
- for(i = 0; i < all_sigio_fds.used; i++){
- if(all_sigio_fds.poll[i].fd == fd)
+ for (i = 0; i < all_sigio_fds.used; i++) {
+ if (all_sigio_fds.poll[i].fd == fd)
break;
}
- if(i == all_sigio_fds.used)
+ if (i == all_sigio_fds.used)
goto out;
p = &all_sigio_fds.poll[i];
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd)
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used;
err = need_poll(&next_poll, n + 1);
- if(err)
+ if (err)
goto out;
memcpy(next_poll.poll, current_poll.poll,
@@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd)
struct pollfd *p;
int err = 0, i, n = 0;
- /* This is called from exitcalls elsewhere in UML - if
+ /*
+ * This is called from exitcalls elsewhere in UML - if
* sigio_cleanup has already run, then update_thread will hang
* or fail because the thread is no longer running.
*/
- if(write_sigio_pid == -1)
+ if (write_sigio_pid == -1)
return -EIO;
sigio_lock();
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd) break;
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
+ break;
}
- if(i == current_poll.used)
+ if (i == current_poll.used)
goto out;
err = need_poll(&next_poll, current_poll.used - 1);
- if(err)
+ if (err)
goto out;
- for(i = 0; i < current_poll.used; i++){
+ for (i = 0; i < current_poll.used; i++) {
p = &current_poll.poll[i];
- if(p->fd != fd)
+ if (p->fd != fd)
next_poll.poll[n++] = *p;
}
next_poll.used = current_poll.used - 1;
@@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd)
p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
if (p == NULL) {
- printk("setup_initial_poll : failed to allocate poll\n");
+ printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
+ "poll\n");
return NULL;
}
*p = ((struct pollfd) { .fd = fd,
@@ -261,27 +272,29 @@ static void write_sigio_workaround(void)
return;
err = os_pipe(l_write_sigio_fds, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 1 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
"err = %d\n", -err);
return;
}
err = os_pipe(l_sigio_private, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 2 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
"err = %d\n", -err);
goto out_close1;
}
p = setup_initial_poll(l_sigio_private[1]);
- if(!p)
+ if (!p)
goto out_close2;
sigio_lock();
- /* Did we race? Don't try to optimize this, please, it's not so likely
- * to happen, and no more than once at the boot. */
- if(write_sigio_pid != -1)
+ /*
+ * Did we race? Don't try to optimize this, please, it's not so likely
+ * to happen, and no more than once at the boot.
+ */
+ if (write_sigio_pid != -1)
goto out_free;
current_poll = ((struct pollfds) { .poll = p,
@@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read)
{
int err;
- if(!isatty(fd))
+ if (!isatty(fd))
return;
- if((read || pty_output_sigio) && (!read || pty_close_sigio))
+ if ((read || pty_output_sigio) && (!read || pty_close_sigio))
return;
write_sigio_workaround();
sigio_lock();
err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
- if(err){
- printk("maybe_sigio_broken - failed to add pollfd for "
- "descriptor %d\n", fd);
+ if (err) {
+ printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
+ "for descriptor %d\n", fd);
goto out;
}
@@ -388,7 +401,7 @@ static void openpty_cb(void *arg)
struct openpty_arg *info = arg;
info->err = 0;
- if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
info->err = -errno;
}
@@ -397,17 +410,17 @@ static int async_pty(int master, int slave)
int flags;
flags = fcntl(master, F_GETFL);
- if(flags < 0)
+ if (flags < 0)
return -errno;
- if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
- (fcntl(master, F_SETOWN, os_getpid()) < 0))
+ if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+ (fcntl(master, F_SETOWN, os_getpid()) < 0))
return -errno;
- if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+ if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
return -errno;
- return(0);
+ return 0;
}
static void __init check_one_sigio(void (*proc)(int, int))
@@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int))
int master, slave, err;
initial_thread_cb(openpty_cb, &pty);
- if(pty.err){
- printk("openpty failed, errno = %d\n", -pty.err);
+ if (pty.err) {
+ printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
+ -pty.err);
return;
}
master = pty.master;
slave = pty.slave;
- if((master == -1) || (slave == -1)){
- printk("openpty failed to allocate a pty\n");
+ if ((master == -1) || (slave == -1)) {
+ printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
+ "pty\n");
return;
}
/* Not now, but complain so we now where we failed. */
err = raw(master);
- if (err < 0)
- panic("check_sigio : __raw failed, errno = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
+ -err);
+ return;
+ }
err = async_pty(master, slave);
- if(err < 0)
- panic("tty_fds : sigio_async failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
+ "err = %d\n", -err);
+ return;
+ }
+
+ if (sigaction(SIGIO, NULL, &old) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
- if(sigaction(SIGIO, NULL, &old) < 0)
- panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
new = old;
new.sa_handler = handler;
- if(sigaction(SIGIO, &new, NULL) < 0)
- panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &new, NULL) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
got_sigio = 0;
(*proc)(master, slave);
@@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int))
close(master);
close(slave);
- if(sigaction(SIGIO, &old, NULL) < 0)
- panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &old, NULL) < 0)
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
+ "errno = %d\n", errno);
}
static void tty_output(int master, int slave)
@@ -461,42 +490,45 @@ static void tty_output(int master, int slave)
int n;
char buf[512];
- printk("Checking that host ptys support output SIGIO...");
+ printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
memset(buf, 0, sizeof(buf));
- while(write(master, buf, sizeof(buf)) > 0) ;
- if(errno != EAGAIN)
- panic("tty_output : write failed, errno = %d\n", errno);
- while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+ while (write(master, buf, sizeof(buf)) > 0) ;
+ if (errno != EAGAIN)
+ printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
+ errno);
+ while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
+ ;
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_output_sigio = 1;
- }
- else if(n == -EAGAIN)
- printk("No, enabling workaround\n");
- else panic("tty_output : read failed, err = %d\n", n);
+ } else if (n == -EAGAIN)
+ printk(UM_KERN_CONT "No, enabling workaround\n");
+ else
+ printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
{
- printk("Checking that host ptys support SIGIO on close...");
+ printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
+ "close...");
close(slave);
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_close_sigio = 1;
- }
- else printk("No, enabling workaround\n");
+ } else
+ printk(UM_KERN_CONT "No, enabling workaround\n");
}
void __init check_sigio(void)
{
- if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
- (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
- printk("No pseudo-terminals available - skipping pty SIGIO "
- "check\n");
+ if ((access("/dev/ptmx", R_OK) < 0) &&
+ (access("/dev/ptyp0", R_OK) < 0)) {
+ printk(UM_KERN_WARNING "No pseudo-terminals available - "
+ "skipping pty SIGIO check\n");
return;
}
check_one_sigio(tty_output);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index e9800b0b5689..0fb0cc8d4757 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -9,11 +9,47 @@
#include <errno.h>
#include <signal.h>
#include <strings.h>
+#include "as-layout.h"
+#include "kern_util.h"
#include "os.h"
#include "sysdep/barrier.h"
#include "sysdep/sigcontext.h"
#include "user.h"
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
+ [SIGTRAP] = relay_signal,
+ [SIGFPE] = relay_signal,
+ [SIGILL] = relay_signal,
+ [SIGWINCH] = winch,
+ [SIGBUS] = bus_handler,
+ [SIGSEGV] = segv_handler,
+ [SIGIO] = sigio_handler,
+ [SIGVTALRM] = timer_handler };
+
+static void sig_handler_common(int sig, struct sigcontext *sc)
+{
+ struct uml_pt_regs r;
+ int save_errno = errno;
+
+ r.is_user = 0;
+ if (sig == SIGSEGV) {
+ /* For segfaults, we want the data from the sigcontext. */
+ copy_sc(&r, sc);
+ GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+ }
+
+ /* enable signals if sig isn't IRQ signal */
+ if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
+ unblock_signals();
+
+ (*sig_info[sig])(sig, &r);
+
+ errno = save_errno;
+}
+
/*
* These are the asynchronous signals. SIGPROF is excluded because we want to
* be able to profile all of UML, not just the non-critical sections. If
@@ -26,13 +62,8 @@
#define SIGVTALRM_BIT 1
#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
-/*
- * These are used by both the signal handlers and
- * block/unblock_signals. I don't want modifications cached in a
- * register - they must go straight to memory.
- */
-static volatile int signals_enabled = 1;
-static volatile int pending = 0;
+static int signals_enabled;
+static unsigned int signals_pending;
void sig_handler(int sig, struct sigcontext *sc)
{
@@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!enabled && (sig == SIGIO)) {
- pending |= SIGIO_MASK;
+ signals_pending |= SIGIO_MASK;
return;
}
block_signals();
- sig_handler_common_skas(sig, sc);
+ sig_handler_common(sig, sc);
set_signals(enabled);
}
@@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!signals_enabled) {
- pending |= SIGVTALRM_MASK;
+ signals_pending |= SIGVTALRM_MASK;
return;
}
@@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
-void remove_sigstack(void)
-{
- stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
- .ss_sp = NULL,
- .ss_size = 0 });
-
- if (sigaltstack(&stack, NULL) != 0)
- panic("disabling signal stack failed, errno = %d\n", errno);
-}
-
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
void handle_signal(int sig, struct sigcontext *sc)
@@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigaddset(&action.sa_mask, mask);
va_end(ap);
+ if (sig == SIGSEGV)
+ flags |= SA_NODEFER;
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if (sigaction(sig, &action, NULL) < 0)
@@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
int change_sig(int signal, int on)
{
- sigset_t sigset, old;
+ sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, signal);
- sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
- return !sigismember(&old, signal);
+ if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
+ return -errno;
+
+ return 0;
}
void block_signals(void)
@@ -196,7 +222,7 @@ void block_signals(void)
* This might matter if gcc figures out how to inline this and
* decides to shuffle this code into the caller.
*/
- mb();
+ barrier();
}
void unblock_signals(void)
@@ -209,36 +235,26 @@ void unblock_signals(void)
/*
* We loop because the IRQ handler returns with interrupts off. So,
* interrupts may have arrived and we need to re-enable them and
- * recheck pending.
+ * recheck signals_pending.
*/
while(1) {
/*
* Save and reset save_pending after enabling signals. This
- * way, pending won't be changed while we're reading it.
+ * way, signals_pending won't be changed while we're reading it.
*/
signals_enabled = 1;
/*
- * Setting signals_enabled and reading pending must
+ * Setting signals_enabled and reading signals_pending must
* happen in this order.
*/
- mb();
-
- save_pending = pending;
- if (save_pending == 0) {
- /*
- * This must return with signals enabled, so
- * this barrier ensures that writes are
- * flushed out before the return. This might
- * matter if gcc figures out how to inline
- * this (unlikely, given its size) and decides
- * to shuffle this code into the caller.
- */
- mb();
+ barrier();
+
+ save_pending = signals_pending;
+ if (save_pending == 0)
return;
- }
- pending = 0;
+ signals_pending = 0;
/*
* We have pending interrupts, so disable signals, as the
@@ -254,7 +270,7 @@ void unblock_signals(void)
* back here.
*/
if (save_pending & SIGIO_MASK)
- sig_handler_common_skas(SIGIO, NULL);
+ sig_handler_common(SIGIO, NULL);
if (save_pending & SIGVTALRM_MASK)
real_alarm_handler(NULL);
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index 5fd8d4dad66a..d2ea3409e072 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -1,10 +1,10 @@
#
-# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
# Licensed under the GPL
#
-obj-y := mem.o process.o trap.o
+obj-y := mem.o process.o
-USER_OBJS := mem.o process.o trap.o
+USER_OBJS := $(obj-y)
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index e8b7a97e83d3..d36c89c24a45 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -15,6 +15,7 @@
#include "as-layout.h"
#include "chan_user.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "mem.h"
#include "os.h"
#include "process.h"
@@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data)
static int ptrace_dump_regs(int pid)
{
- unsigned long regs[MAX_REG_NR];
- int i;
+ unsigned long regs[MAX_REG_NR];
+ int i;
- if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
- return -errno;
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ return -errno;
printk(UM_KERN_ERR "Stub registers -\n");
for (i = 0; i < ARRAY_SIZE(regs); i++)
printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
- return 0;
+ return 0;
}
/*
* Signals that are OK to receive in the stub - we'll just continue it.
* SIGWINCH will happen when UML is inside a detached screen.
*/
-#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
+#define STUB_SIG_MASK (1 << SIGVTALRM)
/* Signals that the stub will finish with - anything else is an error */
-#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
+#define STUB_DONE_MASK (1 << SIGTRAP)
void wait_stub_done(int pid)
{
@@ -72,9 +73,11 @@ void wait_stub_done(int pid)
break;
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("wait_stub_done : continue failed, errno = %d\n",
- errno);
+ if (err) {
+ printk(UM_KERN_ERR "wait_stub_done : continue failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
@@ -85,8 +88,10 @@ bad_wait:
if (err)
printk(UM_KERN_ERR "Failed to get registers from stub, "
"errno = %d\n", -err);
- panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
- "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
+ printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
+ "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
+ status);
+ fatal_sigsegv();
}
extern unsigned long current_stub_stack(void);
@@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
if (ptrace_faultinfo) {
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
- if (err)
- panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "get_skas_faultinfo - "
+ "PTRACE_FAULTINFO failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
/* Special handling for i386, which has different structs */
if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
@@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
}
else {
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
- if (err)
- panic("Failed to continue stub, pid = %d, errno = %d\n",
- pid, errno);
+ if (err) {
+ printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
+ "errno = %d\n", pid, errno);
+ fatal_sigsegv();
+ }
wait_stub_done(pid);
/*
@@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
int err, status;
+ if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
+ fatal_sigsegv();
+
/* Mark this as a syscall */
UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
@@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid);
- if (err < 0)
- panic("handle_trap - nullifying syscall failed, "
- "errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - nullifying syscall "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
- if (err < 0)
- panic("handle_trap - continuing to end of syscall "
- "failed, errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - continuing to end of "
+ "syscall failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
if ((err < 0) || !WIFSTOPPED(status) ||
- (WSTOPSIG(status) != SIGTRAP + 0x80)) {
- err = ptrace_dump_regs(pid);
- if (err)
- printk(UM_KERN_ERR "Failed to get registers "
+ (WSTOPSIG(status) != SIGTRAP + 0x80)) {
+ err = ptrace_dump_regs(pid);
+ if (err)
+ printk(UM_KERN_ERR "Failed to get registers "
"from process, errno = %d\n", -err);
- panic("handle_trap - failed to wait at end of syscall, "
- "errno = %d, status = %d\n", errno, status);
- }
+ printk(UM_KERN_ERR "handle_trap - failed to wait at "
+ "end of syscall, errno = %d, status = %d\n",
+ errno, status);
+ fatal_sigsegv();
+ }
}
handle_syscall(regs);
@@ -178,10 +196,13 @@ static int userspace_tramp(void *stack)
ptrace(PTRACE_TRACEME, 0, 0, 0);
signal(SIGTERM, SIG_DFL);
+ signal(SIGWINCH, SIG_IGN);
err = set_interval();
- if (err)
- panic("userspace_tramp - setting timer failed, errno = %d\n",
- err);
+ if (err) {
+ printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
+ "errno = %d\n", err);
+ exit(1);
+ }
if (!proc_mm) {
/*
@@ -221,16 +242,14 @@ static int userspace_tramp(void *stack)
set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGIO);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sigaddset(&sa.sa_mask, SIGVTALRM);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sa.sa_flags = SA_ONSTACK;
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER;
sa.sa_handler = (void *) v;
sa.sa_restorer = NULL;
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- panic("userspace_tramp - setting SIGSEGV handler "
- "failed - errno = %d\n", errno);
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
+ "handler failed - errno = %d\n", errno);
+ exit(1);
+ }
}
kill(os_getpid(), SIGSTOP);
@@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack)
{
void *stack;
unsigned long sp;
- int pid, status, n, flags;
+ int pid, status, n, flags, err;
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (stack == MAP_FAILED)
- panic("start_userspace : mmap failed, errno = %d", errno);
+ if (stack == MAP_FAILED) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : mmap failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
+
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES;
@@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack)
flags |= SIGCHLD;
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
- if (pid < 0)
- panic("start_userspace : clone failed, errno = %d", errno);
+ if (pid < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : clone failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
do {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
- if (n < 0)
- panic("start_userspace : wait failed, errno = %d",
- errno);
+ if (n < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : wait failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
- if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
- panic("start_userspace : expected SIGSTOP, got status = %d",
- status);
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
+ err = -EINVAL;
+ printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
+ "status = %d\n", status);
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *) PTRACE_O_TRACESYSGOOD) < 0)
- panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *) PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
- if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
- panic("start_userspace : munmap failed, errno = %d\n", errno);
+ if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : munmap failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
void userspace(struct uml_pt_regs *regs)
@@ -302,7 +347,16 @@ void userspace(struct uml_pt_regs *regs)
nsecs += os_nsecs();
while (1) {
- restore_registers(pid, regs);
+ /*
+ * This can legitimately fail if the process loads a
+ * bogus value into a segment register. It will
+ * segfault and PTRACE_GETREGS will read that value
+ * out of the process. However, PTRACE_SETREGS will
+ * fail. In this case, there is nothing to do but
+ * just kill the process.
+ */
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
+ fatal_sigsegv();
/* Now we set local_using_sysemu to be used for one loop */
local_using_sysemu = get_using_sysemu();
@@ -310,19 +364,26 @@ void userspace(struct uml_pt_regs *regs)
op = SELECT_PTRACE_OPERATION(local_using_sysemu,
singlestepping(NULL));
- err = ptrace(op, pid, 0, 0);
- if (err)
- panic("userspace - could not resume userspace process, "
- "pid=%d, ptrace operation = %d, errno = %d\n",
- pid, op, errno);
+ if (ptrace(op, pid, 0, 0)) {
+ printk(UM_KERN_ERR "userspace - ptrace continue "
+ "failed, op = %d, errno = %d\n", op, errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
- if (err < 0)
- panic("userspace - waitpid failed, errno = %d\n",
- errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "userspace - wait failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
regs->is_user = 1;
- save_registers(pid, regs);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
+ printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
+
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
if (WIFSTOPPED(status)) {
@@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs)
break;
case SIGVTALRM:
now = os_nsecs();
- if(now < nsecs)
+ if (now < nsecs)
break;
block_signals();
(*sig_info[sig])(sig, regs);
@@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs)
default:
printk(UM_KERN_ERR "userspace - child stopped "
"with signal %d\n", sig);
+ fatal_sigsegv();
}
pid = userspace_pid[0];
interrupt_end();
@@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
.it_interval = tv }) });
err = ptrace_setregs(pid, thread_regs);
- if (err < 0)
- panic("copy_context_skas0 : PTRACE_SETREGS failed, "
- "pid = %d, errno = %d\n", pid, -err);
+ if (err < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
+ "failed, pid = %d, errno = %d\n", pid, -err);
+ return err;
+ }
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
@@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* parent's stack, and check, if bad result.
*/
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("Failed to continue new process, pid = %d, "
- "errno = %d\n", pid, errno);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
+ "errno = %d\n", pid, errno);
+ return err;
+ }
+
wait_stub_done(pid);
pid = data->err;
- if (pid < 0)
- panic("copy_context_skas0 - stub-parent reports error %d\n",
- -pid);
+ if (pid < 0) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
+ "error %d\n", -pid);
+ return pid;
+ }
/*
* Wait, until child has finished too: read child's result from
* child's stack and check it.
*/
wait_stub_done(pid);
- if (child_data->err != STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %ld\n",
- child_data->err);
+ if (child_data->err != STUB_DATA) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
+ "error %ld\n", child_data->err);
+ err = child_data->err;
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *)PTRACE_O_TRACESYSGOOD) < 0)
- panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *)PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
/*
@@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* available. Opening /proc/mm creates a new mm_context, which lacks
* the stub-pages. Thus, we map them using /proc/mm-fd
*/
-void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack)
+int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack)
{
struct proc_mm_op mmop;
int n;
@@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code,
printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
"offset = %llx\n", code, code_fd,
(unsigned long long) code_offset);
- panic("map_stub_pages : /proc/mm map for code failed, "
- "err = %d\n", n);
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
+ "failed, err = %d\n", n);
+ return -n;
}
if (stack) {
@@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code,
.offset = map_offset
} } });
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
- if (n != sizeof(mmop))
- panic("map_stub_pages : /proc/mm map for data failed, "
- "err = %d\n", errno);
+ if (n != sizeof(mmop)) {
+ n = errno;
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
+ "data failed, err = %d\n", n);
+ return -n;
+ }
}
+
+ return 0;
}
void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
@@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
kmalloc_ok = 0;
return 1;
default:
- panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+ printk(UM_KERN_ERR "Bad sigsetjmp return in "
+ "start_idle_thread - %d\n", n);
+ fatal_sigsegv();
}
longjmp(*switch_buf, 1);
}
@@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp)
if (proc_mm) {
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
mm_idp->u.mm_fd);
- if (err)
- panic("__switch_mm - PTRACE_SWITCH_MM failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
else userspace_pid[0] = mm_idp->u.pid;
}
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
deleted file mode 100644
index 3b1b9244f468..000000000000
--- a/arch/um/os-Linux/skas/trap.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#if 0
-#include "kern_util.h"
-#include "skas.h"
-#include "ptrace_user.h"
-#include "sysdep/ptrace_user.h"
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include "sysdep/ptrace.h"
-#include "kern_constants.h"
-#include "as-layout.h"
-#include "os.h"
-#include "sigcontext.h"
-#include "task.h"
-
-static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
-
-void sig_handler_common_skas(int sig, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct uml_pt_regs *r;
- void (*handler)(int, struct uml_pt_regs *);
- int save_user, save_errno = errno;
-
- /*
- * This is done because to allow SIGSEGV to be delivered inside a SEGV
- * handler. This can happen in copy_user, and if SEGV is disabled,
- * the process will die.
- * XXX Figure out why this is better than SA_NODEFER
- */
- if (sig == SIGSEGV) {
- change_sig(SIGSEGV, 1);
- /*
- * For segfaults, we want the data from the
- * sigcontext. In this case, we don't want to mangle
- * the process registers, so use a static set of
- * registers. For other signals, the process
- * registers are OK.
- */
- r = &ksig_regs[cpu()];
- copy_sc(r, sc_ptr);
- }
- else r = TASK_REGS(get_current());
-
- save_user = r->is_user;
- r->is_user = 0;
- if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
- (sig == SIGILL) || (sig == SIGTRAP))
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
-
- change_sig(SIGUSR1, 1);
-
- handler = sig_info[sig];
-
- /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
- unblock_signals();
-
- handler(sig, r);
-
- errno = save_errno;
- r->is_user = save_user;
-}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7b81f6c08a5e..b616e15638fb 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -60,10 +60,11 @@ static int ptrace_child(void)
* the UML code itself.
*/
ret = 2;
- _exit(ret);
+
+ exit(ret);
}
-static void fatal_perror(char *str)
+static void fatal_perror(const char *str)
{
perror(str);
exit(1);
@@ -341,6 +342,8 @@ static void __init check_coredump_limit(void)
void __init os_early_checks(void)
{
+ int pid;
+
/* Print out the core dump limits early */
check_coredump_limit();
@@ -350,6 +353,11 @@ void __init os_early_checks(void)
* kernel is running.
*/
check_tmpexec();
+
+ pid = start_ptraced_child();
+ if (init_registers(pid))
+ fatal("Failed to initialize default registers");
+ stop_ptraced_child(pid, 1, 1);
}
static int __init noprocmm_cmd_param(char *str, int* add)
@@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void)
non_fatal("found\n");
}
- init_registers(pid);
stop_ptraced_child(pid, 1, 1);
}
@@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void)
else non_fatal("found\n");
}
-int can_do_skas(void)
+void can_do_skas(void)
{
non_fatal("Checking for the skas3 patch in the host:\n");
@@ -476,8 +483,6 @@ int can_do_skas(void)
if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
skas_needs_stub = 1;
-
- return 1;
}
int __init parse_iomem(char *str, int *add)
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
deleted file mode 100644
index 2a1c9843e32e..000000000000
--- a/arch/um/os-Linux/trap.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "os.h"
-#include "sysdep/ptrace.h"
-
-/* Initialized from linux_main() */
-void (*sig_info[NSIG])(int, struct uml_pt_regs *);
-
-void os_fill_handlinfo(struct kern_handlers h)
-{
- sig_info[SIGTRAP] = h.relay_signal;
- sig_info[SIGFPE] = h.relay_signal;
- sig_info[SIGILL] = h.relay_signal;
- sig_info[SIGWINCH] = h.winch;
- sig_info[SIGBUS] = h.bus_handler;
- sig_info[SIGSEGV] = h.page_fault;
- sig_info[SIGIO] = h.sigio_handler;
- sig_info[SIGVTALRM] = h.timer_handler;
-}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 4cfdd18ea1ef..b09ff66a77ee 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -1,13 +1,16 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
+#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
struct grantpt_info {
int fd;
@@ -26,36 +29,34 @@ static void grantpt_cb(void *arg)
int get_pty(void)
{
struct grantpt_info info;
- int fd;
-
- fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
- if(fd < 0){
- printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
- return(fd);
+ int fd, err;
+
+ fd = open("/dev/ptmx", O_RDWR);
+ if (fd < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - "
+ "err = %d\n", errno);
+ return err;
}
info.fd = fd;
initial_thread_cb(grantpt_cb, &info);
- if(info.res < 0){
- printk("get_pty : Couldn't grant pty - errno = %d\n",
- -info.err);
- return(-1);
+ if (info.res < 0) {
+ err = -info.err;
+ printk(UM_KERN_ERR "get_pty : Couldn't grant pty - "
+ "errno = %d\n", -info.err);
+ goto out;
}
- if(unlockpt(fd) < 0){
- printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
- return(-1);
+
+ if (unlockpt(fd) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - "
+ "errno = %d\n", errno);
+ goto out;
}
- return(fd);
+ return fd;
+out:
+ close(fd);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
index d11a55baa6bd..cc648e6fd3a2 100644
--- a/arch/um/os-Linux/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -12,7 +12,6 @@
#include <sys/time.h>
#include "init.h"
#include "user.h"
-#include "kern_util.h"
#include "os.h"
#define TTY_LOG_DIR "./"
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 3e058ce9ffb6..a6f31d476993 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -88,21 +88,6 @@ void setup_hostinfo(char *buf, int len)
host.release, host.version, host.machine);
}
-int setjmp_wrapper(void (*proc)(void *, void *), ...)
-{
- va_list args;
- jmp_buf buf;
- int n;
-
- n = UML_SETJMP(&buf);
- if(n == 0){
- va_start(args, proc);
- (*proc)(&buf, &args);
- }
- va_end(args);
- return n;
-}
-
void os_dump_core(void)
{
int pid;
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
index a4360b5207db..8d4f273f1219 100644
--- a/arch/um/sys-i386/bug.c
+++ b/arch/um/sys-i386/bug.c
@@ -4,6 +4,7 @@
*/
#include <linux/uaccess.h>
+#include <asm/errno.h>
/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 806895d73bcc..a74442d13762 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -3,171 +3,47 @@
* Licensed under the GPL
*/
-#include <errno.h>
#include <signal.h>
-#include <string.h>
#include "kern_constants.h"
-#include "os.h"
+#include "kern_util.h"
+#include "longjmp.h"
#include "task.h"
#include "user.h"
-
-#define MAXTOKEN 64
+#include "sysdep/ptrace.h"
/* Set during early boot */
int host_has_cmov = 1;
-int host_has_xmm = 0;
+static jmp_buf cmov_test_return;
-static char token(int fd, char *buf, int len, char stop)
+static void cmov_sigill_test_handler(int sig)
{
- int n;
- char *ptr, *end, c;
-
- ptr = buf;
- end = &buf[len];
- do {
- n = os_read_file(fd, ptr, sizeof(*ptr));
- c = *ptr++;
- if (n != sizeof(*ptr)) {
- if (n == 0)
- return 0;
- printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
- "err = %d\n", -n);
- if (n < 0)
- return n;
- else return -EIO;
- }
- } while ((c != '\n') && (c != stop) && (ptr < end));
-
- if (ptr == end) {
- printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
- stop);
- return -1;
- }
- *(ptr - 1) = '\0';
- return c;
-}
-
-static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
-{
- int n;
- char c;
-
- scratch[len - 1] = '\0';
- while (1) {
- c = token(fd, scratch, len - 1, ':');
- if (c <= 0)
- return 0;
- else if (c != ':') {
- printk(UM_KERN_ERR "Failed to find ':' in "
- "/proc/cpuinfo\n");
- return 0;
- }
-
- if (!strncmp(scratch, key, strlen(key)))
- return 1;
-
- do {
- n = os_read_file(fd, &c, sizeof(c));
- if (n != sizeof(c)) {
- printk(UM_KERN_ERR "Failed to find newline in "
- "/proc/cpuinfo, err = %d\n", -n);
- return 0;
- }
- } while (c != '\n');
- }
- return 0;
+ host_has_cmov = 0;
+ longjmp(cmov_test_return, 1);
}
-static int check_cpu_flag(char *feature, int *have_it)
-{
- char buf[MAXTOKEN], c;
- int fd, len = ARRAY_SIZE(buf);
-
- printk(UM_KERN_INFO "Checking for host processor %s support...",
- feature);
- fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
- -fd);
- return 0;
- }
-
- *have_it = 0;
- if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
- goto out;
-
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c != ' ') {
- printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
- goto out;
- }
-
- while (1) {
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c == '\n')
- break;
-
- if (!strcmp(buf, feature)) {
- *have_it = 1;
- goto out;
- }
- }
- out:
- if (*have_it == 0)
- printk("No\n");
- else if (*have_it == 1)
- printk("Yes\n");
- os_close_file(fd);
- return 1;
-}
-
-#if 0 /*
- * This doesn't work in tt mode, plus it's causing compilation problems
- * for some people.
- */
-static void disable_lcall(void)
+void arch_check_bugs(void)
{
- struct modify_ldt_ldt_s ldt;
- int err;
+ struct sigaction old, new;
- bzero(&ldt, sizeof(ldt));
- ldt.entry_number = 7;
- ldt.base_addr = 0;
- ldt.limit = 0;
- err = modify_ldt(1, &ldt, sizeof(ldt));
- if (err)
- printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
- errno);
-}
-#endif
+ printk(UM_KERN_INFO "Checking for host processor cmov support...");
+ new.sa_handler = cmov_sigill_test_handler;
-void arch_init_thread(void)
-{
-#if 0
- disable_lcall();
-#endif
-}
+ /* Make sure that SIGILL is enabled after the handler longjmps back */
+ new.sa_flags = SA_NODEFER;
+ sigemptyset(&new.sa_mask);
+ sigaction(SIGILL, &new, &old);
-void arch_check_bugs(void)
-{
- int have_it;
+ if (setjmp(cmov_test_return) == 0) {
+ unsigned long foo = 0;
+ __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+ printk(UM_KERN_CONT "Yes\n");
+ } else
+ printk(UM_KERN_CONT "No\n");
- if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
- printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
- "capability checks\n");
- return;
- }
- if (check_cpu_flag("cmov", &have_it))
- host_has_cmov = have_it;
- if (check_cpu_flag("xmm", &have_it))
- host_has_xmm = have_it;
+ sigaction(SIGILL, &old, &new);
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
unsigned char tmp[2];
@@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
* SIGILL in init.
*/
if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
- return 0;
+ return;
+
+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+ printk(UM_KERN_ERR "SIGILL in init, could not read "
+ "instructions!\n");
+ return;
+ }
- if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
- panic("SIGILL in init, could not read instructions!\n");
if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
- return 0;
+ return;
if (host_has_cmov == 0)
- panic("SIGILL caused by cmov, which this processor doesn't "
- "implement, boot a filesystem compiled for older "
- "processors");
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor doesn't implement. Boot a filesystem "
+ "compiled for older processors");
else if (host_has_cmov == 1)
- panic("SIGILL caused by cmov, which this processor claims to "
- "implement");
- else if (host_has_cmov == -1)
- panic("SIGILL caused by cmov, couldn't tell if this processor "
- "implements it, boot a filesystem compiled for older "
- "processors");
- else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
- return 0;
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor claims to implement");
+ else
+ printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+ host_has_cmov);
}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 67c0958eb984..a34263e6b08d 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,8 +3,9 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/unistd.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/unistd.h>
#include "os.h"
#include "proc_mm.h"
#include "skas.h"
@@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
if (ptrace_ldt)
return read_ldt_from_host(ptr, bytecount);
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
if (size > bytecount)
@@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
ptr += size;
}
}
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
if (bytecount == 0 || err == -EFAULT)
goto out;
@@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
}
if (!ptrace_ldt)
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
if (err)
@@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
err = 0;
out_unlock:
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
out:
return err;
}
@@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
if (!ptrace_ldt)
- init_MUTEX(&new_mm->ldt.semaphore);
+ mutex_init(&new_mm->ldt.lock);
if (!from_mm) {
memset(&desc, 0, sizeof(desc));
@@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
* i.e., we have to use the stub for modify_ldt, which
* can't handle the big read buffer of up to 64kB.
*/
- down(&from_mm->ldt.semaphore);
+ mutex_lock(&from_mm->ldt.lock);
if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
sizeof(new_mm->ldt.u.entries));
@@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
}
}
new_mm->ldt.entry_count = from_mm->ldt.entry_count;
- up(&from_mm->ldt.semaphore);
+ mutex_unlock(&from_mm->ldt.lock);
}
out:
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index bd3da8a61f64..6b4499906a6c 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -8,11 +8,11 @@
#include "asm/uaccess.h"
#include "skas.h"
-extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
+extern int arch_switch_tls(struct task_struct *to);
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
- int err = arch_switch_tls(from, to);
+ int err = arch_switch_tls(to);
if (!err)
return;
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 5cf97bc229b9..0b10c3e74028 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -19,17 +19,3 @@ int ptrace_setregs(long pid, unsigned long *regs)
return -errno;
return 0;
}
-
-int ptrace_getfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
-
-int ptrace_setfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 19053d46cb60..fd0c25ad6af3 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -168,12 +168,13 @@ static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
struct sigcontext sc;
- int err;
+ int err, pid;
err = copy_from_user(&sc, from, sizeof(sc));
if (err)
return err;
+ pid = userspace_pid[current_thread_info()->cpu];
copy_sc(&regs->regs, &sc);
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
@@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = restore_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fpx_registers failed, errno = %d\n",
@@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = restore_fp_registers(pid, (unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fp_registers failed, errno = %d\n",
@@ -223,7 +222,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
{
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
- int err;
+ int err, pid;
sc.gs = REGS_GS(regs->regs.gp);
sc.fs = REGS_FS(regs->regs.gp);
@@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to,
to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
sc.fpstate = to_fp;
+ pid = userspace_pid[current_thread_info()->cpu];
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
- err = save_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = save_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0){
printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
"failed, errno = %d\n", err);
@@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
else {
struct user_i387_struct fp;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = save_fp_registers(pid, (unsigned long *) &fp);
if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
return 1;
}
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index e730772c401b..7699e89f660f 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -7,7 +7,7 @@
.globl batch_syscall_stub
batch_syscall_stub:
/* load pointer to first operation */
- mov $(ASM_STUB_DATA+8), %esp
+ mov $(STUB_DATA+8), %esp
again:
/* load length of additional data */
@@ -15,12 +15,12 @@ again:
/* if(length == 0) : end of list */
/* write possible 0 to header */
- mov %eax, ASM_STUB_DATA+4
+ mov %eax, STUB_DATA+4
cmpl $0, %eax
jz done
/* save current pointer */
- mov %esp, ASM_STUB_DATA+4
+ mov %esp, STUB_DATA+4
/* skip additional data */
add %eax, %esp
@@ -46,7 +46,7 @@ again:
done:
/* save return value */
- mov %eax, ASM_STUB_DATA
+ mov %eax, STUB_DATA
/* stop */
int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index b3999cb76bfd..28ccf737a79f 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -1,32 +1,17 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
-#include <sys/select.h> /* The only way I can see to get sigset_t */
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
- int pid;
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* Load pointer to sigcontext into esp, since we need to leave
- * the stack in its original form when we do the sigreturn here, by
- * hand.
- */
- __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
- "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+ trap_myself();
}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index 12d4148dba39..00e5f5203eea 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -9,4 +9,9 @@
#define old_mmap old_mmap_i386
+.section .rodata,"a"
+
#include "../../x86/kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index fcaff86b000c..c6c7131e563b 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -26,6 +26,11 @@ int do_set_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_set_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_get_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task)
* SKAS patch.
*/
-int arch_switch_tls(struct task_struct *from, struct task_struct *to)
+int arch_switch_tls(struct task_struct *to)
{
if (!host_supports_tls)
return 0;
@@ -225,7 +235,8 @@ out:
}
/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+ int idx)
{
struct thread_struct *t = &task->thread;
@@ -263,7 +274,7 @@ clear:
goto out;
}
-asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+int sys_set_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
* i386. However the only possible error are caused by bugs.
*/
int ptrace_set_thread_area(struct task_struct *child, int idx,
- struct user_desc __user *user_desc)
+ struct user_desc __user *user_desc)
{
struct user_desc info;
@@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
return set_tls_entry(child, &info, idx, 0);
}
-asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
+int sys_get_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -355,10 +366,9 @@ out:
return ret;
}
-
/*
- * XXX: This part is probably common to i386 and x86-64. Don't create a common
- * file for now, do that when implementing x86-64 support.
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
*/
static int __init __setup_host_supports_tls(void)
{
@@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void)
printk(KERN_INFO "Host TLS support detected\n");
printk(KERN_INFO "Detected host type: ");
switch (host_gdt_entry_tls_min) {
- case GDT_ENTRY_TLS_MIN_I386:
- printk("i386\n");
- break;
- case GDT_ENTRY_TLS_MIN_X86_64:
- printk("x86_64\n");
- break;
+ case GDT_ENTRY_TLS_MIN_I386:
+ printk(KERN_CONT "i386");
+ break;
+ case GDT_ENTRY_TLS_MIN_X86_64:
+ printk(KERN_CONT "x86_64");
+ break;
}
+ printk(KERN_CONT " (GDT indexes %d to %d)\n",
+ host_gdt_entry_tls_min,
+ host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
} else
printk(KERN_ERR " Host TLS support NOT detected! "
"TLS support inside UML will not work\n");
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index a9814a7ae60e..08901526e893 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
ptrace_user.o sysrq.o
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel
+EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
all: $(OBJ)
@@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c
semaphore.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
checksum.S:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/lib/$@ $@
+ ln -s $(srctree)/arch/ppc/lib/$@ $@
mk_defs.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.head:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.h: mk_defs.c ppc_defs.head \
- $(TOPDIR)/include/asm-ppc/mmu.h \
- $(TOPDIR)/include/asm-ppc/processor.h \
- $(TOPDIR)/include/asm-ppc/pgtable.h \
- $(TOPDIR)/include/asm-ppc/ptrace.h
+ $(srctree)/include/asm-ppc/mmu.h \
+ $(srctree)/include/asm-ppc/processor.h \
+ $(srctree)/include/asm-ppc/pgtable.h \
+ $(srctree)/include/asm-ppc/ptrace.h
# $(CC) $(CFLAGS) -S mk_defs.c
cp ppc_defs.head ppc_defs.h
# for bk, this way we can write to the file even if it's not checked out
@@ -56,13 +56,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
checksum.o: checksum.S
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
misc.o: misc.S ppc_defs.h
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
index a4360b5207db..e8034e363d83 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/um/sys-x86_64/bug.c
@@ -5,7 +5,8 @@
#include <linux/uaccess.h>
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
*/
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index 506b6765bbcb..44e02ba2a265 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -6,15 +6,10 @@
#include "sysdep/ptrace.h"
-void arch_init_thread(void)
-{
-}
-
void arch_check_bugs(void)
{
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
- return 0;
}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b7631b0e9ddc..f3458d7d1c5a 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,13 +5,12 @@
* Licensed under the GPL
*/
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
+#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/mm.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
#include <asm/uaccess.h>
-#include <asm/elf.h>
/*
* determines which flags the user has access to.
@@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
unsigned long tmp;
#ifdef TIF_IA32
- /* Some code in the 64bit emulation may not be 64bit clean.
- Don't take any chances. */
+ /*
+ * Some code in the 64bit emulation may not be 64bit clean.
+ * Don't take any chances.
+ */
if (test_tsk_thread_flag(child, TIF_IA32))
value &= 0xffffffff;
#endif
- switch (regno){
+ switch (regno) {
case FS:
case GS:
case DS:
@@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data)
if (addr < MAX_REG_OFFSET)
return putreg(child, addr, data);
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
if ((addr == 4) || (addr == 5))
@@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data)
return -EIO;
tmp = 0; /* Default return condition */
- if (addr < MAX_REG_OFFSET){
+ if (addr < MAX_REG_OFFSET)
tmp = getreg(child, addr);
- }
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
tmp = child->thread.arch.debugregs[addr];
@@ -127,8 +127,9 @@ int is_syscall(unsigned long addr)
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
- if (n){
- /* access_process_vm() grants access to vsyscall and stub,
+ if (n) {
+ /*
+ * access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
@@ -155,7 +156,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
return err;
n = copy_to_user(buf, fpregs, sizeof(fpregs));
- if(n > 0)
+ if (n > 0)
return -EFAULT;
return n;
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index b5f9c33e311e..c57a496d3f5b 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -4,55 +4,19 @@
* Licensed under the GPL
*/
-#include <stddef.h>
#include <errno.h>
#include "ptrace_user.h"
-#include "user.h"
-#include "kern_constants.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
- if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
- return(-errno);
- return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
- if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
- return(-errno);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+ return -errno;
return(0);
}
-int ptrace_setfpregs(long pid, unsigned long *regs)
+int ptrace_setregs(long pid, unsigned long *regs_out)
{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
return -errno;
- return 0;
-}
-
-void ptrace_pokeuser(unsigned long addr, unsigned long data)
-{
- panic("ptrace_pokeuser");
-}
-
-#define DS 184
-#define ES 192
-#define __USER_DS 0x2b
-
-void arch_enter_kernel(void *task, int pid)
-{
-}
-
-void arch_leave_kernel(void *task, int pid)
-{
-#ifdef UM_USER_CS
- if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
- printk("POKEUSR CS failed");
-#endif
-
- if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
- printk("POKEUSR DS failed");
- if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
- printk("POKEUSR ES failed");
+ return(0);
}
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 14070181407b..1a899a7ed7a6 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -81,7 +81,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
+ err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
@@ -143,7 +143,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
if (err)
return 1;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
+ err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
index 4afe204a6af7..568768763155 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -8,18 +8,18 @@ syscall_stub:
/* We don't have 64-bit constants, so this constructs the address
* we need.
*/
- movq $(ASM_STUB_DATA >> 32), %rbx
+ movq $(STUB_DATA >> 32), %rbx
salq $32, %rbx
- movq $(ASM_STUB_DATA & 0xffffffff), %rcx
+ movq $(STUB_DATA & 0xffffffff), %rcx
or %rcx, %rbx
movq %rax, (%rbx)
int3
.globl batch_syscall_stub
batch_syscall_stub:
- mov $(ASM_STUB_DATA >> 32), %rbx
+ mov $(STUB_DATA >> 32), %rbx
sal $32, %rbx
- mov $(ASM_STUB_DATA & 0xffffffff), %rax
+ mov $(STUB_DATA & 0xffffffff), %rax
or %rax, %rbx
/* load pointer to first operation */
mov %rbx, %rsp
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 3afb590f0072..ced051afc705 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -1,51 +1,22 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stddef.h>
#include <signal.h>
-#include <asm/unistd.h>
#include "as-layout.h"
-#include "uml-config.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
#include "sysdep/stub.h"
-
-/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
- * in the libc headers anywhere.
- */
-struct rt_sigframe
-{
- char *pretcode;
- struct ucontext uc;
- struct siginfo info;
-};
-
-/* Copied here from <linux/kernel.h> - we're userspace. */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
+#include "sysdep/faultinfo.h"
+#include "sysdep/sigcontext.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct ucontext *uc;
- int pid;
__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
&uc->uc_mcontext);
-
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* sys_sigreturn expects that the stack pointer will be 8 bytes into
- * the signal frame. So, we use the ucontext pointer, which we know
- * already, to get the signal frame pointer, and add 8 to that.
- */
- __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
- "g" ((unsigned long)
- container_of(uc, struct rt_sigframe, uc) + 8),
- "g" (__NR_rt_sigreturn));
+ trap_myself();
}
+
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index 71b2ae4ad5de..c128eb897008 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -1,5 +1,7 @@
-/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML. */
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
#include <linux/linkage.h>
#include <linux/sys.h>
@@ -8,22 +10,26 @@
#define __NO_STUBS
-/* Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table. */
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
/* Not going to be implemented by UML, since we have no hardware. */
#define stub_iopl sys_ni_syscall
#define sys_ioperm sys_ni_syscall
-/* The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility. */
-/*#define sys_set_thread_area sys_ni_syscall
-#define sys_get_thread_area sys_ni_syscall*/
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
/* On UML we call it this way ("old" means it's not mmap2) */
#define sys_mmap old_mmap
-/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
- * See arch/x86_64/kernel/sys_x86_64.c */
+/*
+ * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
+ * See arch/x86_64/kernel/sys_x86_64.c
+ */
#define sys_uname sys_uname64
#define stub_clone sys_clone
@@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void);
extern void sys_ni_syscall(void);
-sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = {
- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
- [0 ... UM_NR_syscall_max] = &sys_ni_syscall,
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ * [0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
#include <asm-x86/unistd_64.h>
};
+
+int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 86f6b18410ee..f1199fd34d38 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
case ARCH_SET_GS:
- restore_registers(pid, &current->thread.regs.regs);
+ ret = restore_registers(pid, &current->thread.regs.regs);
+ if (ret)
+ return ret;
break;
case ARCH_GET_FS:
case ARCH_GET_GS:
@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
current->thread.arch.fs = (unsigned long) ptr;
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_SET_GS:
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_GET_FS:
ret = put_user(tmp, addr);
@@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
return ret;
}
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
return;
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index 765444031819..f4f82beb3508 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -4,32 +4,33 @@
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/utsname.h"
-#include "linux/module.h"
-#include "asm/current.h"
-#include "asm/ptrace.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
#include "sysrq.h"
-void __show_regs(struct pt_regs * regs)
+void __show_regs(struct pt_regs *regs)
{
printk("\n");
print_modules();
- printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
current->comm, print_tainted(), init_utsname()->release);
- printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
+ printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
PT_REGS_RIP(regs));
- printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
PT_REGS_EFLAGS(regs));
- printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
- printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
- printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+ printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
- printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
- printk("R13: %016lx R14: %016lx R15: %016lx\n",
+ printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
}
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
index 8b8eff1bd977..3dead392a415 100644
--- a/arch/um/sys-x86_64/um_module.c
+++ b/arch/um/sys-x86_64/um_module.c
@@ -1,7 +1,7 @@
#include <linux/vmalloc.h>
#include <linux/moduleloader.h>
-/*Copied from i386 arch/i386/kernel/module.c */
+/* Copied from i386 arch/i386/kernel/module.c */
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -13,7 +13,9 @@ void *module_alloc(unsigned long size)
void module_free(struct module *mod, void *module_region)
{
vfree(module_region);
- /* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
+ /*
+ * FIXME: If module_region == mod->init_region, trim exception
+ * table entries.
+ */
}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 59eef1c7fdaa..434821187cfc 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -465,6 +465,9 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
Calgary anyway, pass 'iommu=calgary' on the kernel command line.
If unsure, say Y.
+config IOMMU_HELPER
+ def_bool (CALGARY_IOMMU || GART_IOMMU)
+
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
bool
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 0db0a6291bbd..8022d3c695c0 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -722,7 +722,9 @@ ia32_sys_call_table:
.quad sys_epoll_pwait
.quad compat_sys_utimensat /* 320 */
.quad compat_sys_signalfd
- .quad compat_sys_timerfd
+ .quad sys_timerfd_create
.quad sys_eventfd
.quad sys32_fallocate
+ .quad compat_sys_timerfd_settime /* 325 */
+ .quad compat_sys_timerfd_gettime
ia32_syscall_end:
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 1fe7f043ebde..1b5464c2434f 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/gart.h>
#include <asm/calgary.h>
#include <asm/tce.h>
@@ -260,22 +261,28 @@ static void iommu_range_reserve(struct iommu_table *tbl,
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
- unsigned int npages)
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
+ unsigned int npages)
{
unsigned long flags;
unsigned long offset;
+ unsigned long boundary_size;
+
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
BUG_ON(npages == 0);
spin_lock_irqsave(&tbl->it_lock, flags);
- offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
- tbl->it_size, npages);
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, tbl->it_hint,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
tbl->chip_ops->tce_cache_blast(tbl);
- offset = find_next_zero_string(tbl->it_map, 0,
- tbl->it_size, npages);
+
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
printk(KERN_WARNING "Calgary: IOMMU full.\n");
spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -286,7 +293,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- set_bit_string(tbl->it_map, offset, npages);
tbl->it_hint = offset + npages;
BUG_ON(tbl->it_hint > tbl->it_size);
@@ -295,13 +301,13 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return offset;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
- unsigned int npages, int direction)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, unsigned int npages, int direction)
{
unsigned long entry;
dma_addr_t ret = bad_dma_address;
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (unlikely(entry == bad_dma_address))
goto error;
@@ -354,7 +360,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
badbit, tbl, dma_addr, entry, npages);
}
- __clear_bit_string(tbl->it_map, entry, npages);
+ iommu_area_free(tbl->it_map, entry, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
@@ -438,7 +444,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
vaddr = (unsigned long) sg_virt(s);
npages = num_dma_pages(vaddr, s->length);
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (entry == bad_dma_address) {
/* makes sure unmap knows to stop */
s->dma_length = 0;
@@ -476,7 +482,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
npages = num_dma_pages(uaddr, size);
if (translation_enabled(tbl))
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
else
dma_handle = virt_to_bus(vaddr);
@@ -516,7 +522,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
if (translation_enabled(tbl)) {
/* set up tces to cover the allocated range */
- mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
+ mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
if (mapping == bad_dma_address)
goto free;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 845cbecd68e9..65f6acb025c8 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/kdebug.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -82,17 +83,24 @@ AGPEXTERN __u32 *agp_gatt_table;
static unsigned long next_bit; /* protected by iommu_bitmap_lock */
static int need_flush; /* global flush state. set for each gart wrap */
-static unsigned long alloc_iommu(int size)
+static unsigned long alloc_iommu(struct device *dev, int size)
{
unsigned long offset, flags;
+ unsigned long boundary_size;
+ unsigned long base_index;
+
+ base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
+ PAGE_SIZE) >> PAGE_SHIFT;
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- offset = find_next_zero_string(iommu_gart_bitmap, next_bit,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
+ size, base_index, boundary_size, 0);
if (offset == -1) {
need_flush = 1;
- offset = find_next_zero_string(iommu_gart_bitmap, 0,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
+ size, base_index, boundary_size, 0);
}
if (offset != -1) {
set_bit_string(iommu_gart_bitmap, offset, size);
@@ -114,7 +122,7 @@ static void free_iommu(unsigned long offset, int size)
unsigned long flags;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- __clear_bit_string(iommu_gart_bitmap, offset, size);
+ iommu_area_free(iommu_gart_bitmap, offset, size);
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
}
@@ -235,7 +243,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir)
{
unsigned long npages = to_pages(phys_mem, size);
- unsigned long iommu_page = alloc_iommu(npages);
+ unsigned long iommu_page = alloc_iommu(dev, npages);
int i;
if (iommu_page == -1) {
@@ -355,10 +363,11 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
}
/* Map multiple scatterlist entries continuous into the first. */
-static int __dma_map_cont(struct scatterlist *start, int nelems,
- struct scatterlist *sout, unsigned long pages)
+static int __dma_map_cont(struct device *dev, struct scatterlist *start,
+ int nelems, struct scatterlist *sout,
+ unsigned long pages)
{
- unsigned long iommu_start = alloc_iommu(pages);
+ unsigned long iommu_start = alloc_iommu(dev, pages);
unsigned long iommu_page = iommu_start;
struct scatterlist *s;
int i;
@@ -394,8 +403,8 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
}
static inline int
-dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
- unsigned long pages, int need)
+dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
+ struct scatterlist *sout, unsigned long pages, int need)
{
if (!need) {
BUG_ON(nelems != 1);
@@ -403,7 +412,7 @@ dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
sout->dma_length = start->length;
return 0;
}
- return __dma_map_cont(start, nelems, sout, pages);
+ return __dma_map_cont(dev, start, nelems, sout, pages);
}
/*
@@ -416,6 +425,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
struct scatterlist *s, *ps, *start_sg, *sgmap;
int need = 0, nextneed, i, out, start;
unsigned long pages = 0;
+ unsigned int seg_size;
+ unsigned int max_seg_size;
if (nents == 0)
return 0;
@@ -426,6 +437,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
out = 0;
start = 0;
start_sg = sgmap = sg;
+ seg_size = 0;
+ max_seg_size = dma_get_max_seg_size(dev);
ps = NULL; /* shut up gcc */
for_each_sg(sg, s, nents, i) {
dma_addr_t addr = sg_phys(s);
@@ -443,11 +456,13 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
* offset.
*/
if (!iommu_merge || !nextneed || !need || s->offset ||
+ (s->length + seg_size > max_seg_size) ||
(ps->offset + ps->length) % PAGE_SIZE) {
- if (dma_map_cont(start_sg, i - start, sgmap,
- pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start,
+ sgmap, pages, need) < 0)
goto error;
out++;
+ seg_size = 0;
sgmap = sg_next(sgmap);
pages = 0;
start = i;
@@ -455,11 +470,12 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
}
}
+ seg_size += s->length;
need = nextneed;
pages += to_pages(s->offset, s->length);
ps = s;
}
- if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
goto error;
out++;
flush_gart();
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 8344c70adf61..adff5562f5fd 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -321,6 +321,8 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_timerfd_create
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8f94a0b89dff..cf5308148689 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1739,7 +1739,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
if (bytes == 8) {
gpa_t gpa;
struct page *page;
- char *addr;
+ char *kaddr;
u64 val;
down_read(&current->mm->mmap_sem);
@@ -1754,9 +1754,9 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
val = *(u64 *)new;
page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
- addr = kmap_atomic(page, KM_USER0);
- set_64bit((u64 *)(addr + offset_in_page(gpa)), val);
- kunmap_atomic(addr, KM_USER0);
+ kaddr = kmap_atomic(page, KM_USER0);
+ set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
+ kunmap_atomic(kaddr, KM_USER0);
kvm_release_page_dirty(page);
emul_write:
up_read(&current->mm->mmap_sem);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 4876182daf8a..25df1c1989fe 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -21,7 +21,7 @@ else
lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
lib-y += thunk_64.o clear_page_64.o copy_page_64.o
- lib-y += bitstr_64.o bitops_64.o
+ lib-y += bitops_64.o
lib-y += memmove_64.o memset_64.o
lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
endif
diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
deleted file mode 100644
index 7445caf1b5de..000000000000
--- a/arch/x86/lib/bitstr_64.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <linux/module.h>
-#include <linux/bitops.h>
-
-/* Find string of zero bits in a bitmap */
-unsigned long
-find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
-{
- unsigned long n, end, i;
-
- again:
- n = find_next_zero_bit(bitmap, nbits, start);
- if (n == -1)
- return -1;
-
- /* could test bitsliced, but it's hardly worth it */
- end = n+len;
- if (end > nbits)
- return -1;
- for (i = n+1; i < end; i++) {
- if (test_bit(i, bitmap)) {
- start = i+1;
- goto again;
- }
- }
- return n;
-}
-
-EXPORT_SYMBOL(find_next_zero_string);
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index c7db504be1ea..6c1914622a88 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -272,7 +272,7 @@ static void pgd_dtor(void *pgd)
* preallocate which never got a corresponding vma will need to be
* freed manually.
*/
-static void pgd_mop_up_pmds(pgd_t *pgdp)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
int i;
@@ -285,7 +285,7 @@ static void pgd_mop_up_pmds(pgd_t *pgdp)
pgdp[i] = native_make_pgd(0);
paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
- pmd_free(pmd);
+ pmd_free(mm, pmd);
}
}
}
@@ -313,7 +313,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
pmd_t *pmd = pmd_alloc_one(mm, addr);
if (!pmd) {
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
return 0;
}
@@ -333,7 +333,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
return 1;
}
-static void pgd_mop_up_pmds(pgd_t *pgd)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
}
#endif /* CONFIG_X86_PAE */
@@ -352,9 +352,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
quicklist_free(0, pgd_dtor, pgd);
}
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42ba0e2da1a0..103b9dff1213 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -72,7 +72,7 @@ pcibios_align_resource(void *data, struct resource *res,
}
}
}
-
+EXPORT_SYMBOL(pcibios_align_resource);
/*
* Handle resources of PCI devices. If the world were perfect, we could