summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Kconfig2
-rw-r--r--arch/alpha/mm/init.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c15
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/plat-omap/usb.c2
-rw-r--r--arch/avr32/Kconfig196
-rw-r--r--arch/avr32/Kconfig.debug19
-rw-r--r--arch/avr32/Makefile84
-rw-r--r--arch/avr32/boards/atstk1000/Makefile2
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c37
-rw-r--r--arch/avr32/boards/atstk1000/flash.c95
-rw-r--r--arch/avr32/boards/atstk1000/setup.c59
-rw-r--r--arch/avr32/boards/atstk1000/spi.c27
-rw-r--r--arch/avr32/boot/images/Makefile62
-rw-r--r--arch/avr32/boot/u-boot/Makefile3
-rw-r--r--arch/avr32/boot/u-boot/empty.S1
-rw-r--r--arch/avr32/boot/u-boot/head.S60
-rw-r--r--arch/avr32/configs/atstk1002_defconfig (renamed from arch/mips/configs/ev96100_defconfig)558
-rw-r--r--arch/avr32/kernel/Makefile18
-rw-r--r--arch/avr32/kernel/asm-offsets.c25
-rw-r--r--arch/avr32/kernel/avr32_ksyms.c55
-rw-r--r--arch/avr32/kernel/cpu.c327
-rw-r--r--arch/avr32/kernel/entry-avr32b.S678
-rw-r--r--arch/avr32/kernel/head.S45
-rw-r--r--arch/avr32/kernel/init_task.c38
-rw-r--r--arch/avr32/kernel/irq.c71
-rw-r--r--arch/avr32/kernel/kprobes.c270
-rw-r--r--arch/avr32/kernel/module.c324
-rw-r--r--arch/avr32/kernel/process.c276
-rw-r--r--arch/avr32/kernel/ptrace.c371
-rw-r--r--arch/avr32/kernel/semaphore.c148
-rw-r--r--arch/avr32/kernel/setup.c335
-rw-r--r--arch/avr32/kernel/signal.c328
-rw-r--r--arch/avr32/kernel/switch_to.S35
-rw-r--r--arch/avr32/kernel/sys_avr32.c51
-rw-r--r--arch/avr32/kernel/syscall-stubs.S102
-rw-r--r--arch/avr32/kernel/syscall_table.S289
-rw-r--r--arch/avr32/kernel/time.c238
-rw-r--r--arch/avr32/kernel/traps.c425
-rw-r--r--arch/avr32/kernel/vmlinux.lds.c139
-rw-r--r--arch/avr32/lib/Makefile10
-rw-r--r--arch/avr32/lib/__avr32_asr64.S31
-rw-r--r--arch/avr32/lib/__avr32_lsl64.S31
-rw-r--r--arch/avr32/lib/__avr32_lsr64.S31
-rw-r--r--arch/avr32/lib/clear_user.S76
-rw-r--r--arch/avr32/lib/copy_user.S119
-rw-r--r--arch/avr32/lib/csum_partial.S47
-rw-r--r--arch/avr32/lib/csum_partial_copy_generic.S99
-rw-r--r--arch/avr32/lib/delay.c55
-rw-r--r--arch/avr32/lib/findbit.S154
-rw-r--r--arch/avr32/lib/io-readsl.S24
-rw-r--r--arch/avr32/lib/io-readsw.S43
-rw-r--r--arch/avr32/lib/io-writesl.S20
-rw-r--r--arch/avr32/lib/io-writesw.S38
-rw-r--r--arch/avr32/lib/libgcc.h33
-rw-r--r--arch/avr32/lib/longlong.h98
-rw-r--r--arch/avr32/lib/memcpy.S62
-rw-r--r--arch/avr32/lib/memset.S72
-rw-r--r--arch/avr32/lib/strncpy_from_user.S60
-rw-r--r--arch/avr32/lib/strnlen_user.S67
-rw-r--r--arch/avr32/mach-at32ap/Makefile2
-rw-r--r--arch/avr32/mach-at32ap/at32ap.c90
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c876
-rw-r--r--arch/avr32/mach-at32ap/clock.c148
-rw-r--r--arch/avr32/mach-at32ap/clock.h30
-rw-r--r--arch/avr32/mach-at32ap/extint.c171
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c164
-rw-r--r--arch/avr32/mach-at32ap/hsmc.h127
-rw-r--r--arch/avr32/mach-at32ap/intc.c133
-rw-r--r--arch/avr32/mach-at32ap/intc.h327
-rw-r--r--arch/avr32/mach-at32ap/pio.c118
-rw-r--r--arch/avr32/mach-at32ap/pio.h178
-rw-r--r--arch/avr32/mach-at32ap/sm.c289
-rw-r--r--arch/avr32/mach-at32ap/sm.h240
-rw-r--r--arch/avr32/mm/Makefile6
-rw-r--r--arch/avr32/mm/cache.c150
-rw-r--r--arch/avr32/mm/clear_page.S25
-rw-r--r--arch/avr32/mm/copy_page.S28
-rw-r--r--arch/avr32/mm/dma-coherent.c139
-rw-r--r--arch/avr32/mm/fault.c315
-rw-r--r--arch/avr32/mm/init.c480
-rw-r--r--arch/avr32/mm/ioremap.c197
-rw-r--r--arch/avr32/mm/tlb.c380
-rw-r--r--arch/frv/Kconfig12
-rw-r--r--arch/frv/kernel/Makefile5
-rw-r--r--arch/frv/kernel/irq-mb93091.c157
-rw-r--r--arch/frv/kernel/irq-mb93093.c115
-rw-r--r--arch/frv/kernel/irq-mb93493.c160
-rw-r--r--arch/frv/kernel/irq-routing.c291
-rw-r--r--arch/frv/kernel/irq.c741
-rw-r--r--arch/frv/kernel/setup.c1
-rw-r--r--arch/frv/kernel/time.c1
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c1
-rw-r--r--arch/frv/mm/init.c2
-rw-r--r--arch/h8300/mm/init.c2
-rw-r--r--arch/i386/Kconfig35
-rw-r--r--arch/i386/Makefile8
-rw-r--r--arch/i386/boot/edd.S97
-rw-r--r--arch/i386/boot/setup.S4
-rw-r--r--arch/i386/defconfig1063
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/acpi/Makefile2
-rw-r--r--arch/i386/kernel/acpi/boot.c181
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c6
-rw-r--r--arch/i386/kernel/apic.c31
-rw-r--r--arch/i386/kernel/apm.c26
-rw-r--r--arch/i386/kernel/cpu/amd.c7
-rw-r--r--arch/i386/kernel/cpu/centaur.c24
-rw-r--r--arch/i386/kernel/cpu/common.c8
-rw-r--r--arch/i386/kernel/cpu/cpu.h2
-rw-r--r--arch/i386/kernel/cpu/cyrix.c42
-rw-r--r--arch/i386/kernel/cpu/intel.c3
-rw-r--r--arch/i386/kernel/cpu/mcheck/Makefile2
-rw-r--r--arch/i386/kernel/cpu/mcheck/p4.c26
-rw-r--r--arch/i386/kernel/cpu/mcheck/therm_throt.c180
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c4
-rw-r--r--arch/i386/kernel/cpu/nexgen.c9
-rw-r--r--arch/i386/kernel/cpu/proc.c4
-rw-r--r--arch/i386/kernel/cpu/rise.c4
-rw-r--r--arch/i386/kernel/cpu/transmeta.c7
-rw-r--r--arch/i386/kernel/cpu/umc.c7
-rw-r--r--arch/i386/kernel/crash.c22
-rw-r--r--arch/i386/kernel/efi_stub.S1
-rw-r--r--arch/i386/kernel/entry.S110
-rw-r--r--arch/i386/kernel/head.S67
-rw-r--r--arch/i386/kernel/i8259.c6
-rw-r--r--arch/i386/kernel/io_apic.c125
-rw-r--r--arch/i386/kernel/machine_kexec.c140
-rw-r--r--arch/i386/kernel/mca.c8
-rw-r--r--arch/i386/kernel/microcode.c774
-rw-r--r--arch/i386/kernel/mpparse.c70
-rw-r--r--arch/i386/kernel/nmi.c940
-rw-r--r--arch/i386/kernel/process.c14
-rw-r--r--arch/i386/kernel/ptrace.c10
-rw-r--r--arch/i386/kernel/reboot.c12
-rw-r--r--arch/i386/kernel/relocate_kernel.S162
-rw-r--r--arch/i386/kernel/semaphore.c134
-rw-r--r--arch/i386/kernel/setup.c408
-rw-r--r--arch/i386/kernel/smp.c66
-rw-r--r--arch/i386/kernel/smpboot.c25
-rw-r--r--arch/i386/kernel/srat.c102
-rw-r--r--arch/i386/kernel/stacktrace.c98
-rw-r--r--arch/i386/kernel/syscall_table.S1
-rw-r--r--arch/i386/kernel/time.c73
-rw-r--r--arch/i386/kernel/time_hpet.c37
-rw-r--r--arch/i386/kernel/topology.c21
-rw-r--r--arch/i386/kernel/traps.c242
-rw-r--r--arch/i386/kernel/tsc.c2
-rw-r--r--arch/i386/kernel/vmlinux.lds.S12
-rw-r--r--arch/i386/lib/Makefile2
-rw-r--r--arch/i386/lib/semaphore.S217
-rw-r--r--arch/i386/mach-generic/bigsmp.c1
-rw-r--r--arch/i386/mach-generic/es7000.c1
-rw-r--r--arch/i386/mach-generic/probe.c60
-rw-r--r--arch/i386/mach-generic/summit.c1
-rw-r--r--arch/i386/mach-voyager/voyager_thread.c1
-rw-r--r--arch/i386/mm/boot_ioremap.c7
-rw-r--r--arch/i386/mm/discontig.c105
-rw-r--r--arch/i386/mm/extable.c2
-rw-r--r--arch/i386/mm/fault.c25
-rw-r--r--arch/i386/mm/highmem.c2
-rw-r--r--arch/i386/mm/init.c82
-rw-r--r--arch/i386/mm/pgtable.c30
-rw-r--r--arch/i386/oprofile/nmi_int.c88
-rw-r--r--arch/i386/oprofile/nmi_timer_int.c35
-rw-r--r--arch/i386/oprofile/op_model_athlon.c54
-rw-r--r--arch/i386/oprofile/op_model_p4.c152
-rw-r--r--arch/i386/oprofile/op_model_ppro.c65
-rw-r--r--arch/i386/oprofile/op_x86_model.h1
-rw-r--r--arch/i386/pci/Makefile2
-rw-r--r--arch/i386/pci/common.c4
-rw-r--r--arch/i386/pci/direct.c25
-rw-r--r--arch/i386/pci/early.c52
-rw-r--r--arch/i386/pci/init.c9
-rw-r--r--arch/i386/pci/mmconfig.c41
-rw-r--r--arch/i386/pci/pci.h7
-rw-r--r--arch/i386/power/swsusp.S2
-rw-r--r--arch/ia64/Kconfig20
-rw-r--r--arch/ia64/ia32/sys_ia32.c2
-rw-r--r--arch/ia64/kernel/Makefile5
-rw-r--r--arch/ia64/kernel/acpi.c13
-rw-r--r--arch/ia64/kernel/entry.S4
-rw-r--r--arch/ia64/kernel/esi.c205
-rw-r--r--arch/ia64/kernel/esi_stub.S96
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c4
-rw-r--r--arch/ia64/kernel/kprobes.c61
-rw-r--r--arch/ia64/kernel/mca.c234
-rw-r--r--arch/ia64/kernel/mca_asm.S9
-rw-r--r--arch/ia64/kernel/mca_drv.c54
-rw-r--r--arch/ia64/kernel/mca_drv.h4
-rw-r--r--arch/ia64/kernel/numa.c34
-rw-r--r--arch/ia64/kernel/perfmon.c114
-rw-r--r--arch/ia64/kernel/salinfo.c4
-rw-r--r--arch/ia64/kernel/setup.c41
-rw-r--r--arch/ia64/kernel/smpboot.c24
-rw-r--r--arch/ia64/kernel/topology.c4
-rw-r--r--arch/ia64/kernel/uncached.c2
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S8
-rw-r--r--arch/ia64/mm/contig.c84
-rw-r--r--arch/ia64/mm/discontig.c72
-rw-r--r--arch/ia64/mm/init.c12
-rw-r--r--arch/ia64/pci/pci.c3
-rw-r--r--arch/ia64/sn/kernel/bte.c3
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c3
-rw-r--r--arch/m32r/mm/init.c2
-rw-r--r--arch/m68knommu/mm/init.c2
-rw-r--r--arch/mips/Kconfig46
-rw-r--r--arch/mips/Makefile8
-rw-r--r--arch/mips/au1000/common/dbdma.c10
-rw-r--r--arch/mips/au1000/db1x00/Makefile1
-rw-r--r--arch/mips/au1000/db1x00/mirage_ts.c260
-rw-r--r--arch/mips/basler/excite/excite_device.c16
-rw-r--r--arch/mips/basler/excite/excite_fpga.h80
-rw-r--r--arch/mips/configs/atlas_defconfig3
-rw-r--r--arch/mips/configs/bigsur_defconfig1
-rw-r--r--arch/mips/configs/capcella_defconfig1
-rw-r--r--arch/mips/configs/cobalt_defconfig3
-rw-r--r--arch/mips/configs/db1000_defconfig1
-rw-r--r--arch/mips/configs/db1100_defconfig1
-rw-r--r--arch/mips/configs/db1200_defconfig1
-rw-r--r--arch/mips/configs/db1500_defconfig1
-rw-r--r--arch/mips/configs/db1550_defconfig1
-rw-r--r--arch/mips/configs/ddb5477_defconfig1
-rw-r--r--arch/mips/configs/decstation_defconfig1
-rw-r--r--arch/mips/configs/e55_defconfig11
-rw-r--r--arch/mips/configs/emma2rh_defconfig1
-rw-r--r--arch/mips/configs/ev64120_defconfig1
-rw-r--r--arch/mips/configs/excite_defconfig1
-rw-r--r--arch/mips/configs/ip22_defconfig3
-rw-r--r--arch/mips/configs/ip27_defconfig3
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/it8172_defconfig1
-rw-r--r--arch/mips/configs/ivr_defconfig1
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig3
-rw-r--r--arch/mips/configs/jmr3927_defconfig1
-rw-r--r--arch/mips/configs/lasat200_defconfig3
-rw-r--r--arch/mips/configs/malta_defconfig3
-rw-r--r--arch/mips/configs/mipssim_defconfig1
-rw-r--r--arch/mips/configs/mpc30x_defconfig13
-rw-r--r--arch/mips/configs/ocelot_3_defconfig1
-rw-r--r--arch/mips/configs/ocelot_c_defconfig3
-rw-r--r--arch/mips/configs/ocelot_defconfig3
-rw-r--r--arch/mips/configs/ocelot_g_defconfig3
-rw-r--r--arch/mips/configs/pb1100_defconfig1
-rw-r--r--arch/mips/configs/pb1500_defconfig1
-rw-r--r--arch/mips/configs/pb1550_defconfig1
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig1
-rw-r--r--arch/mips/configs/pnx8550-v2pci_defconfig1
-rw-r--r--arch/mips/configs/qemu_defconfig3
-rw-r--r--arch/mips/configs/rbhma4500_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig3
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig1
-rw-r--r--arch/mips/configs/sead_defconfig1
-rw-r--r--arch/mips/configs/tb0226_defconfig1
-rw-r--r--arch/mips/configs/tb0229_defconfig1
-rw-r--r--arch/mips/configs/tb0287_defconfig1
-rw-r--r--arch/mips/configs/workpad_defconfig11
-rw-r--r--arch/mips/configs/wrppmc_defconfig1
-rw-r--r--arch/mips/configs/yosemite_defconfig1
-rw-r--r--arch/mips/defconfig5
-rw-r--r--arch/mips/galileo-boards/ev96100/Makefile9
-rw-r--r--arch/mips/galileo-boards/ev96100/init.c173
-rw-r--r--arch/mips/galileo-boards/ev96100/irq.c77
-rw-r--r--arch/mips/galileo-boards/ev96100/puts.c138
-rw-r--r--arch/mips/galileo-boards/ev96100/reset.c70
-rw-r--r--arch/mips/galileo-boards/ev96100/setup.c159
-rw-r--r--arch/mips/galileo-boards/ev96100/time.c88
-rw-r--r--arch/mips/kernel/cpu-probe.c62
-rw-r--r--arch/mips/kernel/irixsig.c63
-rw-r--r--arch/mips/kernel/linux32.c10
-rw-r--r--arch/mips/kernel/process.c257
-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.S6
-rw-r--r--arch/mips/kernel/scall64-o32.S4
-rw-r--r--arch/mips/kernel/setup.c439
-rw-r--r--arch/mips/kernel/signal.c8
-rw-r--r--arch/mips/kernel/signal32.c7
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smtc-asm.S2
-rw-r--r--arch/mips/kernel/syscall.c4
-rw-r--r--arch/mips/kernel/traps.c146
-rw-r--r--arch/mips/kernel/vpe.c6
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c105
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c2
-rw-r--r--arch/mips/mips-boards/generic/time.c64
-rw-r--r--arch/mips/mm/c-r3k.c2
-rw-r--r--arch/mips/mm/c-r4k.c28
-rw-r--r--arch/mips/mm/c-sb1.c58
-rw-r--r--arch/mips/mm/c-tx39.c4
-rw-r--r--arch/mips/mm/cache.c18
-rw-r--r--arch/mips/mm/fault.c2
-rw-r--r--arch/mips/mm/init.c4
-rw-r--r--arch/mips/mm/tlb-r4k.c21
-rw-r--r--arch/mips/pci/Makefile4
-rw-r--r--arch/mips/pci/fixup-atlas.c20
-rw-r--r--arch/mips/pci/fixup-ev96100.c48
-rw-r--r--arch/mips/pci/ops-au1000.c2
-rw-r--r--arch/mips/pci/ops-gt96100.c169
-rw-r--r--arch/mips/pci/pci-ev96100.c63
-rw-r--r--arch/mips/pci/pci-ip27.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c3
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c19
-rw-r--r--arch/mips/sibyte/sb1250/irq.c17
-rw-r--r--arch/parisc/mm/init.c4
-rw-r--r--arch/powerpc/Kconfig7
-rw-r--r--arch/powerpc/kernel/swsusp_32.S4
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c2
-rw-r--r--arch/powerpc/mm/mem.c51
-rw-r--r--arch/powerpc/mm/numa.c159
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c3
-rw-r--r--arch/powerpc/platforms/pseries/hvCall_inst.c2
-rw-r--r--arch/powerpc/sysdev/mpic.c2
-rw-r--r--arch/ppc/Kconfig3
-rw-r--r--arch/ppc/mm/init.c23
-rw-r--r--arch/s390/appldata/appldata_mem.c3
-rw-r--r--arch/s390/hypfs/inode.c7
-rw-r--r--arch/s390/kernel/compat_linux.c2
-rw-r--r--arch/s390/kernel/debug.c2
-rw-r--r--arch/s390/kernel/stacktrace.c17
-rw-r--r--arch/s390/mm/cmm.c205
-rw-r--r--arch/sh/Kconfig173
-rw-r--r--arch/sh/Kconfig.debug36
-rw-r--r--arch/sh/Makefile40
-rw-r--r--arch/sh/boards/adx/Makefile6
-rw-r--r--arch/sh/boards/adx/irq.c31
-rw-r--r--arch/sh/boards/adx/setup.c56
-rw-r--r--arch/sh/boards/bigsur/irq.c47
-rw-r--r--arch/sh/boards/bigsur/setup.c47
-rw-r--r--arch/sh/boards/cat68701/Makefile6
-rw-r--r--arch/sh/boards/cat68701/irq.c28
-rw-r--r--arch/sh/boards/cat68701/setup.c85
-rw-r--r--arch/sh/boards/cqreek/Makefile6
-rw-r--r--arch/sh/boards/cqreek/irq.c128
-rw-r--r--arch/sh/boards/cqreek/setup.c100
-rw-r--r--arch/sh/boards/dmida/Makefile7
-rw-r--r--arch/sh/boards/dmida/mach.c59
-rw-r--r--arch/sh/boards/dreamcast/irq.c15
-rw-r--r--arch/sh/boards/dreamcast/rtc.c22
-rw-r--r--arch/sh/boards/dreamcast/setup.c40
-rw-r--r--arch/sh/boards/ec3104/setup.c49
-rw-r--r--arch/sh/boards/harp/Makefile8
-rw-r--r--arch/sh/boards/harp/irq.c147
-rw-r--r--arch/sh/boards/harp/led.c51
-rw-r--r--arch/sh/boards/harp/mach.c62
-rw-r--r--arch/sh/boards/harp/pcidma.c42
-rw-r--r--arch/sh/boards/harp/setup.c90
-rw-r--r--arch/sh/boards/hp6xx/Makefile5
-rw-r--r--arch/sh/boards/hp6xx/hp6xx_apm.c123
-rw-r--r--arch/sh/boards/hp6xx/pm.c88
-rw-r--r--arch/sh/boards/hp6xx/pm_wakeup.S58
-rw-r--r--arch/sh/boards/hp6xx/setup.c62
-rw-r--r--arch/sh/boards/landisk/Makefile5
-rw-r--r--arch/sh/boards/landisk/io.c250
-rw-r--r--arch/sh/boards/landisk/irq.c99
-rw-r--r--arch/sh/boards/landisk/landisk_pwb.c348
-rw-r--r--arch/sh/boards/landisk/rtc.c93
-rw-r--r--arch/sh/boards/landisk/setup.c177
-rw-r--r--arch/sh/boards/mpc1211/rtc.c4
-rw-r--r--arch/sh/boards/mpc1211/setup.c71
-rw-r--r--arch/sh/boards/overdrive/Makefile8
-rw-r--r--arch/sh/boards/overdrive/fpga.c133
-rw-r--r--arch/sh/boards/overdrive/galileo.c587
-rw-r--r--arch/sh/boards/overdrive/io.c172
-rw-r--r--arch/sh/boards/overdrive/irq.c191
-rw-r--r--arch/sh/boards/overdrive/led.c58
-rw-r--r--arch/sh/boards/overdrive/mach.c62
-rw-r--r--arch/sh/boards/overdrive/pcidma.c46
-rw-r--r--arch/sh/boards/overdrive/setup.c36
-rw-r--r--arch/sh/boards/renesas/edosk7705/Makefile4
-rw-r--r--arch/sh/boards/renesas/edosk7705/setup.c29
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/Kconfig12
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/Makefile6
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/io.c252
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/irq.c6
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/led.c26
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/mach.c54
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/setup.c94
-rw-r--r--arch/sh/boards/renesas/r7780rp/Kconfig14
-rw-r--r--arch/sh/boards/renesas/r7780rp/Makefile6
-rw-r--r--arch/sh/boards/renesas/r7780rp/io.c301
-rw-r--r--arch/sh/boards/renesas/r7780rp/irq.c117
-rw-r--r--arch/sh/boards/renesas/r7780rp/led.c45
-rw-r--r--arch/sh/boards/renesas/r7780rp/setup.c163
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/Kconfig12
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/Makefile8
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/io.c191
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/irq.c6
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/led.c11
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/mach.c69
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/setup.c139
-rw-r--r--arch/sh/boards/renesas/sh7710voipgw/Makefile1
-rw-r--r--arch/sh/boards/renesas/sh7710voipgw/setup.c109
-rw-r--r--arch/sh/boards/renesas/systemh/io.c163
-rw-r--r--arch/sh/boards/renesas/systemh/irq.c10
-rw-r--r--arch/sh/boards/renesas/systemh/setup.c30
-rw-r--r--arch/sh/boards/saturn/setup.c14
-rw-r--r--arch/sh/boards/se/7300/io.c8
-rw-r--r--arch/sh/boards/se/7300/irq.c2
-rw-r--r--arch/sh/boards/se/7300/led.c18
-rw-r--r--arch/sh/boards/se/7300/setup.c20
-rw-r--r--arch/sh/boards/se/73180/io.c6
-rw-r--r--arch/sh/boards/se/73180/irq.c9
-rw-r--r--arch/sh/boards/se/73180/led.c15
-rw-r--r--arch/sh/boards/se/73180/setup.c22
-rw-r--r--arch/sh/boards/se/7343/Makefile7
-rw-r--r--arch/sh/boards/se/7343/io.c275
-rw-r--r--arch/sh/boards/se/7343/irq.c193
-rw-r--r--arch/sh/boards/se/7343/led.c46
-rw-r--r--arch/sh/boards/se/7343/setup.c84
-rw-r--r--arch/sh/boards/se/770x/Makefile4
-rw-r--r--arch/sh/boards/se/770x/io.c61
-rw-r--r--arch/sh/boards/se/770x/irq.c2
-rw-r--r--arch/sh/boards/se/770x/led.c17
-rw-r--r--arch/sh/boards/se/770x/mach.c67
-rw-r--r--arch/sh/boards/se/770x/setup.c65
-rw-r--r--arch/sh/boards/se/7751/Makefile4
-rw-r--r--arch/sh/boards/se/7751/io.c171
-rw-r--r--arch/sh/boards/se/7751/irq.c2
-rw-r--r--arch/sh/boards/se/7751/led.c18
-rw-r--r--arch/sh/boards/se/7751/mach.c54
-rw-r--r--arch/sh/boards/se/7751/setup.c109
-rw-r--r--arch/sh/boards/sh03/rtc.c9
-rw-r--r--arch/sh/boards/sh03/setup.c49
-rw-r--r--arch/sh/boards/sh2000/Makefile6
-rw-r--r--arch/sh/boards/sh2000/setup.c70
-rw-r--r--arch/sh/boards/shmin/Makefile5
-rw-r--r--arch/sh/boards/shmin/setup.c41
-rw-r--r--arch/sh/boards/snapgear/io.c145
-rw-r--r--arch/sh/boards/snapgear/rtc.c34
-rw-r--r--arch/sh/boards/snapgear/setup.c115
-rw-r--r--arch/sh/boards/superh/microdev/irq.c39
-rw-r--r--arch/sh/boards/superh/microdev/setup.c113
-rw-r--r--arch/sh/boards/titan/Makefile5
-rw-r--r--arch/sh/boards/titan/io.c126
-rw-r--r--arch/sh/boards/titan/setup.c48
-rw-r--r--arch/sh/boards/unknown/setup.c13
-rw-r--r--arch/sh/boot/compressed/Makefile11
-rw-r--r--arch/sh/cchips/Kconfig6
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/io.c20
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/setup.c10
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/setup.c6
-rw-r--r--arch/sh/cchips/voyagergx/irq.c23
-rw-r--r--arch/sh/cchips/voyagergx/setup.c2
-rw-r--r--arch/sh/configs/landisk_defconfig1373
-rw-r--r--arch/sh/configs/r7780rp_defconfig1099
-rw-r--r--arch/sh/configs/se73180_defconfig1
-rw-r--r--arch/sh/configs/se7343_defconfig997
-rw-r--r--arch/sh/configs/sh7710voipgw_defconfig913
-rw-r--r--arch/sh/configs/shmin_defconfig827
-rw-r--r--arch/sh/configs/titan_defconfig1367
-rw-r--r--arch/sh/drivers/dma/Kconfig3
-rw-r--r--arch/sh/drivers/dma/dma-g2.c54
-rw-r--r--arch/sh/drivers/dma/dma-pvr2.c5
-rw-r--r--arch/sh/drivers/dma/dma-sh.c19
-rw-r--r--arch/sh/drivers/pci/Makefile6
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c38
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c45
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c24
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c38
-rw-r--r--arch/sh/drivers/pci/ops-bigsur.c18
-rw-r--r--arch/sh/drivers/pci/ops-landisk.c68
-rw-r--r--arch/sh/drivers/pci/ops-r7780rp.c75
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c13
-rw-r--r--arch/sh/drivers/pci/ops-sh4.c164
-rw-r--r--arch/sh/drivers/pci/ops-snapgear.c21
-rw-r--r--arch/sh/drivers/pci/ops-titan.c83
-rw-r--r--arch/sh/drivers/pci/pci-auto.c48
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h180
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c326
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.h174
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c139
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.h94
-rw-r--r--arch/sh/drivers/pci/pci-st40.c19
-rw-r--r--arch/sh/drivers/pci/pci.c105
-rw-r--r--arch/sh/kernel/Makefile5
-rw-r--r--arch/sh/kernel/apm.c539
-rw-r--r--arch/sh/kernel/cf-enabler.c12
-rw-r--r--arch/sh/kernel/cpu/Makefile1
-rw-r--r--arch/sh/kernel/cpu/clock.c19
-rw-r--r--arch/sh/kernel/cpu/init.c21
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile5
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c6
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c14
-rw-r--r--arch/sh/kernel/cpu/irq/maskreg.c (renamed from arch/sh/boards/adx/irq_maskreg.c)61
-rw-r--r--arch/sh/kernel/cpu/irq/pint.c8
-rw-r--r--arch/sh/kernel/cpu/rtc.c128
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile13
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7706.c84
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S54
-rw-r--r--arch/sh/kernel/cpu/sh3/probe.c6
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7300.c43
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c48
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7708.c43
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7709.c53
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c43
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile10
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S176
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c138
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh4-202.c43
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh73180.c43
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7343.c43
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c48
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c53
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7770.c53
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7780.c79
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c543
-rw-r--r--arch/sh/kernel/early_printk.c106
-rw-r--r--arch/sh/kernel/entry.S333
-rw-r--r--arch/sh/kernel/head.S43
-rw-r--r--arch/sh/kernel/io.c67
-rw-r--r--arch/sh/kernel/irq.c168
-rw-r--r--arch/sh/kernel/kgdb_stub.c33
-rw-r--r--arch/sh/kernel/machine_kexec.c6
-rw-r--r--arch/sh/kernel/pm.c88
-rw-r--r--arch/sh/kernel/process.c28
-rw-r--r--arch/sh/kernel/ptrace.c1
-rw-r--r--arch/sh/kernel/semaphore.c2
-rw-r--r--arch/sh/kernel/setup.c117
-rw-r--r--arch/sh/kernel/sh_ksyms.c32
-rw-r--r--arch/sh/kernel/signal.c158
-rw-r--r--arch/sh/kernel/sys_sh.c56
-rw-r--r--arch/sh/kernel/syscalls.S353
-rw-r--r--arch/sh/kernel/time.c68
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c24
-rw-r--r--arch/sh/kernel/traps.c184
-rw-r--r--arch/sh/kernel/vmlinux.lds.S17
-rw-r--r--arch/sh/kernel/vsyscall/Makefile36
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall-note.S25
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall-sigreturn.S39
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall-syscall.S10
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall-trapa.S42
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c150
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.lds.S74
-rw-r--r--arch/sh/lib/checksum.S3
-rw-r--r--arch/sh/lib/memcpy-sh4.S4
-rw-r--r--arch/sh/lib/memset.S1
-rw-r--r--arch/sh/math-emu/Makefile1
-rw-r--r--arch/sh/math-emu/math.c624
-rw-r--r--arch/sh/math-emu/sfp-util.h72
-rw-r--r--arch/sh/mm/Kconfig78
-rw-r--r--arch/sh/mm/Makefile16
-rw-r--r--arch/sh/mm/cache-debugfs.c147
-rw-r--r--arch/sh/mm/cache-sh4.c685
-rw-r--r--arch/sh/mm/cache-sh7705.c19
-rw-r--r--arch/sh/mm/clear_page.S99
-rw-r--r--arch/sh/mm/consistent.c2
-rw-r--r--arch/sh/mm/fault.c207
-rw-r--r--arch/sh/mm/hugetlbpage.c52
-rw-r--r--arch/sh/mm/init.c32
-rw-r--r--arch/sh/mm/ioremap.c17
-rw-r--r--arch/sh/mm/pg-nommu.c17
-rw-r--r--arch/sh/mm/pg-sh4.c24
-rw-r--r--arch/sh/mm/pmb.c400
-rw-r--r--arch/sh/mm/tlb-flush.c134
-rw-r--r--arch/sh/mm/tlb-sh4.c8
-rw-r--r--arch/sh/oprofile/Makefile4
-rw-r--r--arch/sh/tools/mach-types10
-rw-r--r--arch/sh64/mm/init.c2
-rw-r--r--arch/sparc/mm/srmmu.c2
-rw-r--r--arch/sparc/mm/sun4c.c2
-rw-r--r--arch/sparc64/defconfig38
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c2
-rw-r--r--arch/sparc64/mm/init.c3
-rw-r--r--arch/sparc64/solaris/misc.c20
-rw-r--r--arch/sparc64/solaris/socksys.c6
-rw-r--r--arch/um/Makefile-x86_647
-rw-r--r--arch/um/drivers/chan_kern.c18
-rw-r--r--arch/um/drivers/daemon.h2
-rw-r--r--arch/um/drivers/daemon_kern.c2
-rw-r--r--arch/um/drivers/daemon_user.c2
-rw-r--r--arch/um/drivers/fd.c4
-rw-r--r--arch/um/drivers/hostaudio_kern.c4
-rw-r--r--arch/um/drivers/line.c6
-rw-r--r--arch/um/drivers/mcast.h2
-rw-r--r--arch/um/drivers/mcast_kern.c2
-rw-r--r--arch/um/drivers/mcast_user.c2
-rw-r--r--arch/um/drivers/mconsole_kern.c2
-rw-r--r--arch/um/drivers/mconsole_user.c7
-rw-r--r--arch/um/drivers/mmapper_kern.c4
-rw-r--r--arch/um/drivers/net_kern.c39
-rw-r--r--arch/um/drivers/null.c4
-rw-r--r--arch/um/drivers/pcap_kern.c4
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_user.c4
-rw-r--r--arch/um/drivers/pty.c6
-rw-r--r--arch/um/drivers/random.c2
-rw-r--r--arch/um/drivers/slip.h2
-rw-r--r--arch/um/drivers/slip_kern.c2
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp.h2
-rw-r--r--arch/um/drivers/slirp_kern.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c4
-rw-r--r--arch/um/drivers/stdio_console.c2
-rw-r--r--arch/um/drivers/tty.c4
-rw-r--r--arch/um/drivers/xterm.c4
-rw-r--r--arch/um/include/chan_kern.h6
-rw-r--r--arch/um/include/chan_user.h6
-rw-r--r--arch/um/include/kern_util.h3
-rw-r--r--arch/um/include/line.h4
-rw-r--r--arch/um/include/longjmp.h5
-rw-r--r--arch/um/include/net_kern.h4
-rw-r--r--arch/um/include/net_user.h1
-rw-r--r--arch/um/include/os.h18
-rw-r--r--arch/um/include/registers.h3
-rw-r--r--arch/um/include/skas/skas.h3
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h22
-rw-r--r--arch/um/include/sysdep-i386/signal.h27
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h24
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h43
-rw-r--r--arch/um/include/sysdep-x86_64/sc.h2
-rw-r--r--arch/um/include/sysdep-x86_64/signal.h29
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/exec.c4
-rw-r--r--arch/um/kernel/gmon_syms.c13
-rw-r--r--arch/um/kernel/irq.c34
-rw-r--r--arch/um/kernel/ksyms.c3
-rw-r--r--arch/um/kernel/mem.c10
-rw-r--r--arch/um/kernel/process.c (renamed from arch/um/kernel/process_kern.c)36
-rw-r--r--arch/um/kernel/reboot.c13
-rw-r--r--arch/um/kernel/skas/Makefile3
-rw-r--r--arch/um/kernel/skas/exec.c30
-rw-r--r--arch/um/kernel/skas/exec_kern.c41
-rw-r--r--arch/um/kernel/skas/mmu.c2
-rw-r--r--arch/um/kernel/skas/process.c217
-rw-r--r--arch/um/kernel/skas/process_kern.c533
-rw-r--r--arch/um/kernel/time.c14
-rw-r--r--arch/um/kernel/tlb.c370
-rw-r--r--arch/um/kernel/trap.c28
-rw-r--r--arch/um/kernel/um_arch.c2
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/drivers/etap.h2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c22
-rw-r--r--arch/um/os-Linux/irq.c2
-rw-r--r--arch/um/os-Linux/main.c34
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/process.c13
-rw-r--r--arch/um/os-Linux/sigio.c103
-rw-r--r--arch/um/os-Linux/signal.c38
-rw-r--r--arch/um/os-Linux/skas/process.c92
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c17
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c15
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c17
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c16
-rw-r--r--arch/um/os-Linux/time.c22
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/uaccess.c3
-rw-r--r--arch/um/os-Linux/util.c5
-rw-r--r--arch/um/sys-i386/Makefile4
-rw-r--r--arch/um/sys-i386/bugs.c9
-rw-r--r--arch/um/sys-i386/ldt.c3
-rw-r--r--arch/um/sys-i386/ptrace_user.c5
-rw-r--r--arch/um/sys-i386/setjmp.S58
-rw-r--r--arch/um/sys-x86_64/Makefile4
-rw-r--r--arch/um/sys-x86_64/setjmp.S54
-rw-r--r--arch/x86_64/Kconfig53
-rw-r--r--arch/x86_64/Makefile10
-rw-r--r--arch/x86_64/boot/compressed/Makefile3
-rw-r--r--arch/x86_64/boot/setup.S4
-rw-r--r--arch/x86_64/defconfig109
-rw-r--r--arch/x86_64/ia32/ia32_aout.c8
-rw-r--r--arch/x86_64/ia32/ia32_signal.c53
-rw-r--r--arch/x86_64/ia32/ia32entry.S9
-rw-r--r--arch/x86_64/ia32/ptrace32.c10
-rw-r--r--arch/x86_64/ia32/sys_ia32.c54
-rw-r--r--arch/x86_64/kernel/Makefile9
-rw-r--r--arch/x86_64/kernel/aperture.c25
-rw-r--r--arch/x86_64/kernel/apic.c229
-rw-r--r--arch/x86_64/kernel/crash.c26
-rw-r--r--arch/x86_64/kernel/e820.c291
-rw-r--r--arch/x86_64/kernel/early-quirks.c122
-rw-r--r--arch/x86_64/kernel/early_printk.c20
-rw-r--r--arch/x86_64/kernel/entry.S63
-rw-r--r--arch/x86_64/kernel/genapic_cluster.c1
-rw-r--r--arch/x86_64/kernel/genapic_flat.c5
-rw-r--r--arch/x86_64/kernel/head.S15
-rw-r--r--arch/x86_64/kernel/head64.c44
-rw-r--r--arch/x86_64/kernel/i8259.c15
-rw-r--r--arch/x86_64/kernel/io_apic.c482
-rw-r--r--arch/x86_64/kernel/ioport.c1
-rw-r--r--arch/x86_64/kernel/irq.c12
-rw-r--r--arch/x86_64/kernel/machine_kexec.c99
-rw-r--r--arch/x86_64/kernel/mce.c29
-rw-r--r--arch/x86_64/kernel/mce_intel.c30
-rw-r--r--arch/x86_64/kernel/mpparse.c238
-rw-r--r--arch/x86_64/kernel/nmi.c840
-rw-r--r--arch/x86_64/kernel/pci-calgary.c142
-rw-r--r--arch/x86_64/kernel/pci-dma.c7
-rw-r--r--arch/x86_64/kernel/pci-gart.c3
-rw-r--r--arch/x86_64/kernel/pci-nommu.c1
-rw-r--r--arch/x86_64/kernel/process.c110
-rw-r--r--arch/x86_64/kernel/ptrace.c29
-rw-r--r--arch/x86_64/kernel/relocate_kernel.S171
-rw-r--r--arch/x86_64/kernel/setup.c249
-rw-r--r--arch/x86_64/kernel/setup64.c45
-rw-r--r--arch/x86_64/kernel/signal.c87
-rw-r--r--arch/x86_64/kernel/smp.c23
-rw-r--r--arch/x86_64/kernel/smpboot.c17
-rw-r--r--arch/x86_64/kernel/stacktrace.c220
-rw-r--r--arch/x86_64/kernel/suspend_asm.S2
-rw-r--r--arch/x86_64/kernel/tce.c12
-rw-r--r--arch/x86_64/kernel/time.c131
-rw-r--r--arch/x86_64/kernel/trampoline.S2
-rw-r--r--arch/x86_64/kernel/traps.c204
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S25
-rw-r--r--arch/x86_64/kernel/vsmp.c3
-rw-r--r--arch/x86_64/kernel/vsyscall.c98
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c1
-rw-r--r--arch/x86_64/lib/Makefile2
-rw-r--r--arch/x86_64/lib/clear_page.S47
-rw-r--r--arch/x86_64/lib/copy_page.S53
-rw-r--r--arch/x86_64/lib/copy_user.S153
-rw-r--r--arch/x86_64/lib/csum-copy.S26
-rw-r--r--arch/x86_64/lib/getuser.S32
-rw-r--r--arch/x86_64/lib/iomap_copy.S10
-rw-r--r--arch/x86_64/lib/memcpy.S69
-rw-r--r--arch/x86_64/lib/memset.S79
-rw-r--r--arch/x86_64/lib/putuser.S32
-rw-r--r--arch/x86_64/lib/rwlock.S38
-rw-r--r--arch/x86_64/lib/thunk.S43
-rw-r--r--arch/x86_64/mm/fault.c28
-rw-r--r--arch/x86_64/mm/init.c129
-rw-r--r--arch/x86_64/mm/k8topology.c6
-rw-r--r--arch/x86_64/mm/numa.c32
-rw-r--r--arch/x86_64/mm/pageattr.c24
-rw-r--r--arch/x86_64/mm/srat.c19
-rw-r--r--arch/x86_64/pci/Makefile3
-rw-r--r--arch/x86_64/pci/mmconfig.c44
737 files changed, 38994 insertions, 16687 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 213c7850d5f..2b36afd8e96 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -381,7 +381,7 @@ config ALPHA_EV56
config ALPHA_EV56
prompt "EV56 CPU (speed >= 333MHz)?"
- depends on ALPHA_NORITAKE && ALPHA_PRIMO
+ depends on ALPHA_NORITAKE || ALPHA_PRIMO
config ALPHA_EV56
prompt "EV56 CPU (speed >= 400MHz)?"
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 917dad1b74c..550f4907d61 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -270,7 +270,7 @@ callback_init(void * kernel_end)
void
paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
unsigned long dma_pfn, high_pfn;
dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index cce26576999..337c01c4ac3 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
/*
* USB Device Controller
*/
-static void corgi_udc_command(int cmd)
-{
- switch(cmd) {
- case PXA2XX_UDC_CMD_CONNECT:
- GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
- break;
- case PXA2XX_UDC_CMD_DISCONNECT:
- GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
- break;
- }
-}
-
static struct pxa2xx_udc_mach_info udc_info __initdata = {
/* no connect GPIO; corgi can't tell connection status */
- .udc_command = corgi_udc_command,
+ .gpio_pullup = CORGI_GPIO_USB_PULLUP,
};
@@ -350,7 +338,6 @@ static void __init corgi_init(void)
corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
- pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
pxa_set_udc_info(&udc_info);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 88a999df0ab..591fc3187c7 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -177,7 +177,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_kernel(pmd));
+ pte_free_kernel(pmd_page_vaddr(pmd));
}
addr += PGDIR_SIZE;
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 9b815327b6a..7e8096809be 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -26,7 +26,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
new file mode 100644
index 00000000000..5f1694eea84
--- /dev/null
+++ b/arch/avr32/Kconfig
@@ -0,0 +1,196 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux Kernel Configuration"
+
+config AVR32
+ bool
+ default y
+ # With EMBEDDED=n, we get lots of stuff automatically selected
+ # that we usually don't need on AVR32.
+ select EMBEDDED
+ help
+ AVR32 is a high-performance 32-bit RISC microprocessor core,
+ designed for cost-sensitive embedded applications, with particular
+ emphasis on low power consumption and high code density.
+
+ There is an AVR32 Linux project with a web page at
+ http://avr32linux.org/.
+
+config UID16
+ bool
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config HARDIRQS_SW_RESEND
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+config GENERIC_TIME
+ bool
+ default y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_BUST_SPINLOCK
+ bool
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+source "init/Kconfig"
+
+menu "System Type and features"
+
+config SUBARCH_AVR32B
+ bool
+config MMU
+ bool
+config PERFORMANCE_COUNTERS
+ bool
+
+config PLATFORM_AT32AP
+ bool
+ select SUBARCH_AVR32B
+ select MMU
+ select PERFORMANCE_COUNTERS
+
+choice
+ prompt "AVR32 CPU type"
+ default CPU_AT32AP7000
+
+config CPU_AT32AP7000
+ bool "AT32AP7000"
+ select PLATFORM_AT32AP
+endchoice
+
+#
+# CPU Daughterboards for ATSTK1000
+config BOARD_ATSTK1002
+ bool
+
+choice
+ prompt "AVR32 board type"
+ default BOARD_ATSTK1000
+
+config BOARD_ATSTK1000
+ bool "ATSTK1000 evaluation board"
+ select BOARD_ATSTK1002 if CPU_AT32AP7000
+endchoice
+
+choice
+ prompt "Boot loader type"
+ default LOADER_U_BOOT
+
+config LOADER_U_BOOT
+ bool "U-Boot (or similar) bootloader"
+endchoice
+
+config LOAD_ADDRESS
+ hex
+ default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
+
+config ENTRY_ADDRESS
+ hex
+ default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
+
+config PHYS_OFFSET
+ hex
+ default 0x10000000 if CPU_AT32AP7000=y
+
+source "kernel/Kconfig.preempt"
+
+config HAVE_ARCH_BOOTMEM_NODE
+ bool
+ default n
+
+config ARCH_HAVE_MEMORY_PRESENT
+ bool
+ default n
+
+config NEED_NODE_MEMMAP_SIZE
+ bool
+ default n
+
+config ARCH_FLATMEM_ENABLE
+ bool
+ default y
+
+config ARCH_DISCONTIGMEM_ENABLE
+ bool
+ default n
+
+config ARCH_SPARSEMEM_ENABLE
+ bool
+ default n
+
+source "mm/Kconfig"
+
+config OWNERSHIP_TRACE
+ bool "Ownership trace support"
+ default y
+ help
+ Say Y to generate an Ownership Trace message on every context switch,
+ enabling Nexus-compliant debuggers to keep track of the PID of the
+ currently executing task.
+
+# FPU emulation goes here
+
+source "kernel/Kconfig.hz"
+
+config CMDLINE
+ string "Default kernel command line"
+ default ""
+ help
+ If you don't have a boot loader capable of passing a command line string
+ to the kernel, you may specify one here. As a minimum, you should specify
+ the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+
+endmenu
+
+menu "Bus options"
+
+config PCI
+ bool
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/avr32/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/avr32/Kconfig.debug b/arch/avr32/Kconfig.debug
new file mode 100644
index 00000000000..64ace00fe6c
--- /dev/null
+++ b/arch/avr32/Kconfig.debug
@@ -0,0 +1,19 @@
+menu "Kernel hacking"
+
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
+source "lib/Kconfig.debug"
+
+config KPROBES
+ bool "Kprobes"
+ depends on DEBUG_KERNEL
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+endmenu
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
new file mode 100644
index 00000000000..cefc95a7398
--- /dev/null
+++ b/arch/avr32/Makefile
@@ -0,0 +1,84 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2004-2006 Atmel Corporation.
+
+# Default target when executing plain make
+.PHONY: all
+all: uImage vmlinux.elf linux.lst
+
+KBUILD_DEFCONFIG := atstk1002_defconfig
+
+CFLAGS += -pipe -fno-builtin -mno-pic
+AFLAGS += -mrelax -mno-pic
+CFLAGS_MODULE += -mno-relax
+LDFLAGS_vmlinux += --relax
+
+cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000
+
+CFLAGS += $(cpuflags-y)
+AFLAGS += $(cpuflags-y)
+
+CHECKFLAGS += -D__avr32__
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o
+head-y += arch/avr32/kernel/head.o
+core-$(CONFIG_PLATFORM_AT32AP) += arch/avr32/mach-at32ap/
+core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
+core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
+core-y += arch/avr32/kernel/
+core-y += arch/avr32/mm/
+libs-y += arch/avr32/lib/ #$(LIBGCC)
+
+archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap
+
+include/asm-avr32/.arch: $(wildcard include/config/platform/*.h) include/config/auto.conf
+ @echo ' SYMLINK include/asm-avr32/arch -> include/asm-avr32/$(archincdir-y)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-avr32
+ $(Q)ln -fsn $(srctree)/include/asm-avr32/$(archincdir-y) include/asm-avr32/arch
+else
+ $(Q)ln -fsn $(archincdir-y) include/asm-avr32/arch
+endif
+ @touch $@
+
+archprepare: include/asm-avr32/.arch
+
+BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
+
+.PHONY: $(BOOT_TARGETS) install
+
+boot := arch/$(ARCH)/boot/images
+
+ KBUILD_IMAGE := $(boot)/uImage
+vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf
+vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso
+uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec
+uImage: KBUILD_IMAGE := $(boot)/uImage
+
+quiet_cmd_listing = LST $@
+ cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@
+quiet_cmd_disasm = DIS $@
+ cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@
+
+vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+install: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
+
+linux.s: vmlinux
+ $(call if_changed,disasm)
+
+linux.lst: vmlinux
+ $(call if_changed,listing)
+
+define archhelp
+ @echo '* vmlinux.elf - ELF image with load address 0'
+ @echo ' vmlinux.cso - PathFinder CSO image'
+ @echo ' uImage - Create a bootable image for U-Boot'
+endef
diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile
new file mode 100644
index 00000000000..df949948053
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/Makefile
@@ -0,0 +1,2 @@
+obj-y += setup.o spi.o flash.o
+obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
new file mode 100644
index 00000000000..49164e9aadd
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -0,0 +1,37 @@
+/*
+ * ATSTK1002 daughterboard-specific init code
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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 <asm/arch/board.h>
+
+struct eth_platform_data __initdata eth0_data = {
+ .valid = 1,
+ .mii_phy_addr = 0x10,
+ .is_rmii = 0,
+ .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+};
+
+extern struct lcdc_platform_data atstk1000_fb0_data;
+
+static int __init atstk1002_init(void)
+{
+ at32_add_system_devices();
+
+ at32_add_device_usart(1); /* /dev/ttyS0 */
+ at32_add_device_usart(2); /* /dev/ttyS1 */
+ at32_add_device_usart(3); /* /dev/ttyS2 */
+
+ at32_add_device_eth(0, &eth0_data);
+ at32_add_device_spi(0);
+ at32_add_device_lcdc(0, &atstk1000_fb0_data);
+
+ return 0;
+}
+postcore_initcall(atstk1002_init);
diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c
new file mode 100644
index 00000000000..aac4300cca1
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/flash.c
@@ -0,0 +1,95 @@
+/*
+ * ATSTK1000 board-specific flash initialization
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/arch/smc.h>
+
+static struct smc_config flash_config __initdata = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 40,
+ .ncs_write_setup = 0,
+ .nwe_setup = 10,
+
+ .ncs_read_pulse = 80,
+ .nrd_pulse = 40,
+ .ncs_write_pulse = 65,
+ .nwe_pulse = 55,
+
+ .read_cycle = 120,
+ .write_cycle = 120,
+
+ .bus_width = 2,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .byte_write = 1,
+};
+
+static struct mtd_partition flash_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0x00000000,
+ .size = 0x00020000, /* 128 KiB */
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "root",
+ .offset = 0x00020000,
+ .size = 0x007d0000,
+ },
+ {
+ .name = "env",
+ .offset = 0x007f0000,
+ .size = 0x00010000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .nr_parts = ARRAY_SIZE(flash_parts),
+ .parts = flash_parts,
+};
+
+static struct resource flash_resource = {
+ .start = 0x00000000,
+ .end = 0x007fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .resource = &flash_resource,
+ .num_resources = 1,
+ .dev = {
+ .platform_data = &flash_data,
+ },
+};
+
+/* This needs to be called after the SMC has been initialized */
+static int __init atstk1000_flash_init(void)
+{
+ int ret;
+
+ ret = smc_set_configuration(0, &flash_config);
+ if (ret < 0) {
+ printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
+ return ret;
+ }
+
+ platform_device_register(&flash_device);
+
+ return 0;
+}
+device_initcall(atstk1000_flash_init);
diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c
new file mode 100644
index 00000000000..191ab85de9a
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/setup.c
@@ -0,0 +1,59 @@
+/*
+ * ATSTK1000 board-specific setup code.
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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/bootmem.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+
+#include <asm/setup.h>
+
+#include <asm/arch/board.h>
+
+/* Initialized by bootloader-specific startup code. */
+struct tag *bootloader_tags __initdata;
+
+struct lcdc_platform_data __initdata atstk1000_fb0_data;
+
+asmlinkage void __init board_early_init(void)
+{
+ extern void sdram_init(void);
+
+#ifdef CONFIG_LOADER_STANDALONE
+ sdram_init();
+#endif
+}
+
+void __init board_setup_fbmem(unsigned long fbmem_start,
+ unsigned long fbmem_size)
+{
+ if (!fbmem_size)
+ return;
+
+ if (!fbmem_start) {
+ void *fbmem;
+
+ fbmem = alloc_bootmem_low_pages(fbmem_size);
+ fbmem_start = __pa(fbmem);
+ } else {
+ pg_data_t *pgdat;
+
+ for_each_online_pgdat(pgdat) {
+ if (fbmem_start >= pgdat->bdata->node_boot_start
+ && fbmem_start <= pgdat->bdata->node_low_pfn)
+ reserve_bootmem_node(pgdat, fbmem_start,
+ fbmem_size);
+ }
+ }
+
+ printk("%luKiB framebuffer memory at address 0x%08lx\n",
+ fbmem_size >> 10, fbmem_start);
+ atstk1000_fb0_data.fbmem_start = fbmem_start;
+ atstk1000_fb0_data.fbmem_size = fbmem_size;
+}
diff --git a/arch/avr32/boards/atstk1000/spi.c b/arch/avr32/boards/atstk1000/spi.c
new file mode 100644
index 00000000000..567726c82c6
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/spi.c
@@ -0,0 +1,27 @@
+/*
+ * ATSTK1000 SPI devices
+ *
+ * Copyright (C) 2005 Atmel Norway
+ *
+ * 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/device.h>
+#include <linux/spi/spi.h>
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "ltv350qv",
+ .max_speed_hz = 16000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ },
+};
+
+static int board_init_spi(void)
+{
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ return 0;
+}
+arch_initcall(board_init_spi);
diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile
new file mode 100644
index 00000000000..ccd74eeecec
--- /dev/null
+++ b/arch/avr32/boot/images/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2004-2006 Atmel Corporation
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+extra-y := vmlinux.bin vmlinux.gz
+
+OBJCOPYFLAGS_vmlinux.bin := -O binary
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A avr32 -O linux -T kernel \
+ -C gzip -a $(CONFIG_LOAD_ADDRESS) -e $(CONFIG_ENTRY_ADDRESS) \
+ -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+targets += uImage uImage.srec
+$(obj)/uImage: $(obj)/vmlinux.gz
+ $(call if_changed,uimage)
+ @echo ' Image $@ is ready'
+
+OBJCOPYFLAGS_uImage.srec := -I binary -O srec
+$(obj)/uImage.srec: $(obj)/uImage
+ $(call if_changed,objcopy)
+
+OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \
+ --change-section-lma __ex_table-0x80000000 \
+ --change-section-lma .rodata-0x80000000 \
+ --change-section-lma .data-0x80000000 \
+ --change-section-lma .init-0x80000000 \
+ --change-section-lma .bss-0x80000000 \
+ --change-section-lma .initrd-0x80000000 \
+ --change-section-lma __param-0x80000000 \
+ --change-section-lma __ksymtab-0x80000000 \
+ --change-section-lma __ksymtab_gpl-0x80000000 \
+ --change-section-lma __kcrctab-0x80000000 \
+ --change-section-lma __kcrctab_gpl-0x80000000 \
+ --change-section-lma __ksymtab_strings-0x80000000 \
+ --change-section-lma .got-0x80000000 \
+ --set-start 0xa0000000
+$(obj)/vmlinux.elf: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+quiet_cmd_sfdwarf = SFDWARF $@
+ cmd_sfdwarf = sfdwarf $< TO $@ GNUAVR IW $(SFDWARF_FLAGS) > $(obj)/sfdwarf.log
+
+$(obj)/vmlinux.cso: $(obj)/vmlinux.elf FORCE
+ $(call if_changed,sfdwarf)
+
+install: $(BOOTIMAGE)
+ sh $(srctree)/install-kernel.sh $<
+
+# Generated files to be removed upon make clean
+clean-files := vmlinux* uImage uImage.srec
diff --git a/arch/avr32/boot/u-boot/Makefile b/arch/avr32/boot/u-boot/Makefile
new file mode 100644
index 00000000000..125ddc96c27
--- /dev/null
+++ b/arch/avr32/boot/u-boot/Makefile
@@ -0,0 +1,3 @@
+extra-y := head.o
+
+obj-y := empty.o
diff --git a/arch/avr32/boot/u-boot/empty.S b/arch/avr32/boot/u-boot/empty.S
new file mode 100644
index 00000000000..8ac91a5f12f
--- /dev/null
+++ b/arch/avr32/boot/u-boot/empty.S
@@ -0,0 +1 @@
+/* Empty file */
diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S
new file mode 100644
index 00000000000..4488fa27fe9
--- /dev/null
+++ b/arch/avr32/boot/u-boot/head.S
@@ -0,0 +1,60 @@
+/*
+ * Startup code for use with the u-boot bootloader.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/setup.h>
+
+ /*
+ * The kernel is loaded where we want it to be and all caches
+ * have just been flushed. We get two parameters from u-boot:
+ *
+ * r12 contains a magic number (ATAG_MAGIC)
+ * r11 points to a tag table providing information about
+ * the system.
+ */
+ .section .init.text,"ax"
+ .global _start
+_start:
+ /* Check if the boot loader actually provided a tag table */
+ lddpc r0, magic_number
+ cp.w r12, r0
+ brne no_tag_table
+
+ /* Initialize .bss */
+ lddpc r2, bss_start_addr
+ lddpc r3, end_addr
+ mov r0, 0
+ mov r1, 0
+1: st.d r2++, r0
+ cp r2, r3
+ brlo 1b
+
+ /*
+ * Save the tag table address for later use. This must be done
+ * _after_ .bss has been initialized...
+ */
+ lddpc r0, tag_table_addr
+ st.w r0[0], r11
+
+ /* Jump to loader-independent setup code */
+ rjmp kernel_entry
+
+ .align 2
+magic_number:
+ .long ATAG_MAGIC
+tag_table_addr:
+ .long bootloader_tags
+bss_start_addr:
+ .long __bss_start
+end_addr:
+ .long _end
+
+no_tag_table:
+ sub r12, pc, (. - 2f)
+ bral panic
+2: .asciz "Boot loader didn't provide correct magic number\n"
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 0bdc10f1161..1d22255009f 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -1,158 +1,15 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.18-rc1
-# Thu Jul 6 10:04:05 2006
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-CONFIG_MIPS_EV96100=y
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_V2PCI is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# Tue Jul 11 12:41:36 2006
+#
+CONFIG_AVR32=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_MIPS_GT64120=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_GT96100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -166,34 +23,34 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
# General setup
#
CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
+# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLAB is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
#
# Loadable module support
@@ -201,52 +58,81 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# Block layer
#
-# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+# System Type and features
#
-CONFIG_HW_HAS_PCI=y
-# CONFIG_PCI is not set
+CONFIG_SUBARCH_AVR32B=y
CONFIG_MMU=y
+CONFIG_PERFORMANCE_COUNTERS=y
+CONFIG_PLATFORM_AT32AP=y
+CONFIG_CPU_AT32AP7000=y
+CONFIG_BOARD_ATSTK1002=y
+CONFIG_BOARD_ATSTK1000=y
+CONFIG_LOADER_U_BOOT=y
+CONFIG_LOAD_ADDRESS=0x10000000
+CONFIG_ENTRY_ADDRESS=0x90000000
+CONFIG_PHYS_OFFSET=0x10000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set
+# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set
+# CONFIG_NEED_NODE_MEMMAP_SIZE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_SPARSEMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_OWNERSHIP_TRACE is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_CMDLINE=""
#
-# PCCARD (PCMCIA/CardBus) support
+# Bus options
#
-# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
+# PCCARD (PCMCIA/CardBus) support
#
+# CONFIG_PCCARD is not set
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -257,18 +143,17 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -279,8 +164,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -288,7 +173,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -327,16 +212,11 @@ CONFIG_NETWORK_SECMARK=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -346,14 +226,15 @@ CONFIG_WIRELESS_EXT=y
# Generic Driver Options
#
CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
@@ -373,14 +254,15 @@ CONFIG_CONNECTOR=m
# Block devices
#
# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -390,7 +272,7 @@ CONFIG_ATA_OVER_ETH=m
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -415,34 +297,22 @@ CONFIG_RAID_ATTRS=m
# Network device support
#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
#
# PHY device support
#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_MIPS_GT96100ETH=y
-# CONFIG_DM9000 is not set
+CONFIG_MII=y
+CONFIG_MACB=y
#
# Ethernet (1000 Mbit)
@@ -465,7 +335,15 @@ CONFIG_MIPS_GT96100ETH=y
# Wan interfaces
#
# CONFIG_WAN is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -485,65 +363,35 @@ CONFIG_MIPS_GT96100ETH=y
#
# Input device support
#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-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
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
#
# IPMI
@@ -579,13 +427,23 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# SPI support
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=m
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
#
# Dallas's 1-wire bus
#
-# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -612,13 +470,28 @@ CONFIG_VIDEO_V4L2=y
# Graphics support
#
# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB=m
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SIDSA=m
+CONFIG_FB_SIDSA_DEFAULT_BPP=24
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+CONFIG_LCD_LTV350QV=m
#
# Sound
@@ -697,15 +570,14 @@ CONFIG_EXT2_FS=y
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_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_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -716,8 +588,11 @@ CONFIG_FUSE_FS=m
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -726,10 +601,10 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
#
# Miscellaneous filesystems
@@ -752,19 +627,25 @@ CONFIG_RAMFS=y
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -779,60 +660,84 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
#
# Kernel hacking
#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS 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=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_KPROBES=y
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -841,10 +746,9 @@ CONFIG_CRYPTO_CRC32C=m
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
new file mode 100644
index 00000000000..90e5afff54a
--- /dev/null
+++ b/arch/avr32/kernel/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux/AVR32 kernel.
+#
+
+extra-y := head.o vmlinux.lds
+
+obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
+obj-y += syscall_table.o syscall-stubs.o irq.o
+obj-y += setup.o traps.o semaphore.o ptrace.o
+obj-y += signal.o sys_avr32.o process.o time.o
+obj-y += init_task.o switch_to.o cpu.o
+obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
+obj-$(CONFIG_KPROBES) += kprobes.o
+
+USE_STANDARD_AS_RULE := true
+
+%.lds: %.lds.c FORCE
+ $(call if_changed_dep,cpp_lds_S)
diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c
new file mode 100644
index 00000000000..97d86586566
--- /dev/null
+++ b/arch/avr32/kernel/asm-offsets.c
@@ -0,0 +1,25 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+ DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+ OFFSET(TI_task, thread_info, task);
+ OFFSET(TI_exec_domain, thread_info, exec_domain);
+ OFFSET(TI_flags, thread_info, flags);
+ OFFSET(TI_cpu, thread_info, cpu);
+ OFFSET(TI_preempt_count, thread_info, preempt_count);
+ OFFSET(TI_restart_block, thread_info, restart_block);
+}
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
new file mode 100644
index 00000000000..04f767a272b
--- /dev/null
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -0,0 +1,55 @@
+/*
+ * Export AVR32-specific functions for loadable modules.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/checksum.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+
+/*
+ * GCC functions
+ */
+extern unsigned long long __avr32_lsl64(unsigned long long u, unsigned long b);
+extern unsigned long long __avr32_lsr64(unsigned long long u, unsigned long b);
+extern unsigned long long __avr32_asr64(unsigned long long u, unsigned long b);
+EXPORT_SYMBOL(__avr32_lsl64);
+EXPORT_SYMBOL(__avr32_lsr64);
+EXPORT_SYMBOL(__avr32_asr64);
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+
+/*
+ * Userspace access stuff.
+ */
+EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_generic);
+
+/* Delay loops (lib/delay.S) */
+EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__const_udelay);
+
+/* Bit operations (lib/findbit.S) */
+EXPORT_SYMBOL(find_first_zero_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_first_bit);
+EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(generic_find_next_zero_le_bit);
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
new file mode 100644
index 00000000000..342452ba204
--- /dev/null
+++ b/arch/avr32/kernel/cpu.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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/sysdev.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <linux/param.h>
+#include <linux/errno.h>
+
+#include <asm/setup.h>
+#include <asm/sysreg.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+#ifdef CONFIG_PERFORMANCE_COUNTERS
+
+/*
+ * XXX: If/when a SMP-capable implementation of AVR32 will ever be
+ * made, we must make sure that the code executes on the correct CPU.
+ */
+static ssize_t show_pc0event(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
+}
+static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf || val > 0x3f)
+ return -EINVAL;
+ val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff);
+ sysreg_write(PCCR, val);
+ return count;
+}
+static ssize_t show_pc0count(struct sys_device *dev, char *buf)
+{
+ unsigned long pcnt0;
+
+ pcnt0 = sysreg_read(PCNT0);
+ return sprintf(buf, "%lu\n", pcnt0);
+}
+static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCNT0, val);
+
+ return count;
+}
+
+static ssize_t show_pc1event(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
+}
+static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf || val > 0x3f)
+ return -EINVAL;
+ val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff);
+ sysreg_write(PCCR, val);
+ return count;
+}
+static ssize_t show_pc1count(struct sys_device *dev, char *buf)
+{
+ unsigned long pcnt1;
+
+ pcnt1 = sysreg_read(PCNT1);
+ return sprintf(buf, "%lu\n", pcnt1);
+}
+static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCNT1, val);
+
+ return count;
+}
+
+static ssize_t show_pccycles(struct sys_device *dev, char *buf)
+{
+ unsigned long pccnt;
+
+ pccnt = sysreg_read(PCCNT);
+ return sprintf(buf, "%lu\n", pccnt);
+}
+static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCCNT, val);
+
+ return count;
+}
+
+static ssize_t show_pcenable(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
+}
+static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long pccr, val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ if (val)
+ val = 1;
+
+ pccr = sysreg_read(PCCR);
+ pccr = (pccr & ~1UL) | val;
+ sysreg_write(PCCR, pccr);
+
+ return count;
+}
+
+static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
+static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
+static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
+static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
+static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
+static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
+
+#endif /* CONFIG_PERFORMANCE_COUNTERS */
+
+static int __init topology_init(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ register_cpu(c, cpu);
+
+#ifdef CONFIG_PERFORMANCE_COUNTERS
+ sysdev_create_file(&c->sysdev, &attr_pc0event);
+ sysdev_create_file(&c->sysdev, &attr_pc0count);
+ sysdev_create_file(&c->sysdev, &attr_pc1event);
+ sysdev_create_file(&c->sysdev, &attr_pc1count);
+ sysdev_create_file(&c->sysdev, &attr_pccycles);
+ sysdev_create_file(&c->sysdev, &attr_pcenable);
+#endif
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
+static const char *cpu_names[] = {
+ "Morgan",
+ "AP7000",
+};
+#define NR_CPU_NAMES ARRAY_SIZE(cpu_names)
+
+static const char *arch_names[] = {
+ "AVR32A",
+ "AVR32B",
+};
+#define NR_ARCH_NAMES ARRAY_SIZE(arch_names)
+
+static const char *mmu_types[] = {
+ "No MMU",
+ "ITLB and DTLB",
+ "Shared TLB",
+ "MPU"
+};
+
+void __init setup_processor(void)
+{
+ unsigned long config0, config1;
+ unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type;
+ unsigned tmp;
+
+ config0 = sysreg_read(CONFIG0); /* 0x0000013e; */
+ config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */
+ cpu_id = config0 >> 24;
+ cpu_rev = (config0 >> 16) & 0xff;
+ arch_id = (config0 >> 13) & 0x07;
+ arch_rev = (config0 >> 10) & 0x07;
+ mmu_type = (config0 >> 7) & 0x03;
+
+ boot_cpu_data.arch_type = arch_id;
+ boot_cpu_data.cpu_type = cpu_id;
+ boot_cpu_data.arch_revision = arch_rev;
+ boot_cpu_data.cpu_revision = cpu_rev;
+ boot_cpu_data.tlb_config = mmu_type;
+
+ tmp = (config1 >> 13) & 0x07;
+ if (tmp) {
+ boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07);
+ boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f);
+ boot_cpu_data.icache.linesz = 1 << (tmp + 1);
+ }
+ tmp = (config1 >> 3) & 0x07;
+ if (tmp) {
+ boot_cpu_data.dcache.ways = 1 << (config1 & 0x07);
+ boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f);
+ boot_cpu_data.dcache.linesz = 1 << (tmp + 1);
+ }
+
+ if ((cpu_id >= NR_CPU_NAMES) || (arch_id >= NR_ARCH_NAMES)) {
+ printk ("Unknown CPU configuration (ID %02x, arch %02x), "
+ "continuing anyway...\n",
+ cpu_id, arch_id);
+ return;
+ }
+
+ printk ("CPU: %s [%02x] revision %d (%s revision %d)\n",
+ cpu_names[cpu_id], cpu_id, cpu_rev,
+ arch_names[arch_id], arch_rev);
+ printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]);
+ printk ("CPU: features:");
+ if (config0 & (1 << 6))
+ printk(" fpu");
+ if (config0 & (1 << 5))
+ printk(" java");
+ if (config0 & (1 << 4))
+ printk(" perfctr");
+ if (config0 & (1 << 3))
+ printk(" ocd");
+ printk("\n");
+}
+
+#ifdef CONFIG_PROC_FS
+static int c_show(struct seq_file *m, void *v)
+{
+ unsigned int icache_size, dcache_size;
+ unsigned int cpu = smp_processor_id();
+
+ icache_size = boot_cpu_data.icache.ways *
+ boot_cpu_data.icache.sets *
+ boot_cpu_data.icache.linesz;
+ dcache_size = boot_cpu_data.dcache.ways *
+ boot_cpu_data.dcache.sets *
+ boot_cpu_data.dcache.linesz;
+
+ seq_printf(m, "processor\t: %d\n", cpu);
+
+ if (boot_cpu_data.arch_type < NR_ARCH_NAMES)
+ seq_printf(m, "cpu family\t: %s revision %d\n",
+ arch_names[boot_cpu_data.arch_type],
+ boot_cpu_data.arch_revision);
+ if (boot_cpu_data.cpu_type < NR_CPU_NAMES)
+ seq_printf(m, "cpu type\t: %s revision %d\n",
+ cpu_names[boot_cpu_data.cpu_type],
+ boot_cpu_data.cpu_revision);
+
+ seq_printf(m, "i-cache\t\t: %dK (%u ways x %u sets x %u)\n",
+ icache_size >> 10,
+ boot_cpu_data.icache.ways,
+ boot_cpu_data.icache.sets,
+ boot_cpu_data.icache.linesz);
+ seq_printf(m, "d-cache\t\t: %dK (%u ways x %u sets x %u)\n",
+ dcache_size >> 10,
+ boot_cpu_data.dcache.ways,
+ boot_cpu_data.dcache.sets,
+ boot_cpu_data.dcache.linesz);
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ boot_cpu_data.loops_per_jiffy / (500000/HZ),
+ (boot_cpu_data.loops_per_jiffy / (5000/HZ)) % 100);
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = c_show
+};
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
new file mode 100644
index 00000000000..eeb66792bc3
--- /dev/null
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the low-level entry-points into the kernel, that is,
+ * exception handlers, debug trap handlers, interrupt handlers and the
+ * system call handler.
+ */
+#include <linux/errno.h>
+
+#include <asm/asm.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
+#include <asm/ocd.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/sysreg.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#ifdef CONFIG_PREEMPT
+# define preempt_stop mask_interrupts
+#else
+# define preempt_stop
+# define fault_resume_kernel fault_restore_all
+#endif
+
+#define __MASK(x) ((1 << (x)) - 1)
+#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
+ (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
+
+ .section .ex.text,"ax",@progbits
+ .align 2
+exception_vectors:
+ bral handle_critical
+ .align 2
+ bral handle_critical
+ .align 2
+ bral do_bus_error_write
+ .align 2
+ bral do_bus_error_read
+ .align 2
+ bral do_nmi_ll
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral handle_debug
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_fpe_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral do_dtlb_modified
+
+ /*
+ * r0 : PGD/PT/PTE
+ * r1 : Offending address
+ * r2 : Scratch register
+ * r3 : Cause (5, 12 or 13)
+ */
+#define tlbmiss_save pushm r0-r3
+#define tlbmiss_restore popm r0-r3
+
+ .section .tlbx.ex.text,"ax",@progbits
+ .global itlb_miss
+itlb_miss:
+ tlbmiss_save
+ rjmp tlb_miss_common
+
+ .section .tlbr.ex.text,"ax",@progbits
+dtlb_miss_read:
+ tlbmiss_save
+ rjmp tlb_miss_common
+
+ .section .tlbw.ex.text,"ax",@progbits
+dtlb_miss_write:
+ tlbmiss_save
+
+ .global tlb_miss_common
+tlb_miss_common:
+ mfsr r0, SYSREG_PTBR
+ mfsr r1, SYSREG_TLBEAR
+
+ /* Is it the vmalloc space? */
+ bld r1, 31
+ brcs handle_vmalloc_miss
+
+ /* First level lookup */
+pgtbl_lookup:
+ lsr r2, r1, PGDIR_SHIFT
+ ld.w r0, r0[r2 << 2]
+ bld r0, _PAGE_BIT_PRESENT
+ brcc page_table_not_present
+
+ /* TODO: Check access rights on page table if necessary */
+
+ /* Translate to virtual address in P1. */
+ andl r0, 0xf000
+ sbr r0, 31
+
+ /* Second level lookup */
+ lsl r1, (32 - PGDIR_SHIFT)
+ lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
+ add r2, r0, r1 << 2
+ ld.w r1, r2[0]
+ bld r1, _PAGE_BIT_PRESENT
+ brcc page_not_present
+
+ /* Mark the page as accessed */
+ sbr r1, _PAGE_BIT_ACCESSED
+ st.w r2[0], r1
+
+ /* Drop software flags */
+ andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
+ mtsr SYSREG_TLBELO, r1
+
+ /* Figure out which entry we want to replace */
+ mfsr r0, SYSREG_TLBARLO
+ clz r2, r0
+ brcc 1f
+ mov r1, -1 /* All entries have been accessed, */
+ mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
+ mov r2, 0 /* and start at 0 */
+1: mfsr r1, SYSREG_MMUCR
+ lsl r2, 14
+ andl r1, 0x3fff, COH
+ or r1, r2
+ mtsr SYSREG_MMUCR, r1
+
+ tlbw
+
+ tlbmiss_restore
+ rete
+
+handle_vmalloc_miss:
+ /* Simply do the lookup in init's page table */
+ mov r0, lo(swapper_pg_dir)
+ orh r0, hi(swapper_pg_dir)
+ rjmp pgtbl_lookup
+
+
+ /* --- System Call --- */
+
+ .section .scall.text,"ax",@progbits
+system_call:
+ pushm r12 /* r12_orig */
+ stmts --sp, r0-lr
+ zero_fp
+ mfsr r0, SYSREG_RAR_SUP
+ mfsr r1, SYSREG_RSR_SUP
+ stm --sp, r0-r1
+
+ /* check for syscall tracing */
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_SYSCALL_TRACE
+ brcs syscall_trace_enter
+
+syscall_trace_cont:
+ cp.w r8, NR_syscalls
+ brhs syscall_badsys
+
+ lddpc lr, syscall_table_addr
+ ld.w lr, lr[r8 << 2]
+ mov r8, r5 /* 5th argument (6th is pushed by stub) */
+ icall lr
+
+ .global syscall_return
+syscall_return:
+ get_thread_info r0
+ mask_interrupts /* make sure we don't miss an interrupt
+ setting need_resched or sigpending
+ between sampling and the rets */
+
+ /* Store the return value so that the correct value is loaded below */
+ stdsp sp[REG_R12], r12
+
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_ALLWORK_MASK, COH
+ brne syscall_exit_work
+
+syscall_exit_cont:
+ popm r8-r9
+ mtsr SYSREG_RAR_SUP, r8
+ mtsr SYSREG_RSR_SUP, r9
+ ldmts sp++, r0-lr
+ sub sp, -4 /* r12_orig */
+ rets
+
+ .align 2
+syscall_table_addr:
+ .long sys_call_table
+
+syscall_badsys:
+ mov r12, -ENOSYS
+ rjmp syscall_return
+
+ .global ret_from_fork
+ret_from_fork:
+ rcall schedule_tail
+
+ /* check for syscall tracing */
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_ALLWORK_MASK, COH
+ brne syscall_exit_work
+ rjmp syscall_exit_cont
+
+syscall_trace_enter:
+ pushm r8-r12
+ rcall syscall_trace
+ popm r8-r12
+ rjmp syscall_trace_cont
+
+syscall_exit_work:
+ bld r1, TIF_SYSCALL_TRACE
+ brcc 1f
+ unmask_interrupts
+ rcall syscall_trace
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+
+1: bld r1, TIF_NEED_RESCHED
+ brcc 2f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 3f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+3: bld r1, TIF_BREAKPOINT
+ brcc syscall_exit_cont
+ mfsr r3, SYSREG_TLBEHI
+ lddsp r2, sp[REG_PC]
+ andl r3, 0xff, COH
+ lsl r3, 1
+ sbr r3, 30
+ sbr r3, 0
+ mtdr DBGREG_BWA2A, r2
+ mtdr DBGREG_BWC2A, r3
+ rjmp syscall_exit_cont
+
+
+ /* The slow path of the TLB miss handler */
+page_table_not_present:
+page_not_present:
+ tlbmiss_restore
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_page_fault
+ rjmp ret_from_exception
+
+ /* This function expects to find offending PC in SYSREG_RAR_EX */
+save_full_context_ex:
+ mfsr r8, SYSREG_RSR_EX
+ mov r12, r8
+ andh r8, (MODE_MASK >> 16), COH
+ mfsr r11, SYSREG_RAR_EX
+ brne 2f
+
+1: pushm r11, r12 /* PC and SR */
+ unmask_exceptions
+ ret r12
+
+2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
+ stdsp sp[4], r10 /* replace saved SP */
+ rjmp 1b
+
+ /* Low-level exception handlers */
+handle_critical:
+ pushm r12
+ pushm r0-r12
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_critical_exception
+
+ /* We should never get here... */
+bad_return:
+ sub r12, pc, (. - 1f)
+ bral panic
+ .align 2
+1: .asciz "Return from critical exception!"
+
+ .align 1
+do_bus_error_write:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mov r11, 1
+ rjmp 1f
+
+do_bus_error_read:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mov r11, 0
+1: mfsr r12, SYSREG_BEAR
+ mov r10, sp
+ rcall do_bus_error
+ rjmp ret_from_exception
+
+ .align 1
+do_nmi_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_nmi
+ rjmp bad_return
+
+handle_address_fault:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_address_exception
+ rjmp ret_from_exception
+
+handle_protection_fault:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_page_fault
+ rjmp ret_from_exception
+
+ .align 1
+do_illegal_opcode_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_illegal_opcode
+ rjmp ret_from_exception
+
+do_dtlb_modified:
+ pushm r0-r3
+ mfsr r1, SYSREG_TLBEAR
+ mfsr r0, SYSREG_PTBR
+ lsr r2, r1, PGDIR_SHIFT
+ ld.w r0, r0[r2 << 2]
+ lsl r1, (32 - PGDIR_SHIFT)
+ lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
+
+ /* Translate to virtual address in P1 */
+ andl r0, 0xf000
+ sbr r0, 31
+ add r2, r0, r1 << 2
+ ld.w r3, r2[0]
+ sbr r3, _PAGE_BIT_DIRTY
+ mov r0, r3
+ st.w r2[0], r3
+
+ /* The page table is up-to-date. Update the TLB entry as well */
+ andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
+ mtsr SYSREG_TLBELO, r0
+
+ /* MMUCR[DRP] is updated automatically, so let's go... */
+ tlbw
+
+ popm r0-r3
+ rete
+
+do_fpe_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ unmask_interrupts
+ mov r12, 26
+ mov r11, sp
+ rcall do_fpe
+ rjmp ret_from_exception
+
+ret_from_exception:
+ mask_interrupts
+ lddsp r4, sp[REG_SR]
+ andh r4, (MODE_MASK >> 16), COH
+ brne fault_resume_kernel
+
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_WORK_MASK, COH
+ brne fault_exit_work
+
+fault_resume_user:
+ popm r8-r9
+ mask_exceptions
+ mtsr SYSREG_RAR_EX, r8
+ mtsr SYSREG_RSR_EX, r9
+ ldmts sp++, r0-lr
+ sub sp, -4
+ rete
+
+fault_resume_kernel:
+#ifdef CONFIG_PREEMPT
+ get_thread_info r0
+ ld.w r2, r0[TI_preempt_count]
+ cp.w r2, 0
+ brne 1f
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_NEED_RESCHED
+ brcc 1f
+ lddsp r4, sp[REG_SR]
+ bld r4, SYSREG_GM_OFFSET
+ brcs 1f
+ rcall preempt_schedule_irq
+1:
+#endif
+
+ popm r8-r9
+ mask_exceptions
+ mfsr r1, SYSREG_SR
+ mtsr SYSREG_RAR_EX, r8
+ mtsr SYSREG_RSR_EX, r9
+ popm lr
+ sub sp, -4 /* ignore SP */
+ popm r0-r12
+ sub sp, -4 /* ignore r12_orig */
+ rete
+
+irq_exit_work:
+ /* Switch to exception mode so that we can share the same code. */
+ mfsr r8, SYSREG_SR
+ cbr r8, SYSREG_M0_OFFSET
+ orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+
+fault_exit_work:
+ bld r1, TIF_NEED_RESCHED
+ brcc 1f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp fault_exit_work
+
+1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 2f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp fault_exit_work
+
+2: bld r1, TIF_BREAKPOINT
+ brcc fault_resume_user
+ mfsr r3, SYSREG_TLBEHI
+ lddsp r2, sp[REG_PC]
+ andl r3, 0xff, COH
+ lsl r3, 1
+ sbr r3, 30
+ sbr r3, 0
+ mtdr DBGREG_BWA2A, r2
+ mtdr DBGREG_BWC2A, r3
+ rjmp fault_resume_user
+
+ /* If we get a debug trap from privileged context we end up here */
+handle_debug_priv:
+ /* Fix up LR and SP in regs. r11 contains the mode we came from */
+ mfsr r8, SYSREG_SR
+ mov r9, r8
+ andh r8, hi(~MODE_MASK)
+ or r8, r11
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ stdsp sp[REG_LR], lr
+ mtsr SYSREG_SR, r9
+ sub pc, -2
+ sub r10, sp, -FRAME_SIZE_FULL
+ stdsp sp[REG_SP], r10
+ mov r12, sp
+ rcall do_debug_priv
+
+ /* Now, put everything back */
+ ssrf SR_EM_BIT
+ popm r10, r11
+ mtsr SYSREG_RAR_DBG, r10
+ mtsr SYSREG_RSR_DBG, r11
+ mfsr r8, SYSREG_SR
+ mov r9, r8
+ andh r8, hi(~MODE_MASK)
+ andh r11, hi(MODE_MASK)
+ or r8, r11
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ popm lr
+ mtsr SYSREG_SR, r9
+ sub pc, -2
+ sub sp, -4 /* skip SP */
+ popm r0-r12
+ sub sp, -4
+ retd
+
+ /*
+ * At this point, everything is masked, that is, interrupts,
+ * exceptions and debugging traps. We might get called from
+ * interrupt or exception context in some rare cases, but this
+ * will be taken care of by do_debug(), so we're not going to
+ * do a 100% correct context save here.
+ */
+handle_debug:
+ sub sp, 4 /* r12_orig */
+ stmts --sp, r0-lr
+ mfsr r10, SYSREG_RAR_DBG
+ mfsr r11, SYSREG_RSR_DBG
+ unmask_exceptions
+ pushm r10,r11
+ andh r11, (MODE_MASK >> 16), COH
+ brne handle_debug_priv
+
+ mov r12, sp
+ rcall do_debug
+
+ lddsp r10, sp[REG_SR]
+ andh r10, (MODE_MASK >> 16), COH
+ breq debug_resume_user
+
+debug_restore_all:
+ popm r10,r11
+ mask_exceptions
+ mtsr SYSREG_RSR_DBG, r11
+ mtsr SYSREG_RAR_DBG, r10
+ ldmts sp++, r0-lr
+ sub sp, -4
+ retd
+
+debug_resume_user:
+ get_thread_info r0
+ mask_interrupts
+
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_DBGWORK_MASK, COH
+ breq debug_restore_all
+
+1: bld r1, TIF_NEED_RESCHED
+ brcc 2f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 3f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+3: bld r1, TIF_SINGLE_STEP
+ brcc debug_restore_all
+ mfdr r2, DBGREG_DC
+ sbr r2, DC_SS_BIT
+ mtdr DBGREG_DC, r2
+ rjmp debug_restore_all
+
+ .set rsr_int0, SYSREG_RSR_INT0
+ .set rsr_int1, SYSREG_RSR_INT1
+ .set rsr_int2, SYSREG_RSR_INT2
+ .set rsr_int3, SYSREG_RSR_INT3
+ .set rar_int0, SYSREG_RAR_INT0
+ .set rar_int1, SYSREG_RAR_INT1
+ .set rar_int2, SYSREG_RAR_INT2
+ .set rar_int3, SYSREG_RAR_INT3
+
+ .macro IRQ_LEVEL level
+ .type irq_level\level, @function
+irq_level\level:
+ sub sp, 4 /* r12_orig */
+ stmts --sp,r0-lr
+ mfsr r8, rar_int\level
+ mfsr r9, rsr_int\level
+ pushm r8-r9
+
+ mov r11, sp
+ mov r12, \level
+
+ rcall do_IRQ
+
+ lddsp r4, sp[REG_SR]
+ andh r4, (MODE_MASK >> 16), COH
+#ifdef CONFIG_PREEMPT
+ brne 2f
+#else
+ brne 1f
+#endif
+
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_WORK_MASK, COH
+ brne irq_exit_work
+
+1: popm r8-r9
+ mtsr rar_int\level, r8
+ mtsr rsr_int\level, r9
+ ldmts sp++,r0-lr
+ sub sp, -4 /* ignore r12_orig */
+ rete
+
+#ifdef CONFIG_PREEMPT
+2:
+ get_thread_info r0
+ ld.w r2, r0[TI_preempt_count]
+ cp.w r2, 0
+ brne 1b
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_NEED_RESCHED
+ brcc 1b
+ lddsp r4, sp[REG_SR]
+ bld r4, SYSREG_GM_OFFSET
+ brcs 1b
+ rcall preempt_schedule_irq
+ rjmp 1b
+#endif
+ .endm
+
+ .section .irq.text,"ax",@progbits
+
+ .global irq_level0
+ .global irq_level1
+ .global irq_level2
+ .global irq_level3
+ IRQ_LEVEL 0
+ IRQ_LEVEL 1
+ IRQ_LEVEL 2
+ IRQ_LEVEL 3
diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S
new file mode 100644
index 00000000000..773b7ad87be
--- /dev/null
+++ b/arch/avr32/kernel/head.S
@@ -0,0 +1,45 @@
+/*
+ * Non-board-specific low-level startup code
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/linkage.h>
+
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/sysreg.h>
+
+ .section .init.text,"ax"
+ .global kernel_entry
+kernel_entry:
+ /* Initialize status register */
+ lddpc r0, init_sr
+ mtsr SYSREG_SR, r0
+
+ /* Set initial stack pointer */
+ lddpc sp, stack_addr
+ sub sp, -THREAD_SIZE
+
+#ifdef CONFIG_FRAME_POINTER
+ /* Mark last stack frame */
+ mov lr, 0
+ mov r7, 0
+#endif
+
+ /* Set up the PIO, SDRAM controller, early printk, etc. */
+ rcall board_early_init
+
+ /* Start the show */
+ lddpc pc, kernel_start_addr
+
+ .align 2
+init_sr:
+ .long 0x007f0000 /* Supervisor mode, everything masked */
+stack_addr:
+ .long init_thread_union
+kernel_start_addr:
+ .long start_kernel
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c
new file mode 100644
index 00000000000..effcacf9d1a
--- /dev/null
+++ b/arch/avr32/kernel/init_task.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/fs.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure. Must be aligned on an 8192-byte boundary.
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c
new file mode 100644
index 00000000000..856f3548e66
--- /dev/null
+++ b/arch/avr32/kernel/irq.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on arch/i386/kernel/irq.c
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * 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.
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ *
+ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysdev.h>
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ %u\n", irq);
+}
+
+#ifdef CONFIG_PROC_FS
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *)v, cpu;
+ struct irqaction *action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_puts(p, " ");
+ for_each_online_cpu(cpu)
+ seq_printf(p, "CPU%d ", cpu);
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto unlock;
+
+ seq_printf(p, "%3d: ", i);
+ for_each_online_cpu(cpu)
+ seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+ seq_printf(p, " %s", action->name);
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+ unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c
new file mode 100644
index 00000000000..6caf9e8d808
--- /dev/null
+++ b/arch/avr32/kernel/kprobes.c
@@ -0,0 +1,270 @@
+/*
+ * Kernel Probes (KProbes)
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * Based on arch/ppc64/kernel/kprobes.c
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 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/kprobes.h>
+#include <linux/ptrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/ocd.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe);
+static unsigned long kprobe_status;
+static struct pt_regs jprobe_saved_regs;
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ int ret = 0;
+
+ if ((unsigned long)p->addr & 0x01) {
+ printk("Attempt to register kprobe at an unaligned address\n");
+ ret = -EINVAL;
+ }
+
+ /* XXX: Might be a good idea to check if p->addr is a valid
+ * kernel address as well... */
+
+ if (!ret) {
+ pr_debug("copy kprobe at %p\n", p->addr);
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
+ }
+
+ return ret;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ pr_debug("arming kprobe at %p\n", p->addr);
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ pr_debug("disarming kprobe at %p\n", p->addr);
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long dc;
+
+ pr_debug("preparing to singlestep over %p (PC=%08lx)\n",
+ p->addr, regs->pc);
+
+ BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D)));
+
+ dc = __mfdr(DBGREG_DC);
+ dc |= DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ /*
+ * We must run the instruction from its original location
+ * since it may actually reference PC.
+ *
+ * TODO: Do the instruction replacement directly in icache.
+ */
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long dc;
+
+ pr_debug("resuming execution at PC=%08lx\n", regs->pc);
+
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes set_current_kprobe(struct kprobe *p)
+{
+ __get_cpu_var(current_kprobe) = p;
+}
+
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ void *addr = (void *)regs->pc;
+ int ret = 0;
+
+ pr_debug("kprobe_handler: kprobe_running=%d\n",
+ kprobe_running());
+
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
+ preempt_disable();
+
+ /* Check that we're not recursing */
+ if (kprobe_running()) {
+ p = get_kprobe(addr);
+ if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ printk("FIXME: kprobe hit while single-stepping!\n");
+ goto no_kprobe;
+ }
+
+ printk("FIXME: kprobe hit while handling another kprobe\n");
+ goto no_kprobe;
+ } else {
+ p = kprobe_running();
+ if (p->break_handler && p->break_handler(p, regs))
+ goto ss_probe;
+ }
+ /* If it's not ours, can't be delete race, (we hold lock). */
+ goto no_kprobe;
+ }
+
+ p = get_kprobe(addr);
+ if (!p)
+ goto no_kprobe;
+
+ kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p);
+ if (p->pre_handler && p->pre_handler(p, regs))
+ /* handler has already set things up, so skip ss setup */
+ return 1;
+
+ss_probe:
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ return ret;
+}
+
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *cur = kprobe_running();
+
+ pr_debug("post_kprobe_handler, cur=%p\n", cur);
+
+ if (!cur)
+ return 0;
+
+ if (cur->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
+ }
+
+ resume_execution(cur, regs);
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+
+ return 1;
+}
+
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ struct kprobe *cur = kprobe_running();
+
+ pr_debug("kprobe_fault_handler: trapnr=%d\n", trapnr);
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ if (kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs);
+ preempt_enable_no_resched();
+ }
+ return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ pr_debug("kprobe_exceptions_notify: val=%lu, data=%p\n",
+ val, data);
+
+ switch (val) {
+ case DIE_BREAKPOINT:
+ if (kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (post_kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_FAULT:
+ if (kprobe_running()
+ && kprobe_fault_handler(args->regs, args->trapnr))
+ ret = NOTIFY_STOP;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+ memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+
+ /*
+ * TODO: We should probably save some of the stack here as
+ * well, since gcc may pass arguments on the stack for certain
+ * functions (lots of arguments, large aggregates, varargs)
+ */
+
+ /* setup return addr to the jprobe handler routine */
+ regs->pc = (unsigned long)jp->entry;
+ return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+ asm volatile("breakpoint" ::: "memory");
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ /*
+ * FIXME - we should ideally be validating that we got here 'cos
+ * of the "trap" in jprobe_return() above, before restoring the
+ * saved regs...
+ */
+ memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+ return 1;
+}
+
+int __init arch_init_kprobes(void)
+{
+ printk("KPROBES: Enabling monitor mode (MM|DBE)...\n");
+ __mtdr(DBGREG_DC, DC_MM | DC_DBE);
+
+ /* TODO: Register kretprobe trampoline */
+ return 0;
+}
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
new file mode 100644
index 00000000000..dfc32f2817b
--- /dev/null
+++ b/arch/avr32/kernel/module.c
@@ -0,0 +1,324 @@
+/*
+ * AVR32-specific kernel module loader
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * GOT initialization parts are based on the s390 version
+ * Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH,
+ * IBM Corporation
+ *
+ * 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/moduleloader.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(mod->arch.syminfo);
+ mod->arch.syminfo = NULL;
+
+ vfree(module_region);
+ /* FIXME: if module_region == mod->init_region, trim exception
+ * table entries. */
+}
+
+static inline int check_rela(Elf32_Rela *rela, struct module *module,
+ char *strings, Elf32_Sym *symbols)
+{
+ struct mod_arch_syminfo *info;
+
+ info = module->arch.syminfo + ELF32_R_SYM(rela->r_info);
+ switch (ELF32_R_TYPE(rela->r_info)) {
+ case R_AVR32_GOT32:
+ case R_AVR32_GOT16:
+ case R_AVR32_GOT8:
+ case R_AVR32_GOT21S:
+ case R_AVR32_GOT18SW: /* mcall */
+ case R_AVR32_GOT16S: /* ld.w */
+ if (rela->r_addend != 0) {
+ printk(KERN_ERR
+ "GOT relocation against %s at offset %u with addend\n",
+ strings + symbols[ELF32_R_SYM(rela->r_info)].st_name,
+ rela->r_offset);
+ return -ENOEXEC;
+ }
+ if (info->got_offset == -1UL) {
+ info->got_offset = module->arch.got_size;
+ module->arch.got_size += sizeof(void *);
+ }
+ pr_debug("GOT[%3lu] %s\n", info->got_offset,
+ strings + symbols[ELF32_R_SYM(rela->r_info)].st_name);
+ break;
+ }
+
+ return 0;
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+ char *secstrings, struct module *module)
+{
+ Elf32_Shdr *symtab;
+ Elf32_Sym *symbols;
+ Elf32_Rela *rela;
+ char *strings;
+ int nrela, i, j;
+ int ret;
+
+ /* Find the symbol table */
+ symtab = NULL;
+ for (i = 0; i < hdr->e_shnum; i++)
+ switch (sechdrs[i].sh_type) {
+ case SHT_SYMTAB:
+ symtab = &sechdrs[i];
+ break;
+ }
+ if (!symtab) {
+ printk(KERN_ERR "module %s: no symbol table\n", module->name);
+ return -ENOEXEC;
+ }
+
+ /* Allocate room for one syminfo structure per symbol. */
+ module->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
+ module->arch.syminfo = vmalloc(module->arch.nsyms
+ * sizeof(struct mod_arch_syminfo));
+ if (!module->arch.syminfo)
+ return -ENOMEM;
+
+ symbols = (void *)hdr + symtab->sh_offset;
+ strings = (void *)hdr + sechdrs[symtab->sh_link].sh_offset;
+ for (i = 0; i < module->arch.nsyms; i++) {
+ if (symbols[i].st_shndx == SHN_UNDEF &&
+ strcmp(strings + symbols[i].st_name,
+ "_GLOBAL_OFFSET_TABLE_") == 0)
+ /* "Define" it as absolute. */
+ symbols[i].st_shndx = SHN_ABS;
+ module->arch.syminfo[i].got_offset = -1UL;
+ module->arch.syminfo[i].got_initialized = 0;
+ }
+
+ /* Allocate GOT entries for symbols that need it. */
+ module->arch.got_size = 0;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_type != SHT_RELA)
+ continue;
+ nrela = sechdrs[i].sh_size / sizeof(Elf32_Rela);
+ rela = (void *)hdr + sechdrs[i].sh_offset;
+ for (j = 0; j < nrela; j++) {
+ ret = check_rela(rela + j, module,
+ strings, symbols);
+ if (ret)
+ goto out_free_syminfo;
+ }
+ }
+
+ /*
+ * Increase core size to make room for GOT and set start
+ * offset for GOT.
+ */
+ module->core_size = ALIGN(module->core_size, 4);
+ module->arch.got_offset = module->core_size;
+ module->core_size += module->arch.got_size;
+
+ return 0;
+
+out_free_syminfo:
+ vfree(module->arch.syminfo);
+ module->arch.syminfo = NULL;
+
+ return ret;
+}
+
+static inline int reloc_overflow(struct module *module, const char *reloc_name,
+ Elf32_Addr relocation)
+{
+ printk(KERN_ERR "module %s: Value %lx does not fit relocation %s\n",
+ module->name, (unsigned long)relocation, reloc_name);
+ return -ENOEXEC;
+}
+
+#define get_u16(loc) (*((uint16_t *)loc))
+#define put_u16(loc, val) (*((uint16_t *)loc) = (val))
+
+int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relindex,
+ struct module *module)
+{
+ Elf32_Shdr *symsec = sechdrs + symindex;
+ Elf32_Shdr *relsec = sechdrs + relindex;
+ Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+ Elf32_Rela *rel = (void *)relsec->sh_addr;
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
+ struct mod_arch_syminfo *info;
+ Elf32_Sym *sym;
+ Elf32_Addr relocation;
+ uint32_t *location;
+ uint32_t value;
+
+ location = (void *)dstsec->sh_addr + rel->r_offset;
+ sym = (Elf32_Sym *)symsec->sh_addr + ELF32_R_SYM(rel->r_info);
+ relocation = sym->st_value + rel->r_addend;
+
+ info = module->arch.syminfo + ELF32_R_SYM(rel->r_info);
+
+ /* Initialize GOT entry if necessary */
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_AVR32_GOT32:
+ case R_AVR32_GOT16:
+ case R_AVR32_GOT8:
+ case R_AVR32_GOT21S:
+ case R_AVR32_GOT18SW:
+ case R_AVR32_GOT16S:
+ if (!info->got_initialized) {
+ Elf32_Addr *gotent;
+
+ gotent = (module->module_core
+ + module->arch.got_offset
+ + info->got_offset);
+ *gotent = relocation;
+ info->got_initialized = 1;
+ }
+
+ relocation = info->got_offset;
+ break;
+ }
+
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_AVR32_32:
+ case R_AVR32_32_CPENT:
+ *location = relocation;
+ break;
+ case R_AVR32_22H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xffe00001) != 0
+ && (relocation & 0xffc00001) != 0xffc00000)
+ return reloc_overflow(module,
+ "R_AVR32_22H_PCREL",
+ relocation);
+ relocation >>= 1;
+
+ value = *location;
+ value = ((value & 0xe1ef0000)
+ | (relocation & 0xffff)
+ | ((relocation & 0x10000) << 4)
+ | ((relocation & 0x1e0000) << 8));
+ *location = value;
+ break;
+ case R_AVR32_11H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xfffffc01) != 0
+ && (relocation & 0xfffff801) != 0xfffff800)
+ return reloc_overflow(module,
+ "R_AVR32_11H_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf00c)
+ | ((relocation & 0x1fe) << 3)
+ | ((relocation & 0x600) >> 9));
+ put_u16(location, value);
+ break;
+ case R_AVR32_9H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xffffff01) != 0
+ && (relocation & 0xfffffe01) != 0xfffffe00)
+ return reloc_overflow(module,
+ "R_AVR32_9H_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf00f)
+ | ((relocation & 0x1fe) << 3));
+ put_u16(location, value);
+ break;
+ case R_AVR32_9UW_PCREL:
+ relocation -= ((Elf32_Addr)location) & 0xfffffffc;
+ if ((relocation & 0xfffffc03) != 0)
+ return reloc_overflow(module,
+ "R_AVR32_9UW_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf80f)
+ | ((relocation & 0x1fc) << 2));
+ put_u16(location, value);
+ break;
+ case R_AVR32_GOTPC:
+ /*
+ * R6 = PC - (PC - GOT)
+ *
+ * At this point, relocation contains the
+ * value of PC. Just subtract the value of
+ * GOT, and we're done.
+ */
+ pr_debug("GOTPC: PC=0x%lx, got_offset=0x%lx, core=0x%p\n",
+ relocation, module->arch.got_offset,
+ module->module_core);
+ relocation -= ((unsigned long)module->module_core
+ + module->arch.got_offset);
+ *location = relocation;
+ break;
+ case R_AVR32_GOT18SW:
+ if ((relocation & 0xfffe0003) != 0
+ && (relocation & 0xfffc0003) != 0xffff0000)
+ return reloc_overflow(module, "R_AVR32_GOT18SW",
+ relocation);
+ relocation >>= 2;
+ /* fall through */
+ case R_AVR32_GOT16S:
+ if ((relocation & 0xffff8000) != 0
+ && (relocation & 0xffff0000) != 0xffff0000)
+ return reloc_overflow(module, "R_AVR32_GOT16S",
+ relocation);
+ pr_debug("GOT reloc @ 0x%lx -> %lu\n",
+ rel->r_offset, relocation);
+ value = *location;
+ value = ((value & 0xffff0000)
+ | (relocation & 0xffff));
+ *location = value;
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ module->name, ELF32_R_TYPE(rel->r_info));
+ return -ENOEXEC;
+ }
+ }
+
+ return ret;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relindex,
+ struct module *module)
+{
+ printk(KERN_ERR "module %s: REL relocations are not supported\n",
+ module->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *module)
+{
+ vfree(module->arch.syminfo);
+ module->arch.syminfo = NULL;
+
+ return 0;
+}
+
+void module_arch_cleanup(struct module *module)
+{
+
+}
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
new file mode 100644
index 00000000000..317dc50945f
--- /dev/null
+++ b/arch/avr32/kernel/process.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/reboot.h>
+#include <linux/unistd.h>
+
+#include <asm/sysreg.h>
+#include <asm/ocd.h>
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ /* TODO: Enter sleep mode */
+ while (!need_resched())
+ cpu_relax();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+ __mtdr(DBGREG_DC, DC_DBE);
+ __mtdr(DBGREG_DC, DC_RES);
+ while (1) ;
+}
+
+/*
+ * PC is actually discarded when returning from a system call -- the
+ * return address must be stored in LR. This function will make sure
+ * LR points to do_exit before starting the thread.
+ *
+ * Also, when returning from fork(), r12 is 0, so we must copy the
+ * argument as well.
+ *
+ * r0 : The argument to the main thread function
+ * r1 : The address of do_exit
+ * r2 : The address of the main thread function
+ */
+asmlinkage extern void kernel_thread_helper(void);
+__asm__(" .type kernel_thread_helper, @function\n"
+ "kernel_thread_helper:\n"
+ " mov r12, r0\n"
+ " mov lr, r2\n"
+ " mov pc, r1\n"
+ " .size kernel_thread_helper, . - kernel_thread_helper");
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+
+ regs.r0 = (unsigned long)arg;
+ regs.r1 = (unsigned long)fn;
+ regs.r2 = (unsigned long)do_exit;
+ regs.lr = (unsigned long)kernel_thread_helper;
+ regs.pc = (unsigned long)kernel_thread_helper;
+ regs.sr = MODE_SUPERVISOR;
+
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
+ 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Free current thread data structures etc
+ */
+void exit_thread(void)
+{
+ /* nothing to do */
+}
+
+void flush_thread(void)
+{
+ /* nothing to do */
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+ /* do nothing */
+}
+
+static const char *cpu_modes[] = {
+ "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
+ "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
+};
+
+void show_regs(struct pt_regs *regs)
+{
+ unsigned long sp = regs->sp;
+ unsigned long lr = regs->lr;
+ unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
+
+ if (!user_mode(regs))
+ sp = (unsigned long)regs + FRAME_SIZE_FULL;
+
+ print_symbol("PC is at %s\n", instruction_pointer(regs));
+ print_symbol("LR is at %s\n", lr);
+ printk("pc : [<%08lx>] lr : [<%08lx>] %s\n"
+ "sp : %08lx r12: %08lx r11: %08lx\n",
+ instruction_pointer(regs),
+ lr, print_tainted(), sp, regs->r12, regs->r11);
+ printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
+ regs->r10, regs->r9, regs->r8);
+ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
+ regs->r7, regs->r6, regs->r5, regs->r4);
+ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
+ regs->r3, regs->r2, regs->r1, regs->r0);
+ printk("Flags: %c%c%c%c%c\n",
+ regs->sr & SR_Q ? 'Q' : 'q',
+ regs->sr & SR_V ? 'V' : 'v',
+ regs->sr & SR_N ? 'N' : 'n',
+ regs->sr & SR_Z ? 'Z' : 'z',
+ regs->sr & SR_C ? 'C' : 'c');
+ printk("Mode bits: %c%c%c%c%c%c%c%c%c\n",
+ regs->sr & SR_H ? 'H' : 'h',
+ regs->sr & SR_R ? 'R' : 'r',
+ regs->sr & SR_J ? 'J' : 'j',
+ regs->sr & SR_EM ? 'E' : 'e',
+ regs->sr & SR_I3M ? '3' : '.',
+ regs->sr & SR_I2M ? '2' : '.',
+ regs->sr & SR_I1M ? '1' : '.',
+ regs->sr & SR_I0M ? '0' : '.',
+ regs->sr & SR_GM ? 'G' : 'g');
+ printk("CPU Mode: %s\n", cpu_modes[mode]);
+
+ show_trace(NULL, (unsigned long *)sp, regs);
+}
+EXPORT_SYMBOL(show_regs);
+
+/* Fill in the fpu structure for a core dump. This is easy -- we don't have any */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+ /* Not valid */
+ return 0;
+}
+
+asmlinkage void ret_from_fork(void);
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs;
+
+ childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1;
+ *childregs = *regs;
+
+ if (user_mode(regs))
+ childregs->sp = usp;
+ else
+ childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE;
+
+ childregs->r12 = 0; /* Set return value for child */
+
+ p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
+ p->thread.cpu_context.ksp = (unsigned long)childregs;
+ p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+
+ return 0;
+}
+
+/* r12-r8 are dummy parameters to force the compiler to use the stack */
+asmlinkage int sys_fork(struct pt_regs *regs)
+{
+ return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidptr,
+ unsigned long child_tidptr, struct pt_regs *regs)
+{
+ if (!newsp)
+ newsp = regs->sp;
+ return do_fork(clone_flags, newsp, regs, 0,
+ (int __user *)parent_tidptr,
+ (int __user *)child_tidptr);
+}
+
+asmlinkage int sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,
+ 0, NULL, NULL);
+}
+
+asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv,
+ char __user *__user *uenvp, struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname(ufilename);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, uargv, uenvp, regs);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+
+out:
+ return error;
+}
+
+
+/*
+ * This function is supposed to answer the question "who called
+ * schedule()?"
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long pc;
+ unsigned long stack_page;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ stack_page = (unsigned long)p->thread_info;
+ BUG_ON(!stack_page);
+
+ /*
+ * The stored value of PC is either the address right after
+ * the call to __switch_to() or ret_from_fork.
+ */
+ pc = thread_saved_pc(p);
+ if (in_sched_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
+ unsigned long fp = p->thread.cpu_context.r7;
+ BUG_ON(fp < stack_page || fp > (THREAD_SIZE + stack_page));
+ pc = *(unsigned long *)fp;
+#else
+ /*
+ * We depend on the frame size of schedule here, which
+ * is actually quite ugly. It might be possible to
+ * determine the frame size automatically at build
+ * time by doing this:
+ * - compile sched.c
+ * - disassemble the resulting sched.o
+ * - look for 'sub sp,??' shortly after '<schedule>:'
+ */
+ unsigned long sp = p->thread.cpu_context.ksp + 16;
+ BUG_ON(sp < stack_page || sp > (THREAD_SIZE + stack_page));
+ pc = *(unsigned long *)sp;
+#endif
+ }
+
+ return pc;
+}
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
new file mode 100644
index 00000000000..3c89e59029a
--- /dev/null
+++ b/arch/avr32/kernel/ptrace.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#undef DEBUG
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/unistd.h>
+#include <linux/notifier.h>
+
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <asm/ocd.h>
+#include <asm/mmu_context.h>
+#include <asm/kdebug.h>
+
+static struct pt_regs *get_user_regs(struct task_struct *tsk)
+{
+ return (struct pt_regs *)((unsigned long) tsk->thread_info +
+ THREAD_SIZE - sizeof(struct pt_regs));
+}
+
+static void ptrace_single_step(struct task_struct *tsk)
+{
+ pr_debug("ptrace_single_step: pid=%u, SR=0x%08lx\n",
+ tsk->pid, tsk->thread.cpu_context.sr);
+ if (!(tsk->thread.cpu_context.sr & SR_D)) {
+ /*
+ * Set a breakpoint at the current pc to force the
+ * process into debug mode. The syscall/exception
+ * exit code will set a breakpoint at the return
+ * address when this flag is set.
+ */
+ pr_debug("ptrace_single_step: Setting TIF_BREAKPOINT\n");
+ set_tsk_thread_flag(tsk, TIF_BREAKPOINT);
+ }
+
+ /* The monitor code will do the actual step for us */
+ set_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching
+ *
+ * Make sure any single step bits, etc. are not set
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ clear_tsk_thread_flag(child, TIF_SINGLE_STEP);
+}
+
+/*
+ * Handle hitting a breakpoint
+ */
+static void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void __user *)instruction_pointer(regs);
+
+ pr_debug("ptrace_break: Sending SIGTRAP to PID %u (pc = 0x%p)\n",
+ tsk->pid, info.si_addr);
+ force_sig_info(SIGTRAP, &info, tsk);
+}
+
+/*
+ * Read the word at offset "offset" into the task's "struct user". We
+ * actually access the pt_regs struct stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long offset,
+ unsigned long __user *data)
+{
+ unsigned long *regs;
+ unsigned long value;
+
+ pr_debug("ptrace_read_user(%p, %#lx, %p)\n",
+ tsk, offset, data);
+
+ if (offset & 3 || offset >= sizeof(struct user)) {
+ printk("ptrace_read_user: invalid offset 0x%08lx\n", offset);
+ return -EIO;
+ }
+
+ regs = (unsigned long *)get_user_regs(tsk);
+
+ value = 0;
+ if (offset < sizeof(struct pt_regs))
+ value = regs[offset / sizeof(regs[0])];
+
+ return put_user(value, data);
+}
+
+/*
+ * Write the word "value" to offset "offset" into the task's "struct
+ * user". We actually access the pt_regs struct stored on the kernel
+ * stack.
+ */
+static int ptrace_write_user(struct task_struct *tsk, unsigned long offset,
+ unsigned long value)
+{
+ unsigned long *regs;
+
+ if (offset & 3 || offset >= sizeof(struct user)) {
+ printk("ptrace_write_user: invalid offset 0x%08lx\n", offset);
+ return -EIO;
+ }
+
+ if (offset >= sizeof(struct pt_regs))
+ return 0;
+
+ regs = (unsigned long *)get_user_regs(tsk);
+ regs[offset / sizeof(regs[0])] = value;
+
+ return 0;
+}
+
+static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
+{
+ struct pt_regs *regs = get_user_regs(tsk);
+
+ return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0;
+}
+
+static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
+{
+ struct pt_regs newregs;
+ int ret;
+
+ ret = -EFAULT;
+ if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) {
+ struct pt_regs *regs = get_user_regs(tsk);
+
+ ret = -EINVAL;
+ if (valid_user_regs(&newregs)) {
+ *regs = newregs;
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ unsigned long tmp;
+ int ret;
+
+ pr_debug("arch_ptrace(%ld, %ld, %#lx, %#lx)\n",
+ request, child->pid, addr, data);
+
+ pr_debug("ptrace: Enabling monitor mode...\n");
+ __mtdr(DBGREG_DC, __mfdr(DBGREG_DC) | DC_MM | DC_DBE);
+
+ switch (request) {
+ /* Read the word at location addr in the child process */
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+ ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ if (ret == sizeof(tmp))
+ ret = put_user(tmp, (unsigned long __user *)data);
+ else
+ ret = -EIO;
+ break;
+
+ case PTRACE_PEEKUSR:
+ ret = ptrace_read_user(child, addr,
+ (unsigned long __user *)data);
+ break;
+
+ /* Write the word in data at location addr */
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+ if (ret == sizeof(data))
+ ret = 0;
+ else
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR:
+ ret = ptrace_write_user(child, addr, data);
+ break;
+
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ /* restart after signal */
+ case PTRACE_CONT:
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->exit_code = data;
+ /* XXX: Are we sure no breakpoints are active here? */
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ /*
+ * Make the child exit. Best I can do is send it a
+ * SIGKILL. Perhaps it should be put in the status that it
+ * wants to exit.
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE)
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+
+ /*
+ * execute single instruction.
+ */
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ ptrace_single_step(child);
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ /* Detach a process that was attached */
+ case PTRACE_DETACH:
+ ret = ptrace_detach(child, data);
+ break;
+
+ case PTRACE_GETREGS:
+ ret = ptrace_getregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_SETREGS:
+ ret = ptrace_setregs(child, (const void __user *)data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+ pr_debug("sys_ptrace returning %d (DC = 0x%08lx)\n", ret, __mfdr(DBGREG_DC));
+ return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+ pr_debug("syscall_trace called\n");
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ pr_debug("syscall_trace: notifying parent\n");
+ /* The 0x80 provides a way for the tracing parent to
+ * distinguish between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it
+ * will do for normal use. strace only continues with a
+ * signal if the stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ pr_debug("syscall_trace: sending signal %d to PID %u\n",
+ current->exit_code, current->pid);
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
+
+asmlinkage void do_debug_priv(struct pt_regs *regs)
+{
+ unsigned long dc, ds;
+ unsigned long die_val;
+
+ ds = __mfdr(DBGREG_DS);
+
+ pr_debug("do_debug_priv: pc = %08lx, ds = %08lx\n", regs->pc, ds);
+
+ if (ds & DS_SSS)
+ die_val = DIE_SSTEP;
+ else
+ die_val = DIE_BREAKPOINT;
+
+ if (notify_die(die_val, regs, 0, SIGTRAP) == NOTIFY_STOP)
+ return;
+
+ if (likely(ds & DS_SSS)) {
+ extern void itlb_miss(void);
+ extern void tlb_miss_common(void);
+ struct thread_info *ti;
+
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ ti = current_thread_info();
+ ti->flags |= _TIF_BREAKPOINT;
+
+ /* The TLB miss handlers don't check thread flags */
+ if ((regs->pc >= (unsigned long)&itlb_miss)
+ && (regs->pc <= (unsigned long)&tlb_miss_common)) {
+ __mtdr(DBGREG_BWA2A, sysreg_read(RAR_EX));
+ __mtdr(DBGREG_BWC2A, 0x40000001 | (get_asid() << 1));
+ }
+
+ /*
+ * If we're running in supervisor mode, the breakpoint
+ * will take us where we want directly, no need to
+ * single step.
+ */
+ if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR)
+ ti->flags |= TIF_SINGLE_STEP;
+ } else {
+ panic("Unable to handle debug trap at pc = %08lx\n",
+ regs->pc);
+ }
+}
+
+/*
+ * Handle breakpoints, single steps and other debuggy things. To keep
+ * things simple initially, we run with interrupts and exceptions
+ * disabled all the time.
+ */
+asmlinkage void do_debug(struct pt_regs *regs)
+{
+ unsigned long dc, ds;
+
+ ds = __mfdr(DBGREG_DS);
+ pr_debug("do_debug: pc = %08lx, ds = %08lx\n", regs->pc, ds);
+
+ if (test_thread_flag(TIF_BREAKPOINT)) {
+ pr_debug("TIF_BREAKPOINT set\n");
+ /* We're taking care of it */
+ clear_thread_flag(TIF_BREAKPOINT);
+ __mtdr(DBGREG_BWC2A, 0);
+ }
+
+ if (test_thread_flag(TIF_SINGLE_STEP)) {
+ pr_debug("TIF_SINGLE_STEP set, ds = 0x%08lx\n", ds);
+ if (ds & DS_SSS) {
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ clear_thread_flag(TIF_SINGLE_STEP);
+ ptrace_break(current, regs);
+ }
+ } else {
+ /* regular breakpoint */
+ ptrace_break(current, regs);
+ }
+}
diff --git a/arch/avr32/kernel/semaphore.c b/arch/avr32/kernel/semaphore.c
new file mode 100644
index 00000000000..1e2705a0501
--- /dev/null
+++ b/arch/avr32/kernel/semaphore.c
@@ -0,0 +1,148 @@
+/*
+ * AVR32 sempahore implementation.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/i386/kernel/semaphore.c
+ * Copyright (C) 1999 Linus Torvalds
+ *
+ * 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/sched.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+#include <asm/semaphore.h>
+#include <asm/atomic.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to acquire the semaphore, while the "sleeping"
+ * variable is a count of such acquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is protected
+ * by the spinlock in the semaphore's waitqueue head.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ * - only on a boundary condition do we need to care. When we go
+ * from a negative count to a non-negative, we wake people up.
+ * - when we go from a non-negative count to a negative do we
+ * (a) synchronize with the "sleeper" count and (b) make sure
+ * that we're on the wakeup list before we synchronize so that
+ * we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+ wake_up(&sem->wait);
+}
+EXPORT_SYMBOL(__up);
+
+void __sched __down(struct semaphore *sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ unsigned long flags;
+
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock in
+ * the wait_queue_head.
+ */
+ if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ schedule();
+
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ }
+ remove_wait_queue_locked(&sem->wait, &wait);
+ wake_up_locked(&sem->wait);
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+ tsk->state = TASK_RUNNING;
+}
+EXPORT_SYMBOL(__down);
+
+int __sched __down_interruptible(struct semaphore *sem)
+{
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ unsigned long flags;
+
+ tsk->state = TASK_INTERRUPTIBLE;
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * With signals pending, this turns into the trylock
+ * failure case - we won't be sleeping, and we can't
+ * get the lock as it has contention. Just correct the
+ * count and exit.
+ */
+ if (signal_pending(current)) {
+ retval = -EINTR;
+ sem->sleepers = 0;
+ atomic_add(sleepers, &sem->count);
+ break;
+ }
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock in
+ * the wait_queue_head.
+ */
+ if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ schedule();
+
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ tsk->state = TASK_INTERRUPTIBLE;
+ }
+ remove_wait_queue_locked(&sem->wait, &wait);
+ wake_up_locked(&sem->wait);
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ tsk->state = TASK_RUNNING;
+ return retval;
+}
+EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
new file mode 100644
index 00000000000..5d68f3c6990
--- /dev/null
+++ b/arch/avr32/kernel/setup.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/console.h>
+#include <linux/ioport.h>
+#include <linux/bootmem.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+
+#include <asm/sections.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/sysreg.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/init.h>
+
+extern int root_mountflags;
+
+/*
+ * Bootloader-provided information about physical memory
+ */
+struct tag_mem_range *mem_phys;
+struct tag_mem_range *mem_reserved;
+struct tag_mem_range *mem_ramdisk;
+
+/*
+ * Initialize loops_per_jiffy as 5000000 (500MIPS).
+ * Better make it too large than too small...
+ */
+struct avr32_cpuinfo boot_cpu_data = {
+ .loops_per_jiffy = 5000000
+};
+EXPORT_SYMBOL(boot_cpu_data);
+
+static char command_line[COMMAND_LINE_SIZE];
+
+/*
+ * Should be more than enough, but if you have a _really_ complex
+ * setup, you might need to increase the size of this...
+ */
+static struct tag_mem_range __initdata mem_range_cache[32];
+static unsigned mem_range_next_free;
+
+/*
+ * Standard memory resources
+ */
+static struct resource mem_res[] = {
+ {
+ .name = "Kernel code",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .name = "Kernel data",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
+
+/*
+ * Early framebuffer allocation. Works as follows:
+ * - If fbmem_size is zero, nothing will be allocated or reserved.
+ * - If fbmem_start is zero when setup_bootmem() is called,
+ * fbmem_size bytes will be allocated from the bootmem allocator.
+ * - If fbmem_start is nonzero, an area of size fbmem_size will be
+ * reserved at the physical address fbmem_start if necessary. If
+ * the area isn't in a memory region known to the kernel, it will
+ * be left alone.
+ *
+ * Board-specific code may use these variables to set up platform data
+ * for the framebuffer driver if fbmem_size is nonzero.
+ */
+static unsigned long __initdata fbmem_start;
+static unsigned long __initdata fbmem_size;
+
+/*
+ * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for
+ * use as framebuffer.
+ *
+ * "fbmem=xxx[kKmM]@yyy[kKmM]" defines a memory region of size xxx and
+ * starting at yyy to be reserved for use as framebuffer.
+ *
+ * The kernel won't verify that the memory region starting at yyy
+ * actually contains usable RAM.
+ */
+static int __init early_parse_fbmem(char *p)
+{
+ fbmem_size = memparse(p, &p);
+ if (*p == '@')
+ fbmem_start = memparse(p, &p);
+ return 0;
+}
+early_param("fbmem", early_parse_fbmem);
+
+static inline void __init resource_init(void)
+{
+ struct tag_mem_range *region;
+
+ kernel_code.start = __pa(init_mm.start_code);
+ kernel_code.end = __pa(init_mm.end_code - 1);
+ kernel_data.start = __pa(init_mm.end_code);
+ kernel_data.end = __pa(init_mm.brk - 1);
+
+ for (region = mem_phys; region; region = region->next) {
+ struct resource *res;
+ unsigned long phys_start, phys_end;
+
+ if (region->size == 0)
+ continue;
+
+ phys_start = region->addr;
+ phys_end = phys_start + region->size - 1;
+
+ res = alloc_bootmem_low(sizeof(*res));
+ res->name = "System RAM";
+ res->start = phys_start;
+ res->end = phys_end;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+ request_resource (&iomem_resource, res);
+
+ if (kernel_code.start >= res->start &&
+ kernel_code.end <= res->end)
+ request_resource (res, &kernel_code);
+ if (kernel_data.start >= res->start &&
+ kernel_data.end <= res->end)
+ request_resource (res, &kernel_data);
+ }
+}
+
+static int __init parse_tag_core(struct tag *tag)
+{
+ if (tag->hdr.size > 2) {
+ if ((tag->u.core.flags & 1) == 0)
+ root_mountflags &= ~MS_RDONLY;
+ ROOT_DEV = new_decode_dev(tag->u.core.rootdev);
+ }
+ return 0;
+}
+__tagtable(ATAG_CORE, parse_tag_core);
+
+static int __init parse_tag_mem_range(struct tag *tag,
+ struct tag_mem_range **root)
+{
+ struct tag_mem_range *cur, **pprev;
+ struct tag_mem_range *new;
+
+ /*
+ * Ignore zero-sized entries. If we're running standalone, the
+ * SDRAM code may emit such entries if something goes
+ * wrong...
+ */
+ if (tag->u.mem_range.size == 0)
+ return 0;
+
+ /*
+ * Copy the data so the bootmem init code doesn't need to care
+ * about it.
+ */
+ if (mem_range_next_free >=
+ (sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
+ panic("Physical memory map too complex!\n");
+
+ new = &mem_range_cache[mem_range_next_free++];
+ *new = tag->u.mem_range;
+
+ pprev = root;
+ cur = *root;
+ while (cur) {
+ pprev = &cur->next;
+ cur = cur->next;
+ }
+
+ *pprev = new;
+ new->next = NULL;
+
+ return 0;
+}
+
+static int __init parse_tag_mem(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_phys);
+}
+__tagtable(ATAG_MEM, parse_tag_mem);
+
+static int __init parse_tag_cmdline(struct tag *tag)
+{
+ strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+ return 0;
+}
+__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
+
+static int __init parse_tag_rdimg(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_ramdisk);
+}
+__tagtable(ATAG_RDIMG, parse_tag_rdimg);
+
+static int __init parse_tag_clock(struct tag *tag)
+{
+ /*
+ * We'll figure out the clocks by peeking at the system
+ * manager regs directly.
+ */
+ return 0;
+}
+__tagtable(ATAG_CLOCK, parse_tag_clock);
+
+static int __init parse_tag_rsvd_mem(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_reserved);
+}
+__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
+
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+#if 0
+ const struct platform_device *pdev;
+
+ /*
+ * We really need a bus type that supports "classes"...this
+ * will do for now (until we must handle other kinds of
+ * ethernet controllers)
+ */
+ pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
+ if (pdev && pdev->dev.platform_data) {
+ struct eth_platform_data *data = pdev->dev.platform_data;
+
+ data->valid = 1;
+ data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
+ memcpy(data->hw_addr, tag->u.ethernet.hw_address,
+ sizeof(data->hw_addr));
+ }
+#endif
+ return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+/*
+ * Scan the tag table for this tag, and call its parse function. The
+ * tag table is built by the linker from all the __tagtable
+ * declarations.
+ */
+static int __init parse_tag(struct tag *tag)
+{
+ extern struct tagtable __tagtable_begin, __tagtable_end;
+ struct tagtable *t;
+
+ for (t = &__tagtable_begin; t < &__tagtable_end; t++)
+ if (tag->hdr.tag == t->tag) {
+ t->parse(tag);
+ break;
+ }
+
+ return t < &__tagtable_end;
+}
+
+/*
+ * Parse all tags in the list we got from the boot loader
+ */
+static void __init parse_tags(struct tag *t)
+{
+ for (; t->hdr.tag != ATAG_NONE; t = tag_next(t))
+ if (!parse_tag(t))
+ printk(KERN_WARNING
+ "Ignoring unrecognised tag 0x%08x\n",
+ t->hdr.tag);
+}
+
+void __init setup_arch (char **cmdline_p)
+{
+ struct clk *cpu_clk;
+
+ parse_tags(bootloader_tags);
+
+ setup_processor();
+ setup_platform();
+
+ cpu_clk = clk_get(NULL, "cpu");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_WARNING "Warning: Unable to get CPU clock\n");
+ } else {
+ unsigned long cpu_hz = clk_get_rate(cpu_clk);
+
+ /*
+ * Well, duh, but it's probably a good idea to
+ * increment the use count.
+ */
+ clk_enable(cpu_clk);
+
+ boot_cpu_data.clk = cpu_clk;
+ boot_cpu_data.loops_per_jiffy = cpu_hz * 4;
+ printk("CPU: Running at %lu.%03lu MHz\n",
+ ((cpu_hz + 500) / 1000) / 1000,
+ ((cpu_hz + 500) / 1000) % 1000);
+ }
+
+ init_mm.start_code = (unsigned long) &_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+ parse_early_param();
+
+ setup_bootmem();
+
+ board_setup_fbmem(fbmem_start, fbmem_size);
+
+#ifdef CONFIG_VT
+ conswitchp = &dummy_con;
+#endif
+
+ paging_init();
+
+ resource_init();
+}
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
new file mode 100644
index 00000000000..33096651c24
--- /dev/null
+++ b/arch/avr32/kernel/signal.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/sh/kernel/signal.c
+ * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 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/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/suspend.h>
+
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->sp);
+}
+
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ unsigned long retcode;
+};
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ int err = 0;
+
+#define COPY(x) err |= __get_user(regs->x, &sc->x)
+ COPY(sr);
+ COPY(pc);
+ COPY(lr);
+ COPY(sp);
+ COPY(r12);
+ COPY(r11);
+ COPY(r10);
+ COPY(r9);
+ COPY(r8);
+ COPY(r7);
+ COPY(r6);
+ COPY(r5);
+ COPY(r4);
+ COPY(r3);
+ COPY(r2);
+ COPY(r1);
+ COPY(r0);
+#undef COPY
+
+ /*
+ * Don't allow anyone to pretend they're running in supervisor
+ * mode or something...
+ */
+ err |= !valid_user_regs(regs);
+
+ return err;
+}
+
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ sigset_t set;
+
+ frame = (struct rt_sigframe __user *)regs->sp;
+ pr_debug("SIG return: frame = %p\n", frame);
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n",
+ regs->pc, regs->lr, regs->sp);
+
+ return regs->r12;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
+{
+ int err = 0;
+
+#define COPY(x) err |= __put_user(regs->x, &sc->x)
+ COPY(sr);
+ COPY(pc);
+ COPY(lr);
+ COPY(sp);
+ COPY(r12);
+ COPY(r11);
+ COPY(r10);
+ COPY(r9);
+ COPY(r8);
+ COPY(r7);
+ COPY(r6);
+ COPY(r5);
+ COPY(r4);
+ COPY(r3);
+ COPY(r2);
+ COPY(r1);
+ COPY(r0);
+#undef COPY
+
+ return err;
+}
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
+{
+ unsigned long sp = regs->sp;
+
+ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void __user *)((sp - framesize) & ~3);
+}
+
+static int
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ err = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto out;
+
+ /*
+ * Set up the return code:
+ *
+ * mov r8, __NR_rt_sigreturn
+ * scall
+ *
+ * Note: This will blow up since we're using a non-executable
+ * stack. Better use SA_RESTORER.
+ */
+#if __NR_rt_sigreturn > 127
+# error __NR_rt_sigreturn must be < 127 to fit in a short mov
+#endif
+ err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
+ &frame->retcode);
+
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Set up the ucontext */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __put_user((void __user *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->sp),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto out;
+
+ regs->r12 = sig;
+ regs->r11 = (unsigned long) &frame->info;
+ regs->r10 = (unsigned long) &frame->uc;
+ regs->sp = (unsigned long) frame;
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->lr = (unsigned long)ka->sa.sa_restorer;
+ else {
+ printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
+ current->comm, current->pid);
+ regs->lr = (unsigned long) &frame->retcode;
+ }
+
+ pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
+ current->comm, current->pid, sig, regs->sp,
+ regs->pc, ka->sa.sa_handler, regs->lr);
+
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+out:
+ return err;
+}
+
+static inline void restart_syscall(struct pt_regs *regs)
+{
+ if (regs->r12 == -ERESTART_RESTARTBLOCK)
+ regs->r8 = __NR_restart_syscall;
+ else
+ regs->r12 = regs->r12_orig;
+ regs->pc -= 2;
+}
+
+static inline void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *oldset, struct pt_regs *regs, int syscall)
+{
+ int ret;
+
+ /*
+ * Set up the stack frame
+ */
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ /*
+ * Check that the resulting registers are sane
+ */
+ ret |= !valid_user_regs(regs);
+
+ /*
+ * Block the signal if we were unsuccessful.
+ */
+ if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka->sa.sa_mask);
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ if (ret == 0)
+ return;
+
+ force_sigsegv(sig, current);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it
+ * doesn't want to handle. Thus you cannot kill init even with a
+ * SIGKILL even by mistake.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+
+ /*
+ * We want the common case to go fast, which is why we may in
+ * certain cases get here from kernel mode. Just return
+ * without doing anything if so.
+ */
+ if (!user_mode(regs))
+ return 0;
+
+ if (try_to_freeze()) {
+ signr = 0;
+ if (!signal_pending(current))
+ goto no_signal;
+ }
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else if (!oldset)
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+no_signal:
+ if (syscall) {
+ switch (regs->r12) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ if (signr > 0) {
+ regs->r12 = -EINTR;
+ break;
+ }
+ /* fall through */
+ case -ERESTARTSYS:
+ if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
+ regs->r12 = -EINTR;
+ break;
+ }
+ /* fall through */
+ case -ERESTARTNOINTR:
+ restart_syscall(regs);
+ }
+ }
+
+ if (signr == 0) {
+ /* No signal to deliver -- put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+ return 0;
+ }
+
+ handle_signal(signr, &ka, &info, oldset, regs, syscall);
+ return 1;
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
+{
+ int syscall = 0;
+
+ if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
+ syscall = 1;
+
+ if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs, &current->blocked, syscall);
+}
diff --git a/arch/avr32/kernel/switch_to.S b/arch/avr32/kernel/switch_to.S
new file mode 100644
index 00000000000..a48d046723c
--- /dev/null
+++ b/arch/avr32/kernel/switch_to.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/sysreg.h>
+
+ .text
+ .global __switch_to
+ .type __switch_to, @function
+
+ /* Switch thread context from "prev" to "next", returning "last"
+ * r12 : prev
+ * r11 : &prev->thread + 1
+ * r10 : &next->thread
+ */
+__switch_to:
+ stm --r11, r0,r1,r2,r3,r4,r5,r6,r7,sp,lr
+ mfsr r9, SYSREG_SR
+ st.w --r11, r9
+ ld.w r8, r10++
+ /*
+ * schedule() may have been called from a mode with a different
+ * set of registers. Make sure we don't lose anything here.
+ */
+ pushm r10,r12
+ mtsr SYSREG_SR, r8
+ frs /* flush the return stack */
+ sub pc, -2 /* flush the pipeline */
+ popm r10,r12
+ ldm r10++, r0,r1,r2,r3,r4,r5,r6,r7,sp,pc
+ .size __switch_to, . - __switch_to
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c
new file mode 100644
index 00000000000..6ec5693da44
--- /dev/null
+++ b/arch/avr32/kernel/sys_avr32.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/unistd.h>
+
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_pipe(unsigned long __user *filedes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(filedes, fd, sizeof(fd)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
+{
+ int error = -EBADF;
+ struct file *file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ return error;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, offset);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+ return error;
+}
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
new file mode 100644
index 00000000000..7589a9b426c
--- /dev/null
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+/*
+ * Stubs for syscalls that require access to pt_regs or that take more
+ * than five parameters.
+ */
+
+#define ARG6 r3
+
+ .text
+ .global __sys_rt_sigsuspend
+ .type __sys_rt_sigsuspend,@function
+__sys_rt_sigsuspend:
+ mov r10, sp
+ rjmp sys_rt_sigsuspend
+
+ .global __sys_sigaltstack
+ .type __sys_sigaltstack,@function
+__sys_sigaltstack:
+ mov r10, sp
+ rjmp sys_sigaltstack
+
+ .global __sys_rt_sigreturn
+ .type __sys_rt_sigreturn,@function
+__sys_rt_sigreturn:
+ mov r12, sp
+ rjmp sys_rt_sigreturn
+
+ .global __sys_fork
+ .type __sys_fork,@function
+__sys_fork:
+ mov r12, sp
+ rjmp sys_fork
+
+ .global __sys_clone
+ .type __sys_clone,@function
+__sys_clone:
+ mov r8, sp
+ rjmp sys_clone
+
+ .global __sys_vfork
+ .type __sys_vfork,@function
+__sys_vfork:
+ mov r12, sp
+ rjmp sys_vfork
+
+ .global __sys_execve
+ .type __sys_execve,@function
+__sys_execve:
+ mov r9, sp
+ rjmp sys_execve
+
+ .global __sys_mmap2
+ .type __sys_mmap2,@function
+__sys_mmap2:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_mmap2
+ sub sp, -4
+ popm pc
+
+ .global __sys_sendto
+ .type __sys_sendto,@function
+__sys_sendto:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_sendto
+ sub sp, -4
+ popm pc
+
+ .global __sys_recvfrom
+ .type __sys_recvfrom,@function
+__sys_recvfrom:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_recvfrom
+ sub sp, -4
+ popm pc
+
+ .global __sys_pselect6
+ .type __sys_pselect6,@function
+__sys_pselect6:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_pselect6
+ sub sp, -4
+ popm pc
+
+ .global __sys_splice
+ .type __sys_splice,@function
+__sys_splice:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_splice
+ sub sp, -4
+ popm pc
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
new file mode 100644
index 00000000000..63b206965d0
--- /dev/null
+++ b/arch/avr32/kernel/syscall_table.S
@@ -0,0 +1,289 @@
+/*
+ * AVR32 system call table
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_SYSV_IPC)
+# define sys_ipc sys_ni_syscall
+#endif
+
+ .section .rodata,"a",@progbits
+ .type sys_call_table,@object
+ .global sys_call_table
+ .align 2
+sys_call_table:
+ .long sys_restart_syscall
+ .long sys_exit
+ .long __sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_umask
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long __sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_chown
+ .long sys_lchown
+ .long sys_lseek
+ .long sys_llseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_umount
+ .long sys_setuid
+ .long sys_getuid
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_pause
+ .long sys_utime
+ .long sys_newstat /* 30 */
+ .long sys_newfstat
+ .long sys_newlstat
+ .long sys_access
+ .long sys_chroot
+ .long sys_sync /* 35 */
+ .long sys_fsync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long __sys_clone
+ .long sys_brk /* 45 */
+ .long sys_setgid
+ .long sys_getgid
+ .long sys_getcwd
+ .long sys_geteuid
+ .long sys_getegid /* 50 */
+ .long sys_acct
+ .long sys_setfsuid
+ .long sys_setfsgid
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_setpgid
+ .long sys_mremap
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setreuid /* 60 */
+ .long sys_setregid
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_rt_sigaction
+ .long __sys_rt_sigreturn
+ .long sys_rt_sigprocmask
+ .long sys_rt_sigpending /* 70 */
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long __sys_rt_sigsuspend
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups /* 80 */
+ .long sys_setgroups
+ .long sys_select
+ .long sys_symlink
+ .long sys_fchdir
+ .long sys_readlink /* 85 */
+ .long sys_pread64
+ .long sys_pwrite64
+ .long sys_swapon
+ .long sys_reboot
+ .long __sys_mmap2 /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_wait4
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_vhangup
+ .long __sys_sigaltstack
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_swapoff
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_sendfile
+ .long sys_setdomainname /* 110 */
+ .long sys_newuname
+ .long sys_adjtimex
+ .long sys_mprotect
+ .long __sys_vfork
+ .long sys_init_module /* 115 */
+ .long sys_delete_module
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_bdflush
+ .long sys_sysfs /* 120 */
+ .long sys_personality
+ .long sys_ni_syscall /* reserved for afs_syscall */
+ .long sys_getdents
+ .long sys_flock
+ .long sys_msync /* 125 */
+ .long sys_readv
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl /* 130 */
+ .long sys_mlock
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam /* 135 */
+ .long sys_sched_getparam
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max /* 140 */
+ .long sys_sched_get_priority_min
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_poll
+ .long sys_nfsservctl /* 145 */
+ .long sys_setresgid
+ .long sys_getresgid
+ .long sys_prctl
+ .long sys_socket
+ .long sys_bind /* 150 */
+ .long sys_connect
+ .long sys_listen
+ .long sys_accept
+ .long sys_getsockname
+ .long sys_getpeername /* 155 */
+ .long sys_socketpair
+ .long sys_send
+ .long sys_recv
+ .long __sys_sendto
+ .long __sys_recvfrom /* 160 */
+ .long sys_shutdown
+ .long sys_setsockopt
+ .long sys_getsockopt
+ .long sys_sendmsg
+ .long sys_recvmsg /* 165 */
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64
+ .long sys_lstat64
+ .long sys_fstat64 /* 170 */
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64
+ .long sys_fcntl64 /* 175 */
+ .long sys_gettid
+ .long sys_readahead
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr /* 180 */
+ .long sys_getxattr
+ .long sys_lgetxattr
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr /* 185 */
+ .long sys_flistxattr
+ .long sys_removexattr
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill /* 190 */
+ .long sys_sendfile64
+ .long sys_futex
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_capget /* 195 */
+ .long sys_capset
+ .long sys_io_setup
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit /* 200 */
+ .long sys_io_cancel
+ .long sys_fadvise64
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create /* 205 */
+ .long sys_epoll_ctl
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create /* 210 */
+ .long sys_timer_settime
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime /* 215 */
+ .long sys_clock_gettime
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64 /* 220 */
+ .long sys_tgkill
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_utimes
+ .long sys_fadvise64_64
+ .long sys_cacheflush /* 225 */
+ .long sys_ni_syscall /* sys_vserver */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 230 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_kexec_load
+ .long sys_waitid
+ .long sys_add_key /* 235 */
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get
+ .long sys_inotify_init /* 240 */
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_openat
+ .long sys_mkdirat
+ .long sys_mknodat /* 245 */
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64
+ .long sys_unlinkat
+ .long sys_renameat /* 250 */
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat
+ .long sys_fchmodat
+ .long sys_faccessat /* 255 */
+ .long __sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare
+ .long sys_set_robust_list
+ .long sys_get_robust_list /* 260 */
+ .long __sys_splice
+ .long sys_sync_file_range
+ .long sys_tee
+ .long sys_vmsplice
+ .long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
new file mode 100644
index 00000000000..b0e6b5855a3
--- /dev/null
+++ b/arch/avr32/kernel/time.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on MIPS implementation arch/mips/kernel/time.c
+ * Copyright 2001 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/clk.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/sysdev.h>
+
+#include <asm/div64.h>
+#include <asm/sysreg.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+static cycle_t read_cycle_count(void)
+{
+ return (cycle_t)sysreg_read(COUNT);
+}
+
+static struct clocksource clocksource_avr32 = {
+ .name = "avr32",
+ .rating = 350,
+ .read = read_cycle_count,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 16,
+ .is_continuous = 1,
+};
+
+/*
+ * By default we provide the null RTC ops
+ */
+static unsigned long null_rtc_get_time(void)
+{
+ return mktime(2004, 1, 1, 0, 0, 0);
+}
+
+static int null_rtc_set_time(unsigned long sec)
+{
+ return 0;
+}
+
+static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
+
+/* how many counter cycles in a jiffy? */
+static unsigned long cycles_per_jiffy;
+
+/* cycle counter value at the previous timer interrupt */
+static unsigned int timerhi, timerlo;
+
+/* the count value for the next timer interrupt */
+static unsigned int expirelo;
+
+static void avr32_timer_ack(void)
+{
+ unsigned int count;
+
+ /* Ack this timer interrupt and set the next one */
+ expirelo += cycles_per_jiffy;
+ if (expirelo == 0) {
+ printk(KERN_DEBUG "expirelo == 0\n");
+ sysreg_write(COMPARE, expirelo + 1);
+ } else {
+ sysreg_write(COMPARE, expirelo);
+ }
+
+ /* Check to see if we have missed any timer interrupts */
+ count = sysreg_read(COUNT);
+ if ((count - expirelo) < 0x7fffffff) {
+ expirelo = count + cycles_per_jiffy;
+ sysreg_write(COMPARE, expirelo);
+ }
+}
+
+static unsigned int avr32_hpt_read(void)
+{
+ return sysreg_read(COUNT);
+}
+
+/*
+ * Taken from MIPS c0_hpt_timer_init().
+ *
+ * Why is it so complicated, and what is "count"? My assumption is
+ * that `count' specifies the "reference cycle", i.e. the cycle since
+ * reset that should mean "zero". The reason COUNT is written twice is
+ * probably to make sure we don't get any timer interrupts while we
+ * are messing with the counter.
+ */
+static void avr32_hpt_init(unsigned int count)
+{
+ count = sysreg_read(COUNT) - count;
+ expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+ sysreg_write(COUNT, expirelo - cycles_per_jiffy);
+ sysreg_write(COMPARE, expirelo);
+ sysreg_write(COUNT, count);
+}
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ /* There must be better ways...? */
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+/*
+ * local_timer_interrupt() does profiling and process accounting on a
+ * per-CPU basis.
+ *
+ * In UP mode, it is invoked from the (global) timer_interrupt.
+ */
+static void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (current->pid)
+ profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(regs));
+}
+
+static irqreturn_t
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int count;
+
+ /* ack timer interrupt and try to set next interrupt */
+ count = avr32_hpt_read();
+ avr32_timer_ack();
+
+ /* Update timerhi/timerlo for intra-jiffy calibration */
+ timerhi += count < timerlo; /* Wrap around */
+ timerlo = count;
+
+ /*
+ * Call the generic timer interrupt handler
+ */
+ write_seqlock(&xtime_lock);
+ do_timer(regs);
+ write_sequnlock(&xtime_lock);
+
+ /*
+ * In UP mode, we call local_timer_interrupt() to do profiling
+ * and process accounting.
+ *
+ * SMP is not supported yet.
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction timer_irqaction = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "timer",
+};
+
+void __init time_init(void)
+{
+ unsigned long mult, shift, count_hz;
+ int ret;
+
+ xtime.tv_sec = rtc_get_time();
+ xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ printk("Before time_init: count=%08lx, compare=%08lx\n",
+ (unsigned long)sysreg_read(COUNT),
+ (unsigned long)sysreg_read(COMPARE));
+
+ count_hz = clk_get_rate(boot_cpu_data.clk);
+ shift = clocksource_avr32.shift;
+ mult = clocksource_hz2mult(count_hz, shift);
+ clocksource_avr32.mult = mult;
+
+ printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift);
+
+ {
+ u64 tmp;
+
+ tmp = TICK_NSEC;
+ tmp <<= shift;
+ tmp += mult / 2;
+ do_div(tmp, mult);
+
+ cycles_per_jiffy = tmp;
+ }
+
+ /* This sets up the high precision timer for the first interrupt. */
+ avr32_hpt_init(avr32_hpt_read());
+
+ printk("After time_init: count=%08lx, compare=%08lx\n",
+ (unsigned long)sysreg_read(COUNT),
+ (unsigned long)sysreg_read(COMPARE));
+
+ ret = clocksource_register(&clocksource_avr32);
+ if (ret)
+ printk(KERN_ERR
+ "timer: could not register clocksource: %d\n", ret);
+
+ ret = setup_irq(0, &timer_irqaction);
+ if (ret)
+ printk("timer: could not request IRQ 0: %d\n", ret);
+}
+
+static struct sysdev_class timer_class = {
+ set_kset_name("timer"),
+};
+
+static struct sys_device timer_device = {
+ .id = 0,
+ .cls = &timer_class,
+};
+
+static int __init init_timer_sysfs(void)
+{
+ int err = sysdev_class_register(&timer_class);
+ if (!err)
+ err = sysdev_register(&timer_device);
+ return err;
+}
+
+device_initcall(init_timer_sysfs);
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
new file mode 100644
index 00000000000..7e803f4d7a1
--- /dev/null
+++ b/arch/avr32/kernel/traps.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#undef DEBUG
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/notifier.h>
+
+#include <asm/traps.h>
+#include <asm/sysreg.h>
+#include <asm/addrspace.h>
+#include <asm/ocd.h>
+#include <asm/mmu_context.h>
+#include <asm/uaccess.h>
+
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+ unsigned long p;
+ int i;
+
+ printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+ for (p = bottom & ~31; p < top; ) {
+ printk("%04lx: ", p & 0xffff);
+
+ for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
+ if (p < bottom || p >= top)
+ printk(" ");
+ else {
+ if (__get_user(val, (unsigned int __user *)p)) {
+ printk("\n");
+ goto out;
+ }
+ printk("%08x ", val);
+ }
+ }
+ printk("\n");
+ }
+
+out:
+ return;
+}
+
+#ifdef CONFIG_FRAME_POINTER
+static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ unsigned long __user *fp;
+ unsigned long __user *last_fp = NULL;
+
+ if (regs) {
+ fp = (unsigned long __user *)regs->r7;
+ } else if (tsk == current) {
+ register unsigned long __user *real_fp __asm__("r7");
+ fp = real_fp;
+ } else {
+ fp = (unsigned long __user *)tsk->thread.cpu_context.r7;
+ }
+
+ /*
+ * Walk the stack until (a) we get an exception, (b) the frame
+ * pointer becomes zero, or (c) the frame pointer gets stuck
+ * at the same value.
+ */
+ while (fp && fp != last_fp) {
+ unsigned long lr, new_fp = 0;
+
+ last_fp = fp;
+ if (__get_user(lr, fp))
+ break;
+ if (fp && __get_user(new_fp, fp + 1))
+ break;
+ fp = (unsigned long __user *)new_fp;
+
+ printk(" [<%08lx>] ", lr);
+ print_symbol("%s\n", lr);
+ }
+ printk("\n");
+}
+#else
+static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ unsigned long addr;
+
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ if (kernel_text_address(addr)) {
+ printk(" [<%08lx>] ", addr);
+ print_symbol("%s\n", addr);
+ }
+ }
+}
+#endif
+
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ if (regs &&
+ (((regs->sr & MODE_MASK) == MODE_EXCEPTION) ||
+ ((regs->sr & MODE_MASK) == MODE_USER)))
+ return;
+
+ printk ("Call trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+
+ __show_trace(tsk, sp, regs);
+ printk("\n");
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+ unsigned long stack;
+
+ if (!tsk)
+ tsk = current;
+ if (sp == 0) {
+ if (tsk == current) {
+ register unsigned long *real_sp __asm__("sp");
+ sp = real_sp;
+ } else {
+ sp = (unsigned long *)tsk->thread.cpu_context.ksp;
+ }
+ }
+
+ stack = (unsigned long)sp;
+ dump_mem("Stack: ", stack,
+ THREAD_SIZE + (unsigned long)tsk->thread_info);
+ show_trace(tsk, sp, NULL);
+}
+
+void dump_stack(void)
+{
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ pr_debug("register_die_notifier: %p\n", nb);
+
+ return atomic_notifier_chain_register(&avr32_die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&avr32_die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
+static DEFINE_SPINLOCK(die_lock);
+
+void __die(const char *str, struct pt_regs *regs, unsigned long err,
+ const char *file, const char *func, unsigned long line)
+{
+ struct task_struct *tsk = current;
+ static int die_counter;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+
+ printk(KERN_ALERT "%s", str);
+ if (file && func)
+ printk(" in %s:%s, line %ld", file, func, line);
+ printk("[#%d]:\n", ++die_counter);
+ print_modules();
+ show_regs(regs);
+ printk("Process %s (pid: %d, stack limit = 0x%p)\n",
+ tsk->comm, tsk->pid, tsk->thread_info + 1);
+
+ if (!user_mode(regs) || in_interrupt()) {
+ dump_mem("Stack: ", regs->sp,
+ THREAD_SIZE + (unsigned long)tsk->thread_info);
+ }
+
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+}
+
+void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err,
+ const char *file, const char *func, unsigned long line)
+{
+ if (!user_mode(regs))
+ __die(str, regs, err, file, func, line);
+}
+
+asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
+{
+#ifdef CONFIG_SUBARCH_AVR32B
+ /*
+ * The exception entry always saves RSR_EX. For NMI, this is
+ * wrong; it should be RSR_NMI
+ */
+ regs->sr = sysreg_read(RSR_NMI);
+#endif
+
+ printk("NMI taken!!!!\n");
+ die("NMI", regs, ecr);
+ BUG();
+}
+
+asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)
+{
+ printk("Unable to handle critical exception %lu at pc = %08lx!\n",
+ ecr, regs->pc);
+ die("Oops", regs, ecr);
+ BUG();
+}
+
+asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ die_if_kernel("Oops: Address exception in kernel mode", regs, ecr);
+
+#ifdef DEBUG
+ if (ecr == ECR_ADDR_ALIGN_X)
+ pr_debug("Instruction Address Exception at pc = %08lx\n",
+ regs->pc);
+ else if (ecr == ECR_ADDR_ALIGN_R)
+ pr_debug("Data Address Exception (Read) at pc = %08lx\n",
+ regs->pc);
+ else if (ecr == ECR_ADDR_ALIGN_W)
+ pr_debug("Data Address Exception (Write) at pc = %08lx\n",
+ regs->pc);
+ else
+ BUG();
+
+ show_regs(regs);
+#endif
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void __user *)regs->pc;
+
+ force_sig_info(SIGBUS, &info, current);
+}
+
+/* This way of handling undefined instructions is stolen from ARM */
+static LIST_HEAD(undef_hook);
+static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
+
+void register_undef_hook(struct undef_hook *hook)
+{
+ spin_lock_irq(&undef_lock);
+ list_add(&hook->node, &undef_hook);
+ spin_unlock_irq(&undef_lock);
+}
+
+void unregister_undef_hook(struct undef_hook *hook)
+{
+ spin_lock_irq(&undef_lock);
+ list_del(&hook->node);
+ spin_unlock_irq(&undef_lock);
+}
+
+static int do_cop_absent(u32 insn)
+{
+ int cop_nr;
+ u32 cpucr;
+ if ( (insn & 0xfdf00000) == 0xf1900000 )
+ /* LDC0 */
+ cop_nr = 0;
+ else
+ cop_nr = (insn >> 13) & 0x7;
+
+ /* Try enabling the coprocessor */
+ cpucr = sysreg_read(CPUCR);
+ cpucr |= (1 << (24 + cop_nr));
+ sysreg_write(CPUCR, cpucr);
+
+ cpucr = sysreg_read(CPUCR);
+ if ( !(cpucr & (1 << (24 + cop_nr))) ){
+ printk("Coprocessor #%i not found!\n", cop_nr);
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_BUG
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
+{
+ char *file;
+ u16 line;
+ char c;
+
+ if (__get_user(line, (u16 __user *)(regs->pc + 2)))
+ return;
+ if (__get_user(file, (char * __user *)(regs->pc + 4))
+ || (unsigned long)file < PAGE_OFFSET
+ || __get_user(c, file))
+ file = "<bad filename>";
+
+ printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
+}
+#else
+static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
+{
+
+}
+#endif
+#endif
+
+asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
+{
+ u32 insn;
+ struct undef_hook *hook;
+ siginfo_t info;
+ void __user *pc;
+
+ if (!user_mode(regs))
+ goto kernel_trap;
+
+ local_irq_enable();
+
+ pc = (void __user *)instruction_pointer(regs);
+ if (__get_user(insn, (u32 __user *)pc))
+ goto invalid_area;
+
+ if (ecr == ECR_COPROC_ABSENT) {
+ if (do_cop_absent(insn) == 0)
+ return;
+ }
+
+ spin_lock_irq(&undef_lock);
+ list_for_each_entry(hook, &undef_hook, node) {
+ if ((insn & hook->insn_mask) == hook->insn_val) {
+ if (hook->fn(regs, insn) == 0) {
+ spin_unlock_irq(&undef_lock);
+ return;
+ }
+ }
+ }
+ spin_unlock_irq(&undef_lock);
+
+invalid_area:
+
+#ifdef DEBUG
+ printk("Illegal instruction at pc = %08lx\n", regs->pc);
+ if (regs->pc < TASK_SIZE) {
+ unsigned long ptbr, pgd, pte, *p;
+
+ ptbr = sysreg_read(PTBR);
+ p = (unsigned long *)ptbr;
+ pgd = p[regs->pc >> 22];
+ p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000);
+ pte = p[(regs->pc >> 12) & 0x3ff];
+ printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte);
+ }
+#endif
+
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)regs->pc;
+ switch (ecr) {
+ case ECR_ILLEGAL_OPCODE:
+ case ECR_UNIMPL_INSTRUCTION:
+ info.si_code = ILL_ILLOPC;
+ break;
+ case ECR_PRIVILEGE_VIOLATION:
+ info.si_code = ILL_PRVOPC;
+ break;
+ case ECR_COPROC_ABSENT:
+ info.si_code = ILL_COPROC;
+ break;
+ default:
+ BUG();
+ }
+
+ force_sig_info(SIGILL, &info, current);
+ return;
+
+kernel_trap:
+#ifdef CONFIG_BUG
+ if (__kernel_text_address(instruction_pointer(regs))) {
+ insn = *(u16 *)instruction_pointer(regs);
+ if (insn == AVR32_BUG_OPCODE) {
+ do_bug_verbose(regs, insn);
+ die("Kernel BUG", regs, 0);
+ return;
+ }
+ }
+#endif
+
+ die("Oops: Illegal instruction in kernel code", regs, ecr);
+}
+
+asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ printk("Floating-point exception at pc = %08lx\n", regs->pc);
+
+ /* We have no FPU... */
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)regs->pc;
+ info.si_code = ILL_COPROC;
+
+ force_sig_info(SIGILL, &info, current);
+}
+
+
+void __init trap_init(void)
+{
+
+}
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
new file mode 100644
index 00000000000..cdd627c6b7d
--- /dev/null
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -0,0 +1,139 @@
+/*
+ * AVR32 linker script for the Linux kernel
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#define LOAD_OFFSET 0x00000000
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32")
+OUTPUT_ARCH(avr32)
+ENTRY(_start)
+
+/* Big endian */
+jiffies = jiffies_64 + 4;
+
+SECTIONS
+{
+ . = CONFIG_ENTRY_ADDRESS;
+ .init : AT(ADDR(.init) - LOAD_OFFSET) {
+ _stext = .;
+ __init_begin = .;
+ _sinittext = .;
+ *(.text.reset)
+ *(.init.text)
+ _einittext = .;
+ . = ALIGN(4);
+ __tagtable_begin = .;
+ *(.taglist)
+ __tagtable_end = .;
+ *(.init.data)
+ . = ALIGN(16);
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ . = ALIGN(4);
+ __initcall_start = .;
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ __initcall_end = .;
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ __security_initcall_start = .;
+ *(.security_initcall.init)
+ __security_initcall_end = .;
+ . = ALIGN(32);
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ }
+
+ . = ALIGN(8192);
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ _evba = .;
+ _text = .;
+ *(.ex.text)
+ . = 0x50;
+ *(.tlbx.ex.text)
+ . = 0x60;
+ *(.tlbr.ex.text)
+ . = 0x70;
+ *(.tlbw.ex.text)
+ . = 0x100;
+ *(.scall.text)
+ *(.irq.text)
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ _etext = .;
+ } = 0xd703d703
+
+ . = ALIGN(4);
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ RODATA
+
+ . = ALIGN(8192);
+
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ _data = .;
+ _sdata = .;
+ /*
+ * First, the init task union, aligned to an 8K boundary.
+ */
+ *(.data.init_task)
+
+ /* Then, the cacheline aligned data */
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
+
+ /* And the rest... */
+ *(.data.rel*)
+ *(.data)
+ CONSTRUCTORS
+
+ _edata = .;
+ }
+
+
+ . = ALIGN(8);
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ __bss_start = .;
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(8);
+ __bss_stop = .;
+ _end = .;
+ }
+
+ /* When something in the kernel is NOT compiled as a module, the module
+ * cleanup code and data are put into these segments. Both can then be
+ * thrown away, as cleanup code is never called unless it's a module.
+ */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ DWARF_DEBUG
+}
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile
new file mode 100644
index 00000000000..09ac43e4052
--- /dev/null
+++ b/arch/avr32/lib/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for AVR32-specific library files
+#
+
+lib-y := copy_user.o clear_user.o
+lib-y += strncpy_from_user.o strnlen_user.o
+lib-y += delay.o memset.o memcpy.o findbit.o
+lib-y += csum_partial.o csum_partial_copy_generic.o
+lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o
+lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o
diff --git a/arch/avr32/lib/__avr32_asr64.S b/arch/avr32/lib/__avr32_asr64.S
new file mode 100644
index 00000000000..368b6bca4c7
--- /dev/null
+++ b/arch/avr32/lib/__avr32_asr64.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ /*
+ * DWtype __avr32_asr64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_asr64
+ .type __avr32_asr64,@function
+__avr32_asr64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsl r8, r11, r9
+ lsr r10, r10, r12
+ asr r11, r11, r12
+ or r10, r8
+ retal r12
+
+1: neg r9
+ asr r10, r11, r9
+ asr r11, 31
+ retal r12
diff --git a/arch/avr32/lib/__avr32_lsl64.S b/arch/avr32/lib/__avr32_lsl64.S
new file mode 100644
index 00000000000..f1dbc2b3625
--- /dev/null
+++ b/arch/avr32/lib/__avr32_lsl64.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ /*
+ * DWtype __avr32_lsl64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_lsl64
+ .type __avr32_lsl64,@function
+__avr32_lsl64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsr r8, r10, r9
+ lsl r10, r10, r12
+ lsl r11, r11, r12
+ or r11, r8
+ retal r12
+
+1: neg r9
+ lsl r11, r10, r9
+ mov r10, 0
+ retal r12
diff --git a/arch/avr32/lib/__avr32_lsr64.S b/arch/avr32/lib/__avr32_lsr64.S
new file mode 100644
index 00000000000..e65bb7f0d24
--- /dev/null
+++ b/arch/avr32/lib/__avr32_lsr64.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ /*
+ * DWtype __avr32_lsr64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_lsr64
+ .type __avr32_lsr64,@function
+__avr32_lsr64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsl r8, r11, r9
+ lsr r11, r11, r12
+ lsr r10, r10, r12
+ or r10, r8
+ retal r12
+
+1: neg r9
+ lsr r10, r11, r9
+ mov r11, 0
+ retal r12
diff --git a/arch/avr32/lib/clear_user.S b/arch/avr32/lib/clear_user.S
new file mode 100644
index 00000000000..d8991b6f8eb
--- /dev/null
+++ b/arch/avr32/lib/clear_user.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/asm.h>
+
+ .text
+ .align 1
+ .global clear_user
+ .type clear_user, "function"
+clear_user:
+ branch_if_kernel r8, __clear_user
+ ret_if_privileged r8, r12, r11, r11
+
+ .global __clear_user
+ .type __clear_user, "function"
+__clear_user:
+ mov r9, r12
+ mov r8, 0
+ andl r9, 3, COH
+ brne 5f
+
+1: sub r11, 4
+ brlt 2f
+
+10: st.w r12++, r8
+ sub r11, 4
+ brge 10b
+
+2: sub r11, -4
+ reteq 0
+
+ /* Unaligned count or address */
+ bld r11, 1
+ brcc 12f
+11: st.h r12++, r8
+ sub r11, 2
+ reteq 0
+12: st.b r12++, r8
+ retal 0
+
+ /* Unaligned address */
+5: cp.w r11, 4
+ brlt 2b
+
+ lsl r9, 2
+ add pc, pc, r9
+13: st.b r12++, r8
+ sub r11, 1
+14: st.b r12++, r8
+ sub r11, 1
+15: st.b r12++, r8
+ sub r11, 1
+ rjmp 1b
+
+ .size clear_user, . - clear_user
+ .size __clear_user, . - __clear_user
+
+ .section .fixup, "ax"
+ .align 1
+18: sub r11, -4
+19: retal r11
+
+ .section __ex_table, "a"
+ .align 2
+ .long 10b, 18b
+ .long 11b, 19b
+ .long 12b, 19b
+ .long 13b, 19b
+ .long 14b, 19b
+ .long 15b, 19b
diff --git a/arch/avr32/lib/copy_user.S b/arch/avr32/lib/copy_user.S
new file mode 100644
index 00000000000..ea59c04b07d
--- /dev/null
+++ b/arch/avr32/lib/copy_user.S
@@ -0,0 +1,119 @@
+/*
+ * Copy to/from userspace with optional address space checking.
+ *
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/asm.h>
+
+ /*
+ * __kernel_size_t
+ * __copy_user(void *to, const void *from, __kernel_size_t n)
+ *
+ * Returns the number of bytes not copied. Might be off by
+ * max 3 bytes if we get a fault in the main loop.
+ *
+ * The address-space checking functions simply fall through to
+ * the non-checking version.
+ */
+ .text
+ .align 1
+ .global copy_from_user
+ .type copy_from_user, @function
+copy_from_user:
+ branch_if_kernel r8, __copy_user
+ ret_if_privileged r8, r11, r10, r10
+ rjmp __copy_user
+ .size copy_from_user, . - copy_from_user
+
+ .global copy_to_user
+ .type copy_to_user, @function
+copy_to_user:
+ branch_if_kernel r8, __copy_user
+ ret_if_privileged r8, r12, r10, r10
+ .size copy_to_user, . - copy_to_user
+
+ .global __copy_user
+ .type __copy_user, @function
+__copy_user:
+ mov r9, r11
+ andl r9, 3, COH
+ brne 6f
+
+ /* At this point, from is word-aligned */
+1: sub r10, 4
+ brlt 3f
+
+2:
+10: ld.w r8, r11++
+11: st.w r12++, r8
+ sub r10, 4
+ brge 2b
+
+3: sub r10, -4
+ reteq 0
+
+ /*
+ * Handle unaligned count. Need to be careful with r10 here so
+ * that we return the correct value even if we get a fault
+ */
+4:
+20: ld.ub r8, r11++
+21: st.b r12++, r8
+ sub r10, 1
+ reteq 0
+22: ld.ub r8, r11++
+23: st.b r12++, r8
+ sub r10, 1
+ reteq 0
+24: ld.ub r8, r11++
+25: st.b r12++, r8
+ retal 0
+
+ /* Handle unaligned from-pointer */
+6: cp.w r10, 4
+ brlt 4b
+ rsub r9, r9, 4
+
+30: ld.ub r8, r11++
+31: st.b r12++, r8
+ sub r10, 1
+ sub r9, 1
+ breq 1b
+32: ld.ub r8, r11++
+33: st.b r12++, r8
+ sub r10, 1
+ sub r9, 1
+ breq 1b
+34: ld.ub r8, r11++
+35: st.b r12++, r8
+ sub r10, 1
+ rjmp 1b
+ .size __copy_user, . - __copy_user
+
+ .section .fixup,"ax"
+ .align 1
+19: sub r10, -4
+29: retal r10
+
+ .section __ex_table,"a"
+ .align 2
+ .long 10b, 19b
+ .long 11b, 19b
+ .long 20b, 29b
+ .long 21b, 29b
+ .long 22b, 29b
+ .long 23b, 29b
+ .long 24b, 29b
+ .long 25b, 29b
+ .long 30b, 29b
+ .long 31b, 29b
+ .long 32b, 29b
+ .long 33b, 29b
+ .long 34b, 29b
+ .long 35b, 29b
diff --git a/arch/avr32/lib/csum_partial.S b/arch/avr32/lib/csum_partial.S
new file mode 100644
index 00000000000..6a262b528eb
--- /dev/null
+++ b/arch/avr32/lib/csum_partial.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ /*
+ * unsigned int csum_partial(const unsigned char *buff,
+ * int len, unsigned int sum)
+ */
+ .text
+ .global csum_partial
+ .type csum_partial,"function"
+ .align 1
+csum_partial:
+ /* checksum complete words, aligned or not */
+3: sub r11, 4
+ brlt 5f
+4: ld.w r9, r12++
+ add r10, r9
+ acr r10
+ sub r11, 4
+ brge 4b
+
+ /* return if we had a whole number of words */
+5: sub r11, -4
+ reteq r10
+
+ /* checksum any remaining bytes at the end */
+ mov r9, 0
+ mov r8, 0
+ cp r11, 2
+ brlt 6f
+ ld.uh r9, r12++
+ sub r11, 2
+ breq 7f
+ lsl r9, 16
+6: ld.ub r8, r12++
+ lsl r8, 8
+7: or r9, r8
+ add r10, r9
+ acr r10
+
+ retal r10
+ .size csum_partial, . - csum_partial
diff --git a/arch/avr32/lib/csum_partial_copy_generic.S b/arch/avr32/lib/csum_partial_copy_generic.S
new file mode 100644
index 00000000000..a3a0f9b8929
--- /dev/null
+++ b/arch/avr32/lib/csum_partial_copy_generic.S
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/errno.h>
+#include <asm/asm.h>
+
+ /*
+ * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len
+ * int sum, int *src_err_ptr,
+ * int *dst_err_ptr)
+ *
+ * Copy src to dst while checksumming, otherwise like csum_partial.
+ */
+
+ .macro ld_src size, reg, ptr
+9999: ld.\size \reg, \ptr
+ .section __ex_table, "a"
+ .long 9999b, fixup_ld_src
+ .previous
+ .endm
+
+ .macro st_dst size, ptr, reg
+9999: st.\size \ptr, \reg
+ .section __ex_table, "a"
+ .long 9999b, fixup_st_dst
+ .previous
+ .endm
+
+ .text
+ .global csum_partial_copy_generic
+ .type csum_partial_copy_generic,"function"
+ .align 1
+csum_partial_copy_generic:
+ pushm r4-r7,lr
+
+ /* The inner loop */
+1: sub r10, 4
+ brlt 5f
+2: ld_src w, r5, r12++
+ st_dst w, r11++, r5
+ add r9, r5
+ acr r9
+ sub r10, 4
+ brge 2b
+
+ /* return if we had a whole number of words */
+5: sub r10, -4
+ brne 7f
+
+6: mov r12, r9
+ popm r4-r7,pc
+
+ /* handle additional bytes at the tail */
+7: mov r5, 0
+ mov r4, 32
+8: ld_src ub, r6, r12++
+ st_dst b, r11++, r6
+ lsl r5, 8
+ sub r4, 8
+ bfins r5, r6, 0, 8
+ sub r10, 1
+ brne 8b
+
+ lsl r5, r5, r4
+ add r9, r5
+ acr r9
+ rjmp 6b
+
+ /* Exception handler */
+ .section .fixup,"ax"
+ .align 1
+fixup_ld_src:
+ mov r9, -EFAULT
+ cp.w r8, 0
+ breq 1f
+ st.w r8[0], r9
+
+1: /*
+ * TODO: zero the complete destination - computing the rest
+ * is too much work
+ */
+
+ mov r9, 0
+ rjmp 6b
+
+fixup_st_dst:
+ mov r9, -EFAULT
+ lddsp r8, sp[20]
+ cp.w r8, 0
+ breq 1f
+ st.w r8[0], r9
+1: mov r9, 0
+ rjmp 6b
+
+ .previous
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
new file mode 100644
index 00000000000..462c8307b68
--- /dev/null
+++ b/arch/avr32/lib/delay.c
@@ -0,0 +1,55 @@
+/*
+ * Precise Delay Loops for avr32
+ *
+ * Copyright (C) 1993 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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/delay.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/delay.h>
+#include <asm/processor.h>
+#include <asm/sysreg.h>
+
+int read_current_timer(unsigned long *timer_value)
+{
+ *timer_value = sysreg_read(COUNT);
+ return 0;
+}
+
+void __delay(unsigned long loops)
+{
+ unsigned bclock, now;
+
+ bclock = sysreg_read(COUNT);
+ do {
+ now = sysreg_read(COUNT);
+ } while ((now - bclock) < loops);
+}
+
+inline void __const_udelay(unsigned long xloops)
+{
+ unsigned long long loops;
+
+ asm("mulu.d %0, %1, %2"
+ : "=r"(loops)
+ : "r"(current_cpu_data.loops_per_jiffy * HZ), "r"(xloops));
+ __delay(loops >> 32);
+}
+
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+ __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S
new file mode 100644
index 00000000000..2b4856f4bf7
--- /dev/null
+++ b/arch/avr32/lib/findbit.S
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/linkage.h>
+
+ .text
+ /*
+ * unsigned long find_first_zero_bit(const unsigned long *addr,
+ * unsigned long size)
+ */
+ENTRY(find_first_zero_bit)
+ cp.w r11, 0
+ reteq r11
+ mov r9, r11
+1: ld.w r8, r12[0]
+ com r8
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ /*
+ * unsigned long find_next_zero_bit(const unsigned long *addr,
+ * unsigned long size,
+ * unsigned long offset)
+ */
+ENTRY(find_next_zero_bit)
+ lsr r8, r10, 5
+ sub r9, r11, r10
+ retle r11
+
+ lsl r8, 2
+ add r12, r8
+ andl r10, 31, COH
+ breq 1f
+
+ /* offset is not word-aligned. Handle the first (32 - r10) bits */
+ ld.w r8, r12[0]
+ com r8
+ sub r12, -4
+ lsr r8, r8, r10
+ brne .L_found
+
+ /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
+ add r9, r10
+ sub r9, 32
+ retle r11
+
+ /* Main loop. offset must be word-aligned */
+1: ld.w r8, r12[0]
+ com r8
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ /* Common return path for when a bit is actually found. */
+.L_found:
+ brev r8
+ clz r10, r8
+ rsub r9, r11
+ add r10, r9
+
+ /* XXX: If we don't have to return exactly "size" when the bit
+ is not found, we may drop this "min" thing */
+ min r12, r11, r10
+ retal r12
+
+ /*
+ * unsigned long find_first_bit(const unsigned long *addr,
+ * unsigned long size)
+ */
+ENTRY(find_first_bit)
+ cp.w r11, 0
+ reteq r11
+ mov r9, r11
+1: ld.w r8, r12[0]
+ cp.w r8, 0
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ /*
+ * unsigned long find_next_bit(const unsigned long *addr,
+ * unsigned long size,
+ * unsigned long offset)
+ */
+ENTRY(find_next_bit)
+ lsr r8, r10, 5
+ sub r9, r11, r10
+ retle r11
+
+ lsl r8, 2
+ add r12, r8
+ andl r10, 31, COH
+ breq 1f
+
+ /* offset is not word-aligned. Handle the first (32 - r10) bits */
+ ld.w r8, r12[0]
+ sub r12, -4
+ lsr r8, r8, r10
+ brne .L_found
+
+ /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
+ add r9, r10
+ sub r9, 32
+ retle r11
+
+ /* Main loop. offset must be word-aligned */
+1: ld.w r8, r12[0]
+ cp.w r8, 0
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ENTRY(generic_find_next_zero_le_bit)
+ lsr r8, r10, 5
+ sub r9, r11, r10
+ retle r11
+
+ lsl r8, 2
+ add r12, r8
+ andl r10, 31, COH
+ breq 1f
+
+ /* offset is not word-aligned. Handle the first (32 - r10) bits */
+ ldswp.w r8, r12[0]
+ sub r12, -4
+ lsr r8, r8, r10
+ brne .L_found
+
+ /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
+ add r9, r10
+ sub r9, 32
+ retle r11
+
+ /* Main loop. offset must be word-aligned */
+1: ldswp.w r8, r12[0]
+ cp.w r8, 0
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
diff --git a/arch/avr32/lib/io-readsl.S b/arch/avr32/lib/io-readsl.S
new file mode 100644
index 00000000000..b103511ed6c
--- /dev/null
+++ b/arch/avr32/lib/io-readsl.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ .global __raw_readsl
+ .type __raw_readsl,@function
+__raw_readsl:
+ cp.w r10, 0
+ reteq r12
+
+ /*
+ * If r11 isn't properly aligned, we might get an exception on
+ * some implementations. But there's not much we can do about it.
+ */
+1: ld.w r8, r12[0]
+ sub r10, 1
+ st.w r11++, r8
+ brne 1b
+
+ retal r12
diff --git a/arch/avr32/lib/io-readsw.S b/arch/avr32/lib/io-readsw.S
new file mode 100644
index 00000000000..456be990902
--- /dev/null
+++ b/arch/avr32/lib/io-readsw.S
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+.Lnot_word_aligned:
+ /*
+ * Bad alignment will cause a hardware exception, which is as
+ * good as anything. No need for us to check for proper alignment.
+ */
+ ld.uh r8, r12[0]
+ sub r10, 1
+ st.h r11++, r8
+
+ /* fall through */
+
+ .global __raw_readsw
+ .type __raw_readsw,@function
+__raw_readsw:
+ cp.w r10, 0
+ reteq r12
+ mov r9, 3
+ tst r11, r9
+ brne .Lnot_word_aligned
+
+ sub r10, 2
+ brlt 2f
+
+1: ldins.h r8:t, r12[0]
+ ldins.h r8:b, r12[0]
+ st.w r11++, r8
+ sub r10, 2
+ brge 1b
+
+2: sub r10, -2
+ reteq r12
+
+ ld.uh r8, r12[0]
+ st.h r11++, r8
+ retal r12
diff --git a/arch/avr32/lib/io-writesl.S b/arch/avr32/lib/io-writesl.S
new file mode 100644
index 00000000000..22138b3a16e
--- /dev/null
+++ b/arch/avr32/lib/io-writesl.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ .global __raw_writesl
+ .type __raw_writesl,@function
+__raw_writesl:
+ cp.w r10, 0
+ reteq r12
+
+1: ld.w r8, r11++
+ sub r10, 1
+ st.w r12[0], r8
+ brne 1b
+
+ retal r12
diff --git a/arch/avr32/lib/io-writesw.S b/arch/avr32/lib/io-writesw.S
new file mode 100644
index 00000000000..8c4a53f1c52
--- /dev/null
+++ b/arch/avr32/lib/io-writesw.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+.Lnot_word_aligned:
+ ld.uh r8, r11++
+ sub r10, 1
+ st.h r12[0], r8
+
+ .global __raw_writesw
+ .type __raw_writesw,@function
+__raw_writesw:
+ cp.w r10, 0
+ mov r9, 3
+ reteq r12
+ tst r11, r9
+ brne .Lnot_word_aligned
+
+ sub r10, 2
+ brlt 2f
+
+1: ld.w r8, r11++
+ bfextu r9, r8, 16, 16
+ st.h r12[0], r9
+ st.h r12[0], r8
+ sub r10, 2
+ brge 1b
+
+2: sub r10, -2
+ reteq r12
+
+ ld.uh r8, r11++
+ st.h r12[0], r8
+ retal r12
diff --git a/arch/avr32/lib/libgcc.h b/arch/avr32/lib/libgcc.h
new file mode 100644
index 00000000000..5a091b5e361
--- /dev/null
+++ b/arch/avr32/lib/libgcc.h
@@ -0,0 +1,33 @@
+/* Definitions for various functions 'borrowed' from gcc-3.4.3 */
+
+#define BITS_PER_UNIT 8
+
+typedef int QItype __attribute__ ((mode (QI)));
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int HItype __attribute__ ((mode (HI)));
+typedef unsigned int UHItype __attribute__ ((mode (HI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define Wtype SItype
+#define UWtype USItype
+#define HWtype SItype
+#define UHWtype USItype
+#define DWtype DItype
+#define UDWtype UDItype
+#define __NW(a,b) __ ## a ## si ## b
+#define __NDW(a,b) __ ## a ## di ## b
+
+struct DWstruct {Wtype high, low;};
+
+typedef union
+{
+ struct DWstruct s;
+ DWtype ll;
+} DWunion;
diff --git a/arch/avr32/lib/longlong.h b/arch/avr32/lib/longlong.h
new file mode 100644
index 00000000000..cd5e369ac43
--- /dev/null
+++ b/arch/avr32/lib/longlong.h
@@ -0,0 +1,98 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+ Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ Free Software Foundation, Inc.
+
+ This definition file is free software; you can redistribute it
+ and/or modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2, or (at your option) any later version.
+
+ This definition file is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Borrowed from gcc-3.4.3 */
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#define count_leading_zeros(count, x) ((count) = __builtin_clz(x))
+
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0; \
+ UWtype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+#define udiv_qrnnd __udiv_qrnnd_c
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __x0, __x1, __x2, __x3; \
+ UHWtype __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart (u); \
+ __uh = __ll_highpart (u); \
+ __vl = __ll_lowpart (v); \
+ __vh = __ll_highpart (v); \
+ \
+ __x0 = (UWtype) __ul * __vl; \
+ __x1 = (UWtype) __ul * __vh; \
+ __x2 = (UWtype) __uh * __vl; \
+ __x3 = (UWtype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
+ } while (0)
diff --git a/arch/avr32/lib/memcpy.S b/arch/avr32/lib/memcpy.S
new file mode 100644
index 00000000000..0abb26142b6
--- /dev/null
+++ b/arch/avr32/lib/memcpy.S
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+
+ /*
+ * void *memcpy(void *to, const void *from, unsigned long n)
+ *
+ * This implementation does word-aligned loads in the main loop,
+ * possibly sacrificing alignment of stores.
+ *
+ * Hopefully, in most cases, both "to" and "from" will be
+ * word-aligned to begin with.
+ */
+ .text
+ .global memcpy
+ .type memcpy, @function
+memcpy:
+ mov r9, r11
+ andl r9, 3, COH
+ brne 1f
+
+ /* At this point, "from" is word-aligned */
+2: sub r10, 4
+ mov r9, r12
+ brlt 4f
+
+3: ld.w r8, r11++
+ sub r10, 4
+ st.w r12++, r8
+ brge 3b
+
+4: neg r10
+ reteq r9
+
+ /* Handle unaligned count */
+ lsl r10, 2
+ add pc, pc, r10
+ ld.ub r8, r11++
+ st.b r12++, r8
+ ld.ub r8, r11++
+ st.b r12++, r8
+ ld.ub r8, r11++
+ st.b r12++, r8
+ retal r9
+
+ /* Handle unaligned "from" pointer */
+1: sub r10, 4
+ brlt 4b
+ add r10, r9
+ lsl r9, 2
+ add pc, pc, r9
+ ld.ub r8, r11++
+ st.b r12++, r8
+ ld.ub r8, r11++
+ st.b r12++, r8
+ ld.ub r8, r11++
+ st.b r12++, r8
+ rjmp 2b
diff --git a/arch/avr32/lib/memset.S b/arch/avr32/lib/memset.S
new file mode 100644
index 00000000000..40da32c0480
--- /dev/null
+++ b/arch/avr32/lib/memset.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/arm/lib/memset.S
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * 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.
+ *
+ * ASM optimised string functions
+ */
+#include <asm/asm.h>
+
+ /*
+ * r12: void *b
+ * r11: int c
+ * r10: size_t len
+ *
+ * Returns b in r12
+ */
+ .text
+ .global memset
+ .type memset, @function
+ .align 5
+memset:
+ mov r9, r12
+ mov r8, r12
+ or r11, r11, r11 << 8
+ andl r9, 3, COH
+ brne 1f
+
+2: or r11, r11, r11 << 16
+ sub r10, 4
+ brlt 5f
+
+ /* Let's do some real work */
+4: st.w r8++, r11
+ sub r10, 4
+ brge 4b
+
+ /*
+ * When we get here, we've got less than 4 bytes to set. r10
+ * might be negative.
+ */
+5: sub r10, -4
+ reteq r12
+
+ /* Fastpath ends here, exactly 32 bytes from memset */
+
+ /* Handle unaligned count or pointer */
+ bld r10, 1
+ brcc 6f
+ st.b r8++, r11
+ st.b r8++, r11
+ bld r10, 0
+ retcc r12
+6: st.b r8++, r11
+ retal r12
+
+ /* Handle unaligned pointer */
+1: sub r10, 4
+ brlt 5b
+ add r10, r9
+ lsl r9, 1
+ add pc, r9
+ st.b r8++, r11
+ st.b r8++, r11
+ st.b r8++, r11
+ rjmp 2b
+
+ .size memset, . - memset
diff --git a/arch/avr32/lib/strncpy_from_user.S b/arch/avr32/lib/strncpy_from_user.S
new file mode 100644
index 00000000000..72bd50599ec
--- /dev/null
+++ b/arch/avr32/lib/strncpy_from_user.S
@@ -0,0 +1,60 @@
+/*
+ * Copy to/from userspace with optional address space checking.
+ *
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * 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/errno.h>
+
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/asm.h>
+
+ /*
+ * long strncpy_from_user(char *dst, const char *src, long count)
+ *
+ * On success, returns the length of the string, not including
+ * the terminating NUL.
+ *
+ * If the string is longer than count, returns count
+ *
+ * If userspace access fails, returns -EFAULT
+ */
+ .text
+ .align 1
+ .global strncpy_from_user
+ .type strncpy_from_user, "function"
+strncpy_from_user:
+ mov r9, -EFAULT
+ branch_if_kernel r8, __strncpy_from_user
+ ret_if_privileged r8, r11, r10, r9
+
+ .global __strncpy_from_user
+ .type __strncpy_from_user, "function"
+__strncpy_from_user:
+ cp.w r10, 0
+ reteq 0
+
+ mov r9, r10
+
+1: ld.ub r8, r11++
+ st.b r12++, r8
+ cp.w r8, 0
+ breq 2f
+ sub r9, 1
+ brne 1b
+
+2: sub r10, r9
+ retal r10
+
+ .section .fixup, "ax"
+ .align 1
+3: mov r12, -EFAULT
+ retal r12
+
+ .section __ex_table, "a"
+ .align 2
+ .long 1b, 3b
diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S
new file mode 100644
index 00000000000..65ce11afa66
--- /dev/null
+++ b/arch/avr32/lib/strnlen_user.S
@@ -0,0 +1,67 @@
+/*
+ * Copy to/from userspace with optional address space checking.
+ *
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * 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 <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/processor.h>
+#include <asm/asm.h>
+
+ .text
+ .align 1
+ .global strnlen_user
+ .type strnlen_user, "function"
+strnlen_user:
+ branch_if_kernel r8, __strnlen_user
+ sub r8, r11, 1
+ add r8, r12
+ retcs 0
+ brmi adjust_length /* do a closer inspection */
+
+ .global __strnlen_user
+ .type __strnlen_user, "function"
+__strnlen_user:
+ mov r10, r12
+
+10: ld.ub r8, r12++
+ cp.w r8, 0
+ breq 2f
+ sub r11, 1
+ brne 10b
+
+ sub r12, -1
+2: sub r12, r10
+ retal r12
+
+
+ .type adjust_length, "function"
+adjust_length:
+ cp.w r12, 0 /* addr must always be < TASK_SIZE */
+ retmi 0
+
+ pushm lr
+ lddpc lr, _task_size
+ sub r11, lr, r12
+ mov r9, r11
+ rcall __strnlen_user
+ cp.w r12, r9
+ brgt 1f
+ popm pc
+1: popm pc, r12=0
+
+ .align 2
+_task_size:
+ .long TASK_SIZE
+
+ .section .fixup, "ax"
+ .align 1
+19: retal 0
+
+ .section __ex_table, "a"
+ .align 2
+ .long 10b, 19b
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
new file mode 100644
index 00000000000..f62eb691551
--- /dev/null
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -0,0 +1,2 @@
+obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o
+obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c
new file mode 100644
index 00000000000..f7cedf5aabe
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/init.h>
+#include <asm/arch/sm.h>
+
+struct at32_sm system_manager;
+
+static int __init at32_sm_init(void)
+{
+ struct resource *regs;
+ struct at32_sm *sm = &system_manager;
+ int ret = -ENXIO;
+
+ regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
+ if (!regs)
+ goto fail;
+
+ spin_lock_init(&sm->lock);
+ sm->pdev = &at32_sm_device;
+
+ ret = -ENOMEM;
+ sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!sm->regs)
+ goto fail;
+
+ return 0;
+
+fail:
+ printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
+ return ret;
+}
+
+void __init setup_platform(void)
+{
+ at32_sm_init();
+ at32_clock_init();
+ at32_portmux_init();
+
+ /* FIXME: This doesn't belong here */
+ at32_setup_serial_console(1);
+}
+
+static int __init pdc_probe(struct platform_device *pdev)
+{
+ struct clk *pclk, *hclk;
+
+ pclk = clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(pclk)) {
+ dev_err(&pdev->dev, "no pclk defined\n");
+ return PTR_ERR(pclk);
+ }
+ hclk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "no hclk defined\n");
+ clk_put(pclk);
+ return PTR_ERR(hclk);
+ }
+
+ clk_enable(pclk);
+ clk_enable(hclk);
+
+ dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n");
+ return 0;
+}
+
+static struct platform_driver pdc_driver = {
+ .probe = pdc_probe,
+ .driver = {
+ .name = "pdc",
+ },
+};
+
+static int __init pdc_init(void)
+{
+ return platform_driver_register(&pdc_driver);
+}
+arch_initcall(pdc_init);
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
new file mode 100644
index 00000000000..37982b60398
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/portmux.h>
+#include <asm/arch/sm.h>
+
+#include "clock.h"
+#include "pio.h"
+#include "sm.h"
+
+#define PBMEM(base) \
+ { \
+ .start = base, \
+ .end = base + 0x3ff, \
+ .flags = IORESOURCE_MEM, \
+ }
+#define IRQ(num) \
+ { \
+ .start = num, \
+ .end = num, \
+ .flags = IORESOURCE_IRQ, \
+ }
+#define NAMED_IRQ(num, _name) \
+ { \
+ .start = num, \
+ .end = num, \
+ .name = _name, \
+ .flags = IORESOURCE_IRQ, \
+ }
+
+#define DEFINE_DEV(_name, _id) \
+static struct platform_device _name##_id##_device = { \
+ .name = #_name, \
+ .id = _id, \
+ .resource = _name##_id##_resource, \
+ .num_resources = ARRAY_SIZE(_name##_id##_resource), \
+}
+#define DEFINE_DEV_DATA(_name, _id) \
+static struct platform_device _name##_id##_device = { \
+ .name = #_name, \
+ .id = _id, \
+ .dev = { \
+ .platform_data = &_name##_id##_data, \
+ }, \
+ .resource = _name##_id##_resource, \
+ .num_resources = ARRAY_SIZE(_name##_id##_resource), \
+}
+
+#define DEV_CLK(_name, devname, bus, _index) \
+static struct clk devname##_##_name = { \
+ .name = #_name, \
+ .dev = &devname##_device.dev, \
+ .parent = &bus##_clk, \
+ .mode = bus##_clk_mode, \
+ .get_rate = bus##_clk_get_rate, \
+ .index = _index, \
+}
+
+enum {
+ PIOA,
+ PIOB,
+ PIOC,
+ PIOD,
+};
+
+enum {
+ FUNC_A,
+ FUNC_B,
+};
+
+unsigned long at32ap7000_osc_rates[3] = {
+ [0] = 32768,
+ /* FIXME: these are ATSTK1002-specific */
+ [1] = 20000000,
+ [2] = 12000000,
+};
+
+static unsigned long osc_get_rate(struct clk *clk)
+{
+ return at32ap7000_osc_rates[clk->index];
+}
+
+static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
+{
+ unsigned long div, mul, rate;
+
+ if (!(control & SM_BIT(PLLEN)))
+ return 0;
+
+ div = SM_BFEXT(PLLDIV, control) + 1;
+ mul = SM_BFEXT(PLLMUL, control) + 1;
+
+ rate = clk->parent->get_rate(clk->parent);
+ rate = (rate + div / 2) / div;
+ rate *= mul;
+
+ return rate;
+}
+
+static unsigned long pll0_get_rate(struct clk *clk)
+{
+ u32 control;
+
+ control = sm_readl(&system_manager, PM_PLL0);
+
+ return pll_get_rate(clk, control);
+}
+
+static unsigned long pll1_get_rate(struct clk *clk)
+{
+ u32 control;
+
+ control = sm_readl(&system_manager, PM_PLL1);
+
+ return pll_get_rate(clk, control);
+}
+
+/*
+ * The AT32AP7000 has five primary clock sources: One 32kHz
+ * oscillator, two crystal oscillators and two PLLs.
+ */
+static struct clk osc32k = {
+ .name = "osc32k",
+ .get_rate = osc_get_rate,
+ .users = 1,
+ .index = 0,
+};
+static struct clk osc0 = {
+ .name = "osc0",
+ .get_rate = osc_get_rate,
+ .users = 1,
+ .index = 1,
+};
+static struct clk osc1 = {
+ .name = "osc1",
+ .get_rate = osc_get_rate,
+ .index = 2,
+};
+static struct clk pll0 = {
+ .name = "pll0",
+ .get_rate = pll0_get_rate,
+ .parent = &osc0,
+};
+static struct clk pll1 = {
+ .name = "pll1",
+ .get_rate = pll1_get_rate,
+ .parent = &osc0,
+};
+
+/*
+ * The main clock can be either osc0 or pll0. The boot loader may
+ * have chosen one for us, so we don't really know which one until we
+ * have a look at the SM.
+ */
+static struct clk *main_clock;
+
+/*
+ * Synchronous clocks are generated from the main clock. The clocks
+ * must satisfy the constraint
+ * fCPU >= fHSB >= fPB
+ * i.e. each clock must not be faster than its parent.
+ */
+static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
+{
+ return main_clock->get_rate(main_clock) >> shift;
+};
+
+static void cpu_clk_mode(struct clk *clk, int enabled)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&sm->lock, flags);
+ mask = sm_readl(sm, PM_CPU_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+ sm_writel(sm, PM_CPU_MASK, mask);
+ spin_unlock_irqrestore(&sm->lock, flags);
+}
+
+static unsigned long cpu_clk_get_rate(struct clk *clk)
+{
+ unsigned long cksel, shift = 0;
+
+ cksel = sm_readl(&system_manager, PM_CKSEL);
+ if (cksel & SM_BIT(CPUDIV))
+ shift = SM_BFEXT(CPUSEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
+}
+
+static void hsb_clk_mode(struct clk *clk, int enabled)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&sm->lock, flags);
+ mask = sm_readl(sm, PM_HSB_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+ sm_writel(sm, PM_HSB_MASK, mask);
+ spin_unlock_irqrestore(&sm->lock, flags);
+}
+
+static unsigned long hsb_clk_get_rate(struct clk *clk)
+{
+ unsigned long cksel, shift = 0;
+
+ cksel = sm_readl(&system_manager, PM_CKSEL);
+ if (cksel & SM_BIT(HSBDIV))
+ shift = SM_BFEXT(HSBSEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
+}
+
+static void pba_clk_mode(struct clk *clk, int enabled)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&sm->lock, flags);
+ mask = sm_readl(sm, PM_PBA_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+ sm_writel(sm, PM_PBA_MASK, mask);
+ spin_unlock_irqrestore(&sm->lock, flags);
+}
+
+static unsigned long pba_clk_get_rate(struct clk *clk)
+{
+ unsigned long cksel, shift = 0;
+
+ cksel = sm_readl(&system_manager, PM_CKSEL);
+ if (cksel & SM_BIT(PBADIV))
+ shift = SM_BFEXT(PBASEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
+}
+
+static void pbb_clk_mode(struct clk *clk, int enabled)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&sm->lock, flags);
+ mask = sm_readl(sm, PM_PBB_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+ sm_writel(sm, PM_PBB_MASK, mask);
+ spin_unlock_irqrestore(&sm->lock, flags);
+}
+
+static unsigned long pbb_clk_get_rate(struct clk *clk)
+{
+ unsigned long cksel, shift = 0;
+
+ cksel = sm_readl(&system_manager, PM_CKSEL);
+ if (cksel & SM_BIT(PBBDIV))
+ shift = SM_BFEXT(PBBSEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
+}
+
+static struct clk cpu_clk = {
+ .name = "cpu",
+ .get_rate = cpu_clk_get_rate,
+ .users = 1,
+};
+static struct clk hsb_clk = {
+ .name = "hsb",
+ .parent = &cpu_clk,
+ .get_rate = hsb_clk_get_rate,
+};
+static struct clk pba_clk = {
+ .name = "pba",
+ .parent = &hsb_clk,
+ .mode = hsb_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 1,
+};
+static struct clk pbb_clk = {
+ .name = "pbb",
+ .parent = &hsb_clk,
+ .mode = hsb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .users = 1,
+ .index = 2,
+};
+
+/* --------------------------------------------------------------------
+ * Generic Clock operations
+ * -------------------------------------------------------------------- */
+
+static void genclk_mode(struct clk *clk, int enabled)
+{
+ u32 control;
+
+ BUG_ON(clk->index > 7);
+
+ control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+ if (enabled)
+ control |= SM_BIT(CEN);
+ else
+ control &= ~SM_BIT(CEN);
+ sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
+}
+
+static unsigned long genclk_get_rate(struct clk *clk)
+{
+ u32 control;
+ unsigned long div = 1;
+
+ BUG_ON(clk->index > 7);
+
+ if (!clk->parent)
+ return 0;
+
+ control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+ if (control & SM_BIT(DIVEN))
+ div = 2 * (SM_BFEXT(DIV, control) + 1);
+
+ return clk->parent->get_rate(clk->parent) / div;
+}
+
+static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
+{
+ u32 control;
+ unsigned long parent_rate, actual_rate, div;
+
+ BUG_ON(clk->index > 7);
+
+ if (!clk->parent)
+ return 0;
+
+ parent_rate = clk->parent->get_rate(clk->parent);
+ control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+
+ if (rate > 3 * parent_rate / 4) {
+ actual_rate = parent_rate;
+ control &= ~SM_BIT(DIVEN);
+ } else {
+ div = (parent_rate + rate) / (2 * rate) - 1;
+ control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
+ actual_rate = parent_rate / (2 * (div + 1));
+ }
+
+ printk("clk %s: new rate %lu (actual rate %lu)\n",
+ clk->name, rate, actual_rate);
+
+ if (apply)
+ sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
+ control);
+
+ return actual_rate;
+}
+
+int genclk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 control;
+
+ BUG_ON(clk->index > 7);
+
+ printk("clk %s: new parent %s (was %s)\n",
+ clk->name, parent->name,
+ clk->parent ? clk->parent->name : "(null)");
+
+ control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+
+ if (parent == &osc1 || parent == &pll1)
+ control |= SM_BIT(OSCSEL);
+ else if (parent == &osc0 || parent == &pll0)
+ control &= ~SM_BIT(OSCSEL);
+ else
+ return -EINVAL;
+
+ if (parent == &pll0 || parent == &pll1)
+ control |= SM_BIT(PLLSEL);
+ else
+ control &= ~SM_BIT(PLLSEL);
+
+ sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
+ clk->parent = parent;
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ * System peripherals
+ * -------------------------------------------------------------------- */
+static struct resource sm_resource[] = {
+ PBMEM(0xfff00000),
+ NAMED_IRQ(19, "eim"),
+ NAMED_IRQ(20, "pm"),
+ NAMED_IRQ(21, "rtc"),
+};
+struct platform_device at32_sm_device = {
+ .name = "sm",
+ .id = 0,
+ .resource = sm_resource,
+ .num_resources = ARRAY_SIZE(sm_resource),
+};
+DEV_CLK(pclk, at32_sm, pbb, 0);
+
+static struct resource intc0_resource[] = {
+ PBMEM(0xfff00400),
+};
+struct platform_device at32_intc0_device = {
+ .name = "intc",
+ .id = 0,
+ .resource = intc0_resource,
+ .num_resources = ARRAY_SIZE(intc0_resource),
+};
+DEV_CLK(pclk, at32_intc0, pbb, 1);
+
+static struct clk ebi_clk = {
+ .name = "ebi",
+ .parent = &hsb_clk,
+ .mode = hsb_clk_mode,
+ .get_rate = hsb_clk_get_rate,
+ .users = 1,
+};
+static struct clk hramc_clk = {
+ .name = "hramc",
+ .parent = &hsb_clk,
+ .mode = hsb_clk_mode,
+ .get_rate = hsb_clk_get_rate,
+ .users = 1,
+};
+
+static struct resource smc0_resource[] = {
+ PBMEM(0xfff03400),
+};
+DEFINE_DEV(smc, 0);
+DEV_CLK(pclk, smc0, pbb, 13);
+DEV_CLK(mck, smc0, hsb, 0);
+
+static struct platform_device pdc_device = {
+ .name = "pdc",
+ .id = 0,
+};
+DEV_CLK(hclk, pdc, hsb, 4);
+DEV_CLK(pclk, pdc, pba, 16);
+
+static struct clk pico_clk = {
+ .name = "pico",
+ .parent = &cpu_clk,
+ .mode = cpu_clk_mode,
+ .get_rate = cpu_clk_get_rate,
+ .users = 1,
+};
+
+/* --------------------------------------------------------------------
+ * PIO
+ * -------------------------------------------------------------------- */
+
+static struct resource pio0_resource[] = {
+ PBMEM(0xffe02800),
+ IRQ(13),
+};
+DEFINE_DEV(pio, 0);
+DEV_CLK(mck, pio0, pba, 10);
+
+static struct resource pio1_resource[] = {
+ PBMEM(0xffe02c00),
+ IRQ(14),
+};
+DEFINE_DEV(pio, 1);
+DEV_CLK(mck, pio1, pba, 11);
+
+static struct resource pio2_resource[] = {
+ PBMEM(0xffe03000),
+ IRQ(15),
+};
+DEFINE_DEV(pio, 2);
+DEV_CLK(mck, pio2, pba, 12);
+
+static struct resource pio3_resource[] = {
+ PBMEM(0xffe03400),
+ IRQ(16),
+};
+DEFINE_DEV(pio, 3);
+DEV_CLK(mck, pio3, pba, 13);
+
+void __init at32_add_system_devices(void)
+{
+ system_manager.eim_first_irq = NR_INTERNAL_IRQS;
+
+ platform_device_register(&at32_sm_device);
+ platform_device_register(&at32_intc0_device);
+ platform_device_register(&smc0_device);
+ platform_device_register(&pdc_device);
+
+ platform_device_register(&pio0_device);
+ platform_device_register(&pio1_device);
+ platform_device_register(&pio2_device);
+ platform_device_register(&pio3_device);
+}
+
+/* --------------------------------------------------------------------
+ * USART
+ * -------------------------------------------------------------------- */
+
+static struct resource usart0_resource[] = {
+ PBMEM(0xffe00c00),
+ IRQ(7),
+};
+DEFINE_DEV(usart, 0);
+DEV_CLK(usart, usart0, pba, 4);
+
+static struct resource usart1_resource[] = {
+ PBMEM(0xffe01000),
+ IRQ(7),
+};
+DEFINE_DEV(usart, 1);
+DEV_CLK(usart, usart1, pba, 4);
+
+static struct resource usart2_resource[] = {
+ PBMEM(0xffe01400),
+ IRQ(8),
+};
+DEFINE_DEV(usart, 2);
+DEV_CLK(usart, usart2, pba, 5);
+
+static struct resource usart3_resource[] = {
+ PBMEM(0xffe01800),
+ IRQ(9),
+};
+DEFINE_DEV(usart, 3);
+DEV_CLK(usart, usart3, pba, 6);
+
+static inline void configure_usart0_pins(void)
+{
+ portmux_set_func(PIOA, 8, FUNC_B); /* RXD */
+ portmux_set_func(PIOA, 9, FUNC_B); /* TXD */
+}
+
+static inline void configure_usart1_pins(void)
+{
+ portmux_set_func(PIOA, 17, FUNC_A); /* RXD */
+ portmux_set_func(PIOA, 18, FUNC_A); /* TXD */
+}
+
+static inline void configure_usart2_pins(void)
+{
+ portmux_set_func(PIOB, 26, FUNC_B); /* RXD */
+ portmux_set_func(PIOB, 27, FUNC_B); /* TXD */
+}
+
+static inline void configure_usart3_pins(void)
+{
+ portmux_set_func(PIOB, 18, FUNC_B); /* RXD */
+ portmux_set_func(PIOB, 17, FUNC_B); /* TXD */
+}
+
+static struct platform_device *setup_usart(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ switch (id) {
+ case 0:
+ pdev = &usart0_device;
+ configure_usart0_pins();
+ break;
+ case 1:
+ pdev = &usart1_device;
+ configure_usart1_pins();
+ break;
+ case 2:
+ pdev = &usart2_device;
+ configure_usart2_pins();
+ break;
+ case 3:
+ pdev = &usart3_device;
+ configure_usart3_pins();
+ break;
+ default:
+ pdev = NULL;
+ break;
+ }
+
+ return pdev;
+}
+
+struct platform_device *__init at32_add_device_usart(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ pdev = setup_usart(id);
+ if (pdev)
+ platform_device_register(pdev);
+
+ return pdev;
+}
+
+struct platform_device *at91_default_console_device;
+
+void __init at32_setup_serial_console(unsigned int usart_id)
+{
+ at91_default_console_device = setup_usart(usart_id);
+}
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+static struct eth_platform_data macb0_data;
+static struct resource macb0_resource[] = {
+ PBMEM(0xfff01800),
+ IRQ(25),
+};
+DEFINE_DEV_DATA(macb, 0);
+DEV_CLK(hclk, macb0, hsb, 8);
+DEV_CLK(pclk, macb0, pbb, 6);
+
+struct platform_device *__init
+at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ switch (id) {
+ case 0:
+ pdev = &macb0_device;
+
+ portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */
+ portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */
+ portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */
+ portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */
+ portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */
+ portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */
+ portmux_set_func(PIOC, 13, FUNC_A); /* RXER */
+ portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */
+ portmux_set_func(PIOC, 16, FUNC_A); /* MDC */
+ portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */
+
+ if (!data->is_rmii) {
+ portmux_set_func(PIOC, 0, FUNC_A); /* COL */
+ portmux_set_func(PIOC, 1, FUNC_A); /* CRS */
+ portmux_set_func(PIOC, 2, FUNC_A); /* TXER */
+ portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */
+ portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */
+ portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */
+ portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */
+ portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */
+ portmux_set_func(PIOC, 18, FUNC_A); /* SPD */
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+
+ memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data));
+ platform_device_register(pdev);
+
+ return pdev;
+}
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+static struct resource spi0_resource[] = {
+ PBMEM(0xffe00000),
+ IRQ(3),
+};
+DEFINE_DEV(spi, 0);
+DEV_CLK(mck, spi0, pba, 0);
+
+struct platform_device *__init at32_add_device_spi(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ switch (id) {
+ case 0:
+ pdev = &spi0_device;
+ portmux_set_func(PIOA, 0, FUNC_A); /* MISO */
+ portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */
+ portmux_set_func(PIOA, 2, FUNC_A); /* SCK */
+ portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */
+ portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */
+ portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */
+ break;
+
+ default:
+ return NULL;
+ }
+
+ platform_device_register(pdev);
+ return pdev;
+}
+
+/* --------------------------------------------------------------------
+ * LCDC
+ * -------------------------------------------------------------------- */
+static struct lcdc_platform_data lcdc0_data;
+static struct resource lcdc0_resource[] = {
+ {
+ .start = 0xff000000,
+ .end = 0xff000fff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(1),
+};
+DEFINE_DEV_DATA(lcdc, 0);
+DEV_CLK(hclk, lcdc0, hsb, 7);
+static struct clk lcdc0_pixclk = {
+ .name = "pixclk",
+ .dev = &lcdc0_device.dev,
+ .mode = genclk_mode,
+ .get_rate = genclk_get_rate,
+ .set_rate = genclk_set_rate,
+ .set_parent = genclk_set_parent,
+ .index = 7,
+};
+
+struct platform_device *__init
+at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ switch (id) {
+ case 0:
+ pdev = &lcdc0_device;
+ portmux_set_func(PIOC, 19, FUNC_A); /* CC */
+ portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */
+ portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */
+ portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */
+ portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */
+ portmux_set_func(PIOC, 24, FUNC_A); /* MODE */
+ portmux_set_func(PIOC, 25, FUNC_A); /* PWR */
+ portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */
+ portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */
+ portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */
+ portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */
+ portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */
+ portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */
+ portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */
+ portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */
+ portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */
+ portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */
+ portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */
+ portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */
+ portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */
+ portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */
+ portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */
+ portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */
+ portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */
+ portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */
+ portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */
+ portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */
+ portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */
+ portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */
+ portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */
+ portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */
+
+ clk_set_parent(&lcdc0_pixclk, &pll0);
+ clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
+ break;
+
+ default:
+ return NULL;
+ }
+
+ memcpy(pdev->dev.platform_data, data,
+ sizeof(struct lcdc_platform_data));
+
+ platform_device_register(pdev);
+ return pdev;
+}
+
+struct clk *at32_clock_list[] = {
+ &osc32k,
+ &osc0,
+ &osc1,
+ &pll0,
+ &pll1,
+ &cpu_clk,
+ &hsb_clk,
+ &pba_clk,
+ &pbb_clk,
+ &at32_sm_pclk,
+ &at32_intc0_pclk,
+ &ebi_clk,
+ &hramc_clk,
+ &smc0_pclk,
+ &smc0_mck,
+ &pdc_hclk,
+ &pdc_pclk,
+ &pico_clk,
+ &pio0_mck,
+ &pio1_mck,
+ &pio2_mck,
+ &pio3_mck,
+ &usart0_usart,
+ &usart1_usart,
+ &usart2_usart,
+ &usart3_usart,
+ &macb0_hclk,
+ &macb0_pclk,
+ &spi0_mck,
+ &lcdc0_hclk,
+ &lcdc0_pixclk,
+};
+unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
+
+void __init at32_portmux_init(void)
+{
+ at32_init_pio(&pio0_device);
+ at32_init_pio(&pio1_device);
+ at32_init_pio(&pio2_device);
+ at32_init_pio(&pio3_device);
+}
+
+void __init at32_clock_init(void)
+{
+ struct at32_sm *sm = &system_manager;
+ u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
+ int i;
+
+ if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
+ main_clock = &pll0;
+ else
+ main_clock = &osc0;
+
+ if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
+ pll0.parent = &osc1;
+ if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
+ pll1.parent = &osc1;
+
+ /*
+ * Turn on all clocks that have at least one user already, and
+ * turn off everything else. We only do this for module
+ * clocks, and even though it isn't particularly pretty to
+ * check the address of the mode function, it should do the
+ * trick...
+ */
+ for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
+ struct clk *clk = at32_clock_list[i];
+
+ if (clk->mode == &cpu_clk_mode)
+ cpu_mask |= 1 << clk->index;
+ else if (clk->mode == &hsb_clk_mode)
+ hsb_mask |= 1 << clk->index;
+ else if (clk->mode == &pba_clk_mode)
+ pba_mask |= 1 << clk->index;
+ else if (clk->mode == &pbb_clk_mode)
+ pbb_mask |= 1 << clk->index;
+ }
+
+ sm_writel(sm, PM_CPU_MASK, cpu_mask);
+ sm_writel(sm, PM_HSB_MASK, hsb_mask);
+ sm_writel(sm, PM_PBA_MASK, pba_mask);
+ sm_writel(sm, PM_PBB_MASK, pbb_mask);
+}
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
new file mode 100644
index 00000000000..3d0d1097389
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -0,0 +1,148 @@
+/*
+ * Clock management for AT32AP CPUs
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * Based on arch/arm/mach-at91rm9200/clock.c
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/string.h>
+
+#include "clock.h"
+
+static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ int i;
+
+ for (i = 0; i < at32_nr_clocks; i++) {
+ struct clk *clk = at32_clock_list[i];
+
+ if (clk->dev == dev && strcmp(id, clk->name) == 0)
+ return clk;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+ /* clocks are static for now, we can't free them */
+}
+EXPORT_SYMBOL(clk_put);
+
+static void __clk_enable(struct clk *clk)
+{
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->users++ == 0 && clk->mode)
+ clk->mode(clk, 1);
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+ BUG_ON(clk->users == 0);
+
+ if (--clk->users == 0 && clk->mode)
+ clk->mode(clk, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long rate;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ rate = clk->get_rate(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags, actual_rate;
+
+ if (!clk->set_rate)
+ return -ENOSYS;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ actual_rate = clk->set_rate(clk, rate, 0);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return actual_rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ long ret;
+
+ if (!clk->set_rate)
+ return -ENOSYS;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ ret = clk->set_rate(clk, rate, 1);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+ int ret;
+
+ if (!clk->set_parent)
+ return -ENOSYS;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ ret = clk->set_parent(clk, parent);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
new file mode 100644
index 00000000000..f953f044ba4
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -0,0 +1,30 @@
+/*
+ * Clock management for AT32AP CPUs
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * Based on arch/arm/mach-at91rm9200/clock.c
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ *
+ * 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/clk.h>
+
+struct clk {
+ const char *name; /* Clock name/function */
+ struct device *dev; /* Device the clock is used by */
+ struct clk *parent; /* Parent clock, if any */
+ void (*mode)(struct clk *clk, int enabled);
+ unsigned long (*get_rate)(struct clk *clk);
+ long (*set_rate)(struct clk *clk, unsigned long rate,
+ int apply);
+ int (*set_parent)(struct clk *clk, struct clk *parent);
+ u16 users; /* Enabled if non-zero */
+ u16 index; /* Sibling index */
+};
+
+extern struct clk *at32_clock_list[];
+extern unsigned int at32_nr_clocks;
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
new file mode 100644
index 00000000000..7da9c5f7a0e
--- /dev/null
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -0,0 +1,171 @@
+/*
+ * External interrupt handling for AT32AP CPUs
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/sm.h>
+
+#include "sm.h"
+
+static void eim_ack_irq(unsigned int irq)
+{
+ struct at32_sm *sm = get_irq_chip_data(irq);
+ sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
+}
+
+static void eim_mask_irq(unsigned int irq)
+{
+ struct at32_sm *sm = get_irq_chip_data(irq);
+ sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
+}
+
+static void eim_mask_ack_irq(unsigned int irq)
+{
+ struct at32_sm *sm = get_irq_chip_data(irq);
+ sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
+ sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
+}
+
+static void eim_unmask_irq(unsigned int irq)
+{
+ struct at32_sm *sm = get_irq_chip_data(irq);
+ sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
+}
+
+static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
+{
+ struct at32_sm *sm = get_irq_chip_data(irq);
+ unsigned int i = irq - sm->eim_first_irq;
+ u32 mode, edge, level;
+ unsigned long flags;
+ int ret = 0;
+
+ flow_type &= IRQ_TYPE_SENSE_MASK;
+
+ spin_lock_irqsave(&sm->lock, flags);
+
+ mode = sm_readl(sm, EIM_MODE);
+ edge = sm_readl(sm, EIM_EDGE);
+ level = sm_readl(sm, EIM_LEVEL);
+
+ switch (flow_type) {
+ case IRQ_TYPE_LEVEL_LOW:
+ mode |= 1 << i;
+ level &= ~(1 << i);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ mode |= 1 << i;
+ level |= 1 << i;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ mode &= ~(1 << i);
+ edge |= 1 << i;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ mode &= ~(1 << i);
+ edge &= ~(1 << i);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ sm_writel(sm, EIM_MODE, mode);
+ sm_writel(sm, EIM_EDGE, edge);
+ sm_writel(sm, EIM_LEVEL, level);
+
+ spin_unlock_irqrestore(&sm->lock, flags);
+
+ return ret;
+}
+
+struct irq_chip eim_chip = {
+ .name = "eim",
+ .ack = eim_ack_irq,
+ .mask = eim_mask_irq,
+ .mask_ack = eim_mask_ack_irq,
+ .unmask = eim_unmask_irq,
+ .set_type = eim_set_irq_type,
+};
+
+static void demux_eim_irq(unsigned int irq, struct irq_desc *desc,
+ struct pt_regs *regs)
+{
+ struct at32_sm *sm = desc->handler_data;
+ struct irq_desc *ext_desc;
+ unsigned long status, pending;
+ unsigned int i, ext_irq;
+
+ spin_lock(&sm->lock);
+
+ status = sm_readl(sm, EIM_ISR);
+ pending = status & sm_readl(sm, EIM_IMR);
+
+ while (pending) {
+ i = fls(pending) - 1;
+ pending &= ~(1 << i);
+
+ ext_irq = i + sm->eim_first_irq;
+ ext_desc = irq_desc + ext_irq;
+ ext_desc->handle_irq(ext_irq, ext_desc, regs);
+ }
+
+ spin_unlock(&sm->lock);
+}
+
+static int __init eim_init(void)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned int i;
+ unsigned int nr_irqs;
+ unsigned int int_irq;
+ u32 pattern;
+
+ /*
+ * The EIM is really the same module as SM, so register
+ * mapping, etc. has been taken care of already.
+ */
+
+ /*
+ * Find out how many interrupt lines that are actually
+ * implemented in hardware.
+ */
+ sm_writel(sm, EIM_IDR, ~0UL);
+ sm_writel(sm, EIM_MODE, ~0UL);
+ pattern = sm_readl(sm, EIM_MODE);
+ nr_irqs = fls(pattern);
+
+ sm->eim_chip = &eim_chip;
+
+ for (i = 0; i < nr_irqs; i++) {
+ set_irq_chip(sm->eim_first_irq + i, &eim_chip);
+ set_irq_chip_data(sm->eim_first_irq + i, sm);
+ }
+
+ int_irq = platform_get_irq_byname(sm->pdev, "eim");
+
+ set_irq_chained_handler(int_irq, demux_eim_irq);
+ set_irq_data(int_irq, sm);
+
+ printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
+ sm->regs, int_irq);
+ printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
+ nr_irqs, sm->eim_first_irq);
+
+ return 0;
+}
+arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
new file mode 100644
index 00000000000..7691721928a
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -0,0 +1,164 @@
+/*
+ * Static Memory Controller for AT32 chips
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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.
+ */
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/arch/smc.h>
+
+#include "hsmc.h"
+
+#define NR_CHIP_SELECTS 6
+
+struct hsmc {
+ void __iomem *regs;
+ struct clk *pclk;
+ struct clk *mck;
+};
+
+static struct hsmc *hsmc;
+
+int smc_set_configuration(int cs, const struct smc_config *config)
+{
+ unsigned long mul;
+ unsigned long offset;
+ u32 setup, pulse, cycle, mode;
+
+ if (!hsmc)
+ return -ENODEV;
+ if (cs >= NR_CHIP_SELECTS)
+ return -EINVAL;
+
+ /*
+ * cycles = x / T = x * f
+ * = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536
+ * = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536
+ */
+ mul = (clk_get_rate(hsmc->mck) / 10000) << 16;
+ mul /= 100000;
+
+#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
+
+ setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
+ | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
+ | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
+ | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
+ pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
+ | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
+ | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
+ | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
+ cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
+ | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
+
+ switch (config->bus_width) {
+ case 1:
+ mode = HSMC_BF(DBW, HSMC_DBW_8_BITS);
+ break;
+ case 2:
+ mode = HSMC_BF(DBW, HSMC_DBW_16_BITS);
+ break;
+ case 4:
+ mode = HSMC_BF(DBW, HSMC_DBW_32_BITS);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (config->nrd_controlled)
+ mode |= HSMC_BIT(READ_MODE);
+ if (config->nwe_controlled)
+ mode |= HSMC_BIT(WRITE_MODE);
+ if (config->byte_write)
+ mode |= HSMC_BIT(BAT);
+
+ pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n",
+ cs, setup, pulse, cycle, mode);
+
+ offset = cs * 0x10;
+ hsmc_writel(hsmc, SETUP0 + offset, setup);
+ hsmc_writel(hsmc, PULSE0 + offset, pulse);
+ hsmc_writel(hsmc, CYCLE0 + offset, cycle);
+ hsmc_writel(hsmc, MODE0 + offset, mode);
+ hsmc_readl(hsmc, MODE0); /* I/O barrier */
+
+ return 0;
+}
+EXPORT_SYMBOL(smc_set_configuration);
+
+static int hsmc_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+ struct clk *pclk, *mck;
+ int ret;
+
+ if (hsmc)
+ return -EBUSY;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs)
+ return -ENXIO;
+ pclk = clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(pclk))
+ return PTR_ERR(pclk);
+ mck = clk_get(&pdev->dev, "mck");
+ if (IS_ERR(mck)) {
+ ret = PTR_ERR(mck);
+ goto out_put_pclk;
+ }
+
+ ret = -ENOMEM;
+ hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL);
+ if (!hsmc)
+ goto out_put_clocks;
+
+ clk_enable(pclk);
+ clk_enable(mck);
+
+ hsmc->pclk = pclk;
+ hsmc->mck = mck;
+ hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!hsmc->regs)
+ goto out_disable_clocks;
+
+ dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n",
+ (unsigned long)regs->start);
+
+ platform_set_drvdata(pdev, hsmc);
+
+ return 0;
+
+out_disable_clocks:
+ clk_disable(mck);
+ clk_disable(pclk);
+ kfree(hsmc);
+out_put_clocks:
+ clk_put(mck);
+out_put_pclk:
+ clk_put(pclk);
+ hsmc = NULL;
+ return ret;
+}
+
+static struct platform_driver hsmc_driver = {
+ .probe = hsmc_probe,
+ .driver = {
+ .name = "smc",
+ },
+};
+
+static int __init hsmc_init(void)
+{
+ return platform_driver_register(&hsmc_driver);
+}
+arch_initcall(hsmc_init);
diff --git a/arch/avr32/mach-at32ap/hsmc.h b/arch/avr32/mach-at32ap/hsmc.h
new file mode 100644
index 00000000000..5681276fafd
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hsmc.h
@@ -0,0 +1,127 @@
+/*
+ * Register definitions for Atmel Static Memory Controller (SMC)
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef __ASM_AVR32_HSMC_H__
+#define __ASM_AVR32_HSMC_H__
+
+/* HSMC register offsets */
+#define HSMC_SETUP0 0x0000
+#define HSMC_PULSE0 0x0004
+#define HSMC_CYCLE0 0x0008
+#define HSMC_MODE0 0x000c
+#define HSMC_SETUP1 0x0010
+#define HSMC_PULSE1 0x0014
+#define HSMC_CYCLE1 0x0018
+#define HSMC_MODE1 0x001c
+#define HSMC_SETUP2 0x0020
+#define HSMC_PULSE2 0x0024
+#define HSMC_CYCLE2 0x0028
+#define HSMC_MODE2 0x002c
+#define HSMC_SETUP3 0x0030
+#define HSMC_PULSE3 0x0034
+#define HSMC_CYCLE3 0x0038
+#define HSMC_MODE3 0x003c
+#define HSMC_SETUP4 0x0040
+#define HSMC_PULSE4 0x0044
+#define HSMC_CYCLE4 0x0048
+#define HSMC_MODE4 0x004c
+#define HSMC_SETUP5 0x0050
+#define HSMC_PULSE5 0x0054
+#define HSMC_CYCLE5 0x0058
+#define HSMC_MODE5 0x005c
+
+/* Bitfields in SETUP0 */
+#define HSMC_NWE_SETUP_OFFSET 0
+#define HSMC_NWE_SETUP_SIZE 6
+#define HSMC_NCS_WR_SETUP_OFFSET 8
+#define HSMC_NCS_WR_SETUP_SIZE 6
+#define HSMC_NRD_SETUP_OFFSET 16
+#define HSMC_NRD_SETUP_SIZE 6
+#define HSMC_NCS_RD_SETUP_OFFSET 24
+#define HSMC_NCS_RD_SETUP_SIZE 6
+
+/* Bitfields in PULSE0 */
+#define HSMC_NWE_PULSE_OFFSET 0
+#define HSMC_NWE_PULSE_SIZE 7
+#define HSMC_NCS_WR_PULSE_OFFSET 8
+#define HSMC_NCS_WR_PULSE_SIZE 7
+#define HSMC_NRD_PULSE_OFFSET 16
+#define HSMC_NRD_PULSE_SIZE 7
+#define HSMC_NCS_RD_PULSE_OFFSET 24
+#define HSMC_NCS_RD_PULSE_SIZE 7
+
+/* Bitfields in CYCLE0 */
+#define HSMC_NWE_CYCLE_OFFSET 0
+#define HSMC_NWE_CYCLE_SIZE 9
+#define HSMC_NRD_CYCLE_OFFSET 16
+#define HSMC_NRD_CYCLE_SIZE 9
+
+/* Bitfields in MODE0 */
+#define HSMC_READ_MODE_OFFSET 0
+#define HSMC_READ_MODE_SIZE 1
+#define HSMC_WRITE_MODE_OFFSET 1
+#define HSMC_WRITE_MODE_SIZE 1
+#define HSMC_EXNW_MODE_OFFSET 4
+#define HSMC_EXNW_MODE_SIZE 2
+#define HSMC_BAT_OFFSET 8
+#define HSMC_BAT_SIZE 1
+#define HSMC_DBW_OFFSET 12
+#define HSMC_DBW_SIZE 2
+#define HSMC_TDF_CYCLES_OFFSET 16
+#define HSMC_TDF_CYCLES_SIZE 4
+#define HSMC_TDF_MODE_OFFSET 20
+#define HSMC_TDF_MODE_SIZE 1
+#define HSMC_PMEN_OFFSET 24
+#define HSMC_PMEN_SIZE 1
+#define HSMC_PS_OFFSET 28
+#define HSMC_PS_SIZE 2
+
+/* Constants for READ_MODE */
+#define HSMC_READ_MODE_NCS_CONTROLLED 0
+#define HSMC_READ_MODE_NRD_CONTROLLED 1
+
+/* Constants for WRITE_MODE */
+#define HSMC_WRITE_MODE_NCS_CONTROLLED 0
+#define HSMC_WRITE_MODE_NWE_CONTROLLED 1
+
+/* Constants for EXNW_MODE */
+#define HSMC_EXNW_MODE_DISABLED 0
+#define HSMC_EXNW_MODE_RESERVED 1
+#define HSMC_EXNW_MODE_FROZEN 2
+#define HSMC_EXNW_MODE_READY 3
+
+/* Constants for BAT */
+#define HSMC_BAT_BYTE_SELECT 0
+#define HSMC_BAT_BYTE_WRITE 1
+
+/* Constants for DBW */
+#define HSMC_DBW_8_BITS 0
+#define HSMC_DBW_16_BITS 1
+#define HSMC_DBW_32_BITS 2
+
+/* Bit manipulation macros */
+#define HSMC_BIT(name) \
+ (1 << HSMC_##name##_OFFSET)
+#define HSMC_BF(name,value) \
+ (((value) & ((1 << HSMC_##name##_SIZE) - 1)) \
+ << HSMC_##name##_OFFSET)
+#define HSMC_BFEXT(name,value) \
+ (((value) >> HSMC_##name##_OFFSET) \
+ & ((1 << HSMC_##name##_SIZE) - 1))
+#define HSMC_BFINS(name,value,old) \
+ (((old) & ~(((1 << HSMC_##name##_SIZE) - 1) \
+ << HSMC_##name##_OFFSET)) | HSMC_BF(name,value))
+
+/* Register access macros */
+#define hsmc_readl(port,reg) \
+ readl((port)->regs + HSMC_##reg)
+#define hsmc_writel(port,reg,value) \
+ writel((value), (port)->regs + HSMC_##reg)
+
+#endif /* __ASM_AVR32_HSMC_H__ */
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
new file mode 100644
index 00000000000..74f8c9f2f03
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include "intc.h"
+
+struct intc {
+ void __iomem *regs;
+ struct irq_chip chip;
+};
+
+extern struct platform_device at32_intc0_device;
+
+/*
+ * TODO: We may be able to implement mask/unmask by setting IxM flags
+ * in the status register.
+ */
+static void intc_mask_irq(unsigned int irq)
+{
+
+}
+
+static void intc_unmask_irq(unsigned int irq)
+{
+
+}
+
+static struct intc intc0 = {
+ .chip = {
+ .name = "intc",
+ .mask = intc_mask_irq,
+ .unmask = intc_unmask_irq,
+ },
+};
+
+/*
+ * All interrupts go via intc at some point.
+ */
+asmlinkage void do_IRQ(int level, struct pt_regs *regs)
+{
+ struct irq_desc *desc;
+ unsigned int irq;
+ unsigned long status_reg;
+
+ local_irq_disable();
+
+ irq_enter();
+
+ irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
+ desc = irq_desc + irq;
+ desc->handle_irq(irq, desc, regs);
+
+ /*
+ * Clear all interrupt level masks so that we may handle
+ * interrupts during softirq processing. If this is a nested
+ * interrupt, interrupts must stay globally disabled until we
+ * return.
+ */
+ status_reg = sysreg_read(SR);
+ status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M)
+ | SYSREG_BIT(I2M) | SYSREG_BIT(I3M));
+ sysreg_write(SR, status_reg);
+
+ irq_exit();
+}
+
+void __init init_IRQ(void)
+{
+ extern void _evba(void);
+ extern void irq_level0(void);
+ struct resource *regs;
+ struct clk *pclk;
+ unsigned int i;
+ u32 offset, readback;
+
+ regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0);
+ if (!regs) {
+ printk(KERN_EMERG "intc: no mmio resource defined\n");
+ goto fail;
+ }
+ pclk = clk_get(&at32_intc0_device.dev, "pclk");
+ if (IS_ERR(pclk)) {
+ printk(KERN_EMERG "intc: no clock defined\n");
+ goto fail;
+ }
+
+ clk_enable(pclk);
+
+ intc0.regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!intc0.regs) {
+ printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
+ (unsigned long)regs->start);
+ goto fail;
+ }
+
+ /*
+ * Initialize all interrupts to level 0 (lowest priority). The
+ * priority level may be changed by calling
+ * irq_set_priority().
+ *
+ */
+ offset = (unsigned long)&irq_level0 - (unsigned long)&_evba;
+ for (i = 0; i < NR_INTERNAL_IRQS; i++) {
+ intc_writel(&intc0, INTPR0 + 4 * i, offset);
+ readback = intc_readl(&intc0, INTPR0 + 4 * i);
+ if (readback == offset)
+ set_irq_chip_and_handler(i, &intc0.chip,
+ handle_simple_irq);
+ }
+
+ /* Unmask all interrupt levels */
+ sysreg_write(SR, (sysreg_read(SR)
+ & ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M)));
+
+ return;
+
+fail:
+ panic("Interrupt controller initialization failed!\n");
+}
+
diff --git a/arch/avr32/mach-at32ap/intc.h b/arch/avr32/mach-at32ap/intc.h
new file mode 100644
index 00000000000..d289ca2fff1
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.h
@@ -0,0 +1,327 @@
+/*
+ * Automatically generated by gen-header.xsl
+ */
+#ifndef __ASM_AVR32_PERIHP_INTC_H__
+#define __ASM_AVR32_PERIHP_INTC_H__
+
+#define INTC_NUM_INT_GRPS 33
+
+#define INTC_INTPR0 0x0
+# define INTC_INTPR0_INTLEV_OFFSET 30
+# define INTC_INTPR0_INTLEV_SIZE 2
+# define INTC_INTPR0_OFFSET_OFFSET 0
+# define INTC_INTPR0_OFFSET_SIZE 24
+#define INTC_INTREQ0 0x100
+# define INTC_INTREQ0_IREQUEST0_OFFSET 0
+# define INTC_INTREQ0_IREQUEST0_SIZE 1
+# define INTC_INTREQ0_IREQUEST1_OFFSET 1
+# define INTC_INTREQ0_IREQUEST1_SIZE 1
+#define INTC_INTPR1 0x4
+# define INTC_INTPR1_INTLEV_OFFSET 30
+# define INTC_INTPR1_INTLEV_SIZE 2
+# define INTC_INTPR1_OFFSET_OFFSET 0
+# define INTC_INTPR1_OFFSET_SIZE 24
+#define INTC_INTREQ1 0x104
+# define INTC_INTREQ1_IREQUEST32_OFFSET 0
+# define INTC_INTREQ1_IREQUEST32_SIZE 1
+# define INTC_INTREQ1_IREQUEST33_OFFSET 1
+# define INTC_INTREQ1_IREQUEST33_SIZE 1
+# define INTC_INTREQ1_IREQUEST34_OFFSET 2
+# define INTC_INTREQ1_IREQUEST34_SIZE 1
+# define INTC_INTREQ1_IREQUEST35_OFFSET 3
+# define INTC_INTREQ1_IREQUEST35_SIZE 1
+# define INTC_INTREQ1_IREQUEST36_OFFSET 4
+# define INTC_INTREQ1_IREQUEST36_SIZE 1
+# define INTC_INTREQ1_IREQUEST37_OFFSET 5
+# define INTC_INTREQ1_IREQUEST37_SIZE 1
+#define INTC_INTPR2 0x8
+# define INTC_INTPR2_INTLEV_OFFSET 30
+# define INTC_INTPR2_INTLEV_SIZE 2
+# define INTC_INTPR2_OFFSET_OFFSET 0
+# define INTC_INTPR2_OFFSET_SIZE 24
+#define INTC_INTREQ2 0x108
+# define INTC_INTREQ2_IREQUEST64_OFFSET 0
+# define INTC_INTREQ2_IREQUEST64_SIZE 1
+# define INTC_INTREQ2_IREQUEST65_OFFSET 1
+# define INTC_INTREQ2_IREQUEST65_SIZE 1
+# define INTC_INTREQ2_IREQUEST66_OFFSET 2
+# define INTC_INTREQ2_IREQUEST66_SIZE 1
+# define INTC_INTREQ2_IREQUEST67_OFFSET 3
+# define INTC_INTREQ2_IREQUEST67_SIZE 1
+# define INTC_INTREQ2_IREQUEST68_OFFSET 4
+# define INTC_INTREQ2_IREQUEST68_SIZE 1
+#define INTC_INTPR3 0xc
+# define INTC_INTPR3_INTLEV_OFFSET 30
+# define INTC_INTPR3_INTLEV_SIZE 2
+# define INTC_INTPR3_OFFSET_OFFSET 0
+# define INTC_INTPR3_OFFSET_SIZE 24
+#define INTC_INTREQ3 0x10c
+# define INTC_INTREQ3_IREQUEST96_OFFSET 0
+# define INTC_INTREQ3_IREQUEST96_SIZE 1
+#define INTC_INTPR4 0x10
+# define INTC_INTPR4_INTLEV_OFFSET 30
+# define INTC_INTPR4_INTLEV_SIZE 2
+# define INTC_INTPR4_OFFSET_OFFSET 0
+# define INTC_INTPR4_OFFSET_SIZE 24
+#define INTC_INTREQ4 0x110
+# define INTC_INTREQ4_IREQUEST128_OFFSET 0
+# define INTC_INTREQ4_IREQUEST128_SIZE 1
+#define INTC_INTPR5 0x14
+# define INTC_INTPR5_INTLEV_OFFSET 30
+# define INTC_INTPR5_INTLEV_SIZE 2
+# define INTC_INTPR5_OFFSET_OFFSET 0
+# define INTC_INTPR5_OFFSET_SIZE 24
+#define INTC_INTREQ5 0x114
+# define INTC_INTREQ5_IREQUEST160_OFFSET 0
+# define INTC_INTREQ5_IREQUEST160_SIZE 1
+#define INTC_INTPR6 0x18
+# define INTC_INTPR6_INTLEV_OFFSET 30
+# define INTC_INTPR6_INTLEV_SIZE 2
+# define INTC_INTPR6_OFFSET_OFFSET 0
+# define INTC_INTPR6_OFFSET_SIZE 24
+#define INTC_INTREQ6 0x118
+# define INTC_INTREQ6_IREQUEST192_OFFSET 0
+# define INTC_INTREQ6_IREQUEST192_SIZE 1
+#define INTC_INTPR7 0x1c
+# define INTC_INTPR7_INTLEV_OFFSET 30
+# define INTC_INTPR7_INTLEV_SIZE 2
+# define INTC_INTPR7_OFFSET_OFFSET 0
+# define INTC_INTPR7_OFFSET_SIZE 24
+#define INTC_INTREQ7 0x11c
+# define INTC_INTREQ7_IREQUEST224_OFFSET 0
+# define INTC_INTREQ7_IREQUEST224_SIZE 1
+#define INTC_INTPR8 0x20
+# define INTC_INTPR8_INTLEV_OFFSET 30
+# define INTC_INTPR8_INTLEV_SIZE 2
+# define INTC_INTPR8_OFFSET_OFFSET 0
+# define INTC_INTPR8_OFFSET_SIZE 24
+#define INTC_INTREQ8 0x120
+# define INTC_INTREQ8_IREQUEST256_OFFSET 0
+# define INTC_INTREQ8_IREQUEST256_SIZE 1
+#define INTC_INTPR9 0x24
+# define INTC_INTPR9_INTLEV_OFFSET 30
+# define INTC_INTPR9_INTLEV_SIZE 2
+# define INTC_INTPR9_OFFSET_OFFSET 0
+# define INTC_INTPR9_OFFSET_SIZE 24
+#define INTC_INTREQ9 0x124
+# define INTC_INTREQ9_IREQUEST288_OFFSET 0
+# define INTC_INTREQ9_IREQUEST288_SIZE 1
+#define INTC_INTPR10 0x28
+# define INTC_INTPR10_INTLEV_OFFSET 30
+# define INTC_INTPR10_INTLEV_SIZE 2
+# define INTC_INTPR10_OFFSET_OFFSET 0
+# define INTC_INTPR10_OFFSET_SIZE 24
+#define INTC_INTREQ10 0x128
+# define INTC_INTREQ10_IREQUEST320_OFFSET 0
+# define INTC_INTREQ10_IREQUEST320_SIZE 1
+#define INTC_INTPR11 0x2c
+# define INTC_INTPR11_INTLEV_OFFSET 30
+# define INTC_INTPR11_INTLEV_SIZE 2
+# define INTC_INTPR11_OFFSET_OFFSET 0
+# define INTC_INTPR11_OFFSET_SIZE 24
+#define INTC_INTREQ11 0x12c
+# define INTC_INTREQ11_IREQUEST352_OFFSET 0
+# define INTC_INTREQ11_IREQUEST352_SIZE 1
+#define INTC_INTPR12 0x30
+# define INTC_INTPR12_INTLEV_OFFSET 30
+# define INTC_INTPR12_INTLEV_SIZE 2
+# define INTC_INTPR12_OFFSET_OFFSET 0
+# define INTC_INTPR12_OFFSET_SIZE 24
+#define INTC_INTREQ12 0x130
+# define INTC_INTREQ12_IREQUEST384_OFFSET 0
+# define INTC_INTREQ12_IREQUEST384_SIZE 1
+#define INTC_INTPR13 0x34
+# define INTC_INTPR13_INTLEV_OFFSET 30
+# define INTC_INTPR13_INTLEV_SIZE 2
+# define INTC_INTPR13_OFFSET_OFFSET 0
+# define INTC_INTPR13_OFFSET_SIZE 24
+#define INTC_INTREQ13 0x134
+# define INTC_INTREQ13_IREQUEST416_OFFSET 0
+# define INTC_INTREQ13_IREQUEST416_SIZE 1
+#define INTC_INTPR14 0x38
+# define INTC_INTPR14_INTLEV_OFFSET 30
+# define INTC_INTPR14_INTLEV_SIZE 2
+# define INTC_INTPR14_OFFSET_OFFSET 0
+# define INTC_INTPR14_OFFSET_SIZE 24
+#define INTC_INTREQ14 0x138
+# define INTC_INTREQ14_IREQUEST448_OFFSET 0
+# define INTC_INTREQ14_IREQUEST448_SIZE 1
+#define INTC_INTPR15 0x3c
+# define INTC_INTPR15_INTLEV_OFFSET 30
+# define INTC_INTPR15_INTLEV_SIZE 2
+# define INTC_INTPR15_OFFSET_OFFSET 0
+# define INTC_INTPR15_OFFSET_SIZE 24
+#define INTC_INTREQ15 0x13c
+# define INTC_INTREQ15_IREQUEST480_OFFSET 0
+# define INTC_INTREQ15_IREQUEST480_SIZE 1
+#define INTC_INTPR16 0x40
+# define INTC_INTPR16_INTLEV_OFFSET 30
+# define INTC_INTPR16_INTLEV_SIZE 2
+# define INTC_INTPR16_OFFSET_OFFSET 0
+# define INTC_INTPR16_OFFSET_SIZE 24
+#define INTC_INTREQ16 0x140
+# define INTC_INTREQ16_IREQUEST512_OFFSET 0
+# define INTC_INTREQ16_IREQUEST512_SIZE 1
+#define INTC_INTPR17 0x44
+# define INTC_INTPR17_INTLEV_OFFSET 30
+# define INTC_INTPR17_INTLEV_SIZE 2
+# define INTC_INTPR17_OFFSET_OFFSET 0
+# define INTC_INTPR17_OFFSET_SIZE 24
+#define INTC_INTREQ17 0x144
+# define INTC_INTREQ17_IREQUEST544_OFFSET 0
+# define INTC_INTREQ17_IREQUEST544_SIZE 1
+#define INTC_INTPR18 0x48
+# define INTC_INTPR18_INTLEV_OFFSET 30
+# define INTC_INTPR18_INTLEV_SIZE 2
+# define INTC_INTPR18_OFFSET_OFFSET 0
+# define INTC_INTPR18_OFFSET_SIZE 24
+#define INTC_INTREQ18 0x148
+# define INTC_INTREQ18_IREQUEST576_OFFSET 0
+# define INTC_INTREQ18_IREQUEST576_SIZE 1
+#define INTC_INTPR19 0x4c
+# define INTC_INTPR19_INTLEV_OFFSET 30
+# define INTC_INTPR19_INTLEV_SIZE 2
+# define INTC_INTPR19_OFFSET_OFFSET 0
+# define INTC_INTPR19_OFFSET_SIZE 24
+#define INTC_INTREQ19 0x14c
+# define INTC_INTREQ19_IREQUEST608_OFFSET 0
+# define INTC_INTREQ19_IREQUEST608_SIZE 1
+# define INTC_INTREQ19_IREQUEST609_OFFSET 1
+# define INTC_INTREQ19_IREQUEST609_SIZE 1
+# define INTC_INTREQ19_IREQUEST610_OFFSET 2
+# define INTC_INTREQ19_IREQUEST610_SIZE 1
+# define INTC_INTREQ19_IREQUEST611_OFFSET 3
+# define INTC_INTREQ19_IREQUEST611_SIZE 1
+#define INTC_INTPR20 0x50
+# define INTC_INTPR20_INTLEV_OFFSET 30
+# define INTC_INTPR20_INTLEV_SIZE 2
+# define INTC_INTPR20_OFFSET_OFFSET 0
+# define INTC_INTPR20_OFFSET_SIZE 24
+#define INTC_INTREQ20 0x150
+# define INTC_INTREQ20_IREQUEST640_OFFSET 0
+# define INTC_INTREQ20_IREQUEST640_SIZE 1
+#define INTC_INTPR21 0x54
+# define INTC_INTPR21_INTLEV_OFFSET 30
+# define INTC_INTPR21_INTLEV_SIZE 2
+# define INTC_INTPR21_OFFSET_OFFSET 0
+# define INTC_INTPR21_OFFSET_SIZE 24
+#define INTC_INTREQ21 0x154
+# define INTC_INTREQ21_IREQUEST672_OFFSET 0
+# define INTC_INTREQ21_IREQUEST672_SIZE 1
+#define INTC_INTPR22 0x58
+# define INTC_INTPR22_INTLEV_OFFSET 30
+# define INTC_INTPR22_INTLEV_SIZE 2
+# define INTC_INTPR22_OFFSET_OFFSET 0
+# define INTC_INTPR22_OFFSET_SIZE 24
+#define INTC_INTREQ22 0x158
+# define INTC_INTREQ22_IREQUEST704_OFFSET 0
+# define INTC_INTREQ22_IREQUEST704_SIZE 1
+# define INTC_INTREQ22_IREQUEST705_OFFSET 1
+# define INTC_INTREQ22_IREQUEST705_SIZE 1
+# define INTC_INTREQ22_IREQUEST706_OFFSET 2
+# define INTC_INTREQ22_IREQUEST706_SIZE 1
+#define INTC_INTPR23 0x5c
+# define INTC_INTPR23_INTLEV_OFFSET 30
+# define INTC_INTPR23_INTLEV_SIZE 2
+# define INTC_INTPR23_OFFSET_OFFSET 0
+# define INTC_INTPR23_OFFSET_SIZE 24
+#define INTC_INTREQ23 0x15c
+# define INTC_INTREQ23_IREQUEST736_OFFSET 0
+# define INTC_INTREQ23_IREQUEST736_SIZE 1
+# define INTC_INTREQ23_IREQUEST737_OFFSET 1
+# define INTC_INTREQ23_IREQUEST737_SIZE 1
+# define INTC_INTREQ23_IREQUEST738_OFFSET 2
+# define INTC_INTREQ23_IREQUEST738_SIZE 1
+#define INTC_INTPR24 0x60
+# define INTC_INTPR24_INTLEV_OFFSET 30
+# define INTC_INTPR24_INTLEV_SIZE 2
+# define INTC_INTPR24_OFFSET_OFFSET 0
+# define INTC_INTPR24_OFFSET_SIZE 24
+#define INTC_INTREQ24 0x160
+# define INTC_INTREQ24_IREQUEST768_OFFSET 0
+# define INTC_INTREQ24_IREQUEST768_SIZE 1
+#define INTC_INTPR25 0x64
+# define INTC_INTPR25_INTLEV_OFFSET 30
+# define INTC_INTPR25_INTLEV_SIZE 2
+# define INTC_INTPR25_OFFSET_OFFSET 0
+# define INTC_INTPR25_OFFSET_SIZE 24
+#define INTC_INTREQ25 0x164
+# define INTC_INTREQ25_IREQUEST800_OFFSET 0
+# define INTC_INTREQ25_IREQUEST800_SIZE 1
+#define INTC_INTPR26 0x68
+# define INTC_INTPR26_INTLEV_OFFSET 30
+# define INTC_INTPR26_INTLEV_SIZE 2
+# define INTC_INTPR26_OFFSET_OFFSET 0
+# define INTC_INTPR26_OFFSET_SIZE 24
+#define INTC_INTREQ26 0x168
+# define INTC_INTREQ26_IREQUEST832_OFFSET 0
+# define INTC_INTREQ26_IREQUEST832_SIZE 1
+#define INTC_INTPR27 0x6c
+# define INTC_INTPR27_INTLEV_OFFSET 30
+# define INTC_INTPR27_INTLEV_SIZE 2
+# define INTC_INTPR27_OFFSET_OFFSET 0
+# define INTC_INTPR27_OFFSET_SIZE 24
+#define INTC_INTREQ27 0x16c
+# define INTC_INTREQ27_IREQUEST864_OFFSET 0
+# define INTC_INTREQ27_IREQUEST864_SIZE 1
+#define INTC_INTPR28 0x70
+# define INTC_INTPR28_INTLEV_OFFSET 30
+# define INTC_INTPR28_INTLEV_SIZE 2
+# define INTC_INTPR28_OFFSET_OFFSET 0
+# define INTC_INTPR28_OFFSET_SIZE 24
+#define INTC_INTREQ28 0x170
+# define INTC_INTREQ28_IREQUEST896_OFFSET 0
+# define INTC_INTREQ28_IREQUEST896_SIZE 1
+#define INTC_INTPR29 0x74
+# define INTC_INTPR29_INTLEV_OFFSET 30
+# define INTC_INTPR29_INTLEV_SIZE 2
+# define INTC_INTPR29_OFFSET_OFFSET 0
+# define INTC_INTPR29_OFFSET_SIZE 24
+#define INTC_INTREQ29 0x174
+# define INTC_INTREQ29_IREQUEST928_OFFSET 0
+# define INTC_INTREQ29_IREQUEST928_SIZE 1
+#define INTC_INTPR30 0x78
+# define INTC_INTPR30_INTLEV_OFFSET 30
+# define INTC_INTPR30_INTLEV_SIZE 2
+# define INTC_INTPR30_OFFSET_OFFSET 0
+# define INTC_INTPR30_OFFSET_SIZE 24
+#define INTC_INTREQ30 0x178
+# define INTC_INTREQ30_IREQUEST960_OFFSET 0
+# define INTC_INTREQ30_IREQUEST960_SIZE 1
+#define INTC_INTPR31 0x7c
+# define INTC_INTPR31_INTLEV_OFFSET 30
+# define INTC_INTPR31_INTLEV_SIZE 2
+# define INTC_INTPR31_OFFSET_OFFSET 0
+# define INTC_INTPR31_OFFSET_SIZE 24
+#define INTC_INTREQ31 0x17c
+# define INTC_INTREQ31_IREQUEST992_OFFSET 0
+# define INTC_INTREQ31_IREQUEST992_SIZE 1
+#define INTC_INTPR32 0x80
+# define INTC_INTPR32_INTLEV_OFFSET 30
+# define INTC_INTPR32_INTLEV_SIZE 2
+# define INTC_INTPR32_OFFSET_OFFSET 0
+# define INTC_INTPR32_OFFSET_SIZE 24
+#define INTC_INTREQ32 0x180
+# define INTC_INTREQ32_IREQUEST1024_OFFSET 0
+# define INTC_INTREQ32_IREQUEST1024_SIZE 1
+#define INTC_INTCAUSE0 0x20c
+# define INTC_INTCAUSE0_CAUSEGRP_OFFSET 0
+# define INTC_INTCAUSE0_CAUSEGRP_SIZE 6
+#define INTC_INTCAUSE1 0x208
+# define INTC_INTCAUSE1_CAUSEGRP_OFFSET 0
+# define INTC_INTCAUSE1_CAUSEGRP_SIZE 6
+#define INTC_INTCAUSE2 0x204
+# define INTC_INTCAUSE2_CAUSEGRP_OFFSET 0
+# define INTC_INTCAUSE2_CAUSEGRP_SIZE 6
+#define INTC_INTCAUSE3 0x200
+# define INTC_INTCAUSE3_CAUSEGRP_OFFSET 0
+# define INTC_INTCAUSE3_CAUSEGRP_SIZE 6
+
+#define INTC_BIT(name) (1 << INTC_##name##_OFFSET)
+#define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET)
+#define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1))
+
+#define intc_readl(port,reg) readl((port)->regs + INTC_##reg)
+#define intc_writel(port,reg,value) writel((value), (port)->regs + INTC_##reg)
+
+#endif /* __ASM_AVR32_PERIHP_INTC_H__ */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
new file mode 100644
index 00000000000..d3aabfca859
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -0,0 +1,118 @@
+/*
+ * Atmel PIO2 Port Multiplexer support
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/portmux.h>
+
+#include "pio.h"
+
+#define MAX_NR_PIO_DEVICES 8
+
+struct pio_device {
+ void __iomem *regs;
+ const struct platform_device *pdev;
+ struct clk *clk;
+ u32 alloc_mask;
+ char name[32];
+};
+
+static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
+
+void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
+ unsigned int function_id)
+{
+ struct pio_device *pio;
+ u32 mask = 1 << pin_id;
+
+ BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+
+ pio = &pio_dev[portmux_id];
+
+ if (function_id)
+ pio_writel(pio, BSR, mask);
+ else
+ pio_writel(pio, ASR, mask);
+ pio_writel(pio, PDR, mask);
+}
+
+static int __init pio_probe(struct platform_device *pdev)
+{
+ struct pio_device *pio = NULL;
+
+ BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
+ pio = &pio_dev[pdev->id];
+ BUG_ON(!pio->regs);
+
+ /* TODO: Interrupts */
+
+ platform_set_drvdata(pdev, pio);
+
+ printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
+ pio->name, pio->regs, platform_get_irq(pdev, 0));
+
+ return 0;
+}
+
+static struct platform_driver pio_driver = {
+ .probe = pio_probe,
+ .driver = {
+ .name = "pio",
+ },
+};
+
+static int __init pio_init(void)
+{
+ return platform_driver_register(&pio_driver);
+}
+subsys_initcall(pio_init);
+
+void __init at32_init_pio(struct platform_device *pdev)
+{
+ struct resource *regs;
+ struct pio_device *pio;
+
+ if (pdev->id > MAX_NR_PIO_DEVICES) {
+ dev_err(&pdev->dev, "only %d PIO devices supported\n",
+ MAX_NR_PIO_DEVICES);
+ return;
+ }
+
+ pio = &pio_dev[pdev->id];
+ snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id);
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(&pdev->dev, "no mmio resource defined\n");
+ return;
+ }
+
+ pio->clk = clk_get(&pdev->dev, "mck");
+ if (IS_ERR(pio->clk))
+ /*
+ * This is a fatal error, but if we continue we might
+ * be so lucky that we manage to initialize the
+ * console and display this message...
+ */
+ dev_err(&pdev->dev, "no mck clock defined\n");
+ else
+ clk_enable(pio->clk);
+
+ pio->pdev = pdev;
+ pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
+
+ pio_writel(pio, ODR, ~0UL);
+ pio_writel(pio, PER, ~0UL);
+}
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
new file mode 100644
index 00000000000..cfea1235159
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -0,0 +1,178 @@
+/*
+ * Atmel PIO2 Port Multiplexer support
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef __ARCH_AVR32_AT32AP_PIO_H__
+#define __ARCH_AVR32_AT32AP_PIO_H__
+
+/* PIO register offsets */
+#define PIO_PER 0x0000
+#define PIO_PDR 0x0004
+#define PIO_PSR 0x0008
+#define PIO_OER 0x0010
+#define PIO_ODR 0x0014
+#define PIO_OSR 0x0018
+#define PIO_IFER 0x0020
+#define PIO_IFDR 0x0024
+#define PIO_ISFR 0x0028
+#define PIO_SODR 0x0030
+#define PIO_CODR 0x0034
+#define PIO_ODSR 0x0038
+#define PIO_PDSR 0x003c
+#define PIO_IER 0x0040
+#define PIO_IDR 0x0044
+#define PIO_IMR 0x0048
+#define PIO_ISR 0x004c
+#define PIO_MDER 0x0050
+#define PIO_MDDR 0x0054
+#define PIO_MDSR 0x0058
+#define PIO_PUDR 0x0060
+#define PIO_PUER 0x0064
+#define PIO_PUSR 0x0068
+#define PIO_ASR 0x0070
+#define PIO_BSR 0x0074
+#define PIO_ABSR 0x0078
+#define PIO_OWER 0x00a0
+#define PIO_OWDR 0x00a4
+#define PIO_OWSR 0x00a8
+
+/* Bitfields in PER */
+
+/* Bitfields in PDR */
+
+/* Bitfields in PSR */
+
+/* Bitfields in OER */
+
+/* Bitfields in ODR */
+
+/* Bitfields in OSR */
+
+/* Bitfields in IFER */
+
+/* Bitfields in IFDR */
+
+/* Bitfields in ISFR */
+
+/* Bitfields in SODR */
+
+/* Bitfields in CODR */
+
+/* Bitfields in ODSR */
+
+/* Bitfields in PDSR */
+
+/* Bitfields in IER */
+
+/* Bitfields in IDR */
+
+/* Bitfields in IMR */
+
+/* Bitfields in ISR */
+
+/* Bitfields in MDER */
+
+/* Bitfields in MDDR */
+
+/* Bitfields in MDSR */
+
+/* Bitfields in PUDR */
+
+/* Bitfields in PUER */
+
+/* Bitfields in PUSR */
+
+/* Bitfields in ASR */
+
+/* Bitfields in BSR */
+
+/* Bitfields in ABSR */
+#define PIO_P0_OFFSET 0
+#define PIO_P0_SIZE 1
+#define PIO_P1_OFFSET 1
+#define PIO_P1_SIZE 1
+#define PIO_P2_OFFSET 2
+#define PIO_P2_SIZE 1
+#define PIO_P3_OFFSET 3
+#define PIO_P3_SIZE 1
+#define PIO_P4_OFFSET 4
+#define PIO_P4_SIZE 1
+#define PIO_P5_OFFSET 5
+#define PIO_P5_SIZE 1
+#define PIO_P6_OFFSET 6
+#define PIO_P6_SIZE 1
+#define PIO_P7_OFFSET 7
+#define PIO_P7_SIZE 1
+#define PIO_P8_OFFSET 8
+#define PIO_P8_SIZE 1
+#define PIO_P9_OFFSET 9
+#define PIO_P9_SIZE 1
+#define PIO_P10_OFFSET 10
+#define PIO_P10_SIZE 1
+#define PIO_P11_OFFSET 11
+#define PIO_P11_SIZE 1
+#define PIO_P12_OFFSET 12
+#define PIO_P12_SIZE 1
+#define PIO_P13_OFFSET 13
+#define PIO_P13_SIZE 1
+#define PIO_P14_OFFSET 14
+#define PIO_P14_SIZE 1
+#define PIO_P15_OFFSET 15
+#define PIO_P15_SIZE 1
+#define PIO_P16_OFFSET 16
+#define PIO_P16_SIZE 1
+#define PIO_P17_OFFSET 17
+#define PIO_P17_SIZE 1
+#define PIO_P18_OFFSET 18
+#define PIO_P18_SIZE 1
+#define PIO_P19_OFFSET 19
+#define PIO_P19_SIZE 1
+#define PIO_P20_OFFSET 20
+#define PIO_P20_SIZE 1
+#define PIO_P21_OFFSET 21
+#define PIO_P21_SIZE 1
+#define PIO_P22_OFFSET 22
+#define PIO_P22_SIZE 1
+#define PIO_P23_OFFSET 23
+#define PIO_P23_SIZE 1
+#define PIO_P24_OFFSET 24
+#define PIO_P24_SIZE 1
+#define PIO_P25_OFFSET 25
+#define PIO_P25_SIZE 1
+#define PIO_P26_OFFSET 26
+#define PIO_P26_SIZE 1
+#define PIO_P27_OFFSET 27
+#define PIO_P27_SIZE 1
+#define PIO_P28_OFFSET 28
+#define PIO_P28_SIZE 1
+#define PIO_P29_OFFSET 29
+#define PIO_P29_SIZE 1
+#define PIO_P30_OFFSET 30
+#define PIO_P30_SIZE 1
+#define PIO_P31_OFFSET 31
+#define PIO_P31_SIZE 1
+
+/* Bitfields in OWER */
+
+/* Bitfields in OWDR */
+
+/* Bitfields in OWSR */
+
+/* Bit manipulation macros */
+#define PIO_BIT(name) (1 << PIO_##name##_OFFSET)
+#define PIO_BF(name,value) (((value) & ((1 << PIO_##name##_SIZE) - 1)) << PIO_##name##_OFFSET)
+#define PIO_BFEXT(name,value) (((value) >> PIO_##name##_OFFSET) & ((1 << PIO_##name##_SIZE) - 1))
+#define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value))
+
+/* Register access macros */
+#define pio_readl(port,reg) readl((port)->regs + PIO_##reg)
+#define pio_writel(port,reg,value) writel((value), (port)->regs + PIO_##reg)
+
+void at32_init_pio(struct platform_device *pdev);
+
+#endif /* __ARCH_AVR32_AT32AP_PIO_H__ */
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
new file mode 100644
index 00000000000..03306eb0345
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.c
@@ -0,0 +1,289 @@
+/*
+ * System Manager driver for AT32AP CPUs
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+
+#include <asm/intc.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/sm.h>
+
+#include "sm.h"
+
+#define SM_EIM_IRQ_RESOURCE 1
+#define SM_PM_IRQ_RESOURCE 2
+#define SM_RTC_IRQ_RESOURCE 3
+
+#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
+
+struct at32_sm system_manager;
+
+int __init at32_sm_init(void)
+{
+ struct resource *regs;
+ struct at32_sm *sm = &system_manager;
+ int ret = -ENXIO;
+
+ regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
+ if (!regs)
+ goto fail;
+
+ spin_lock_init(&sm->lock);
+ sm->pdev = &at32_sm_device;
+
+ ret = -ENOMEM;
+ sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!sm->regs)
+ goto fail;
+
+ return 0;
+
+fail:
+ printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
+ return ret;
+}
+
+/*
+ * External Interrupt Module (EIM).
+ *
+ * EIM gets level- or edge-triggered interrupts of either polarity
+ * from the outside and converts it to active-high level-triggered
+ * interrupts that the internal interrupt controller can handle. EIM
+ * also provides masking/unmasking of interrupts, as well as
+ * acknowledging of edge-triggered interrupts.
+ */
+
+static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
+ disable_irq(irq);
+ return IRQ_NONE;
+}
+
+static struct irqaction eim_spurious_action = {
+ .handler = spurious_eim_interrupt,
+};
+
+static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct irq_controller * irqc = dev_id;
+ struct at32_sm *sm = to_eim(irqc);
+ unsigned long pending;
+
+ /*
+ * No need to disable interrupts globally. The interrupt
+ * level relevant to this group must be masked all the time,
+ * so we know that this particular EIM instance will not be
+ * re-entered.
+ */
+ spin_lock(&sm->lock);
+
+ pending = intc_get_pending(sm->irqc.irq_group);
+ if (unlikely(!pending)) {
+ printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
+ sm->irqc.irq_group);
+ goto unlock;
+ }
+
+ do {
+ struct irqaction *action;
+ unsigned int i;
+
+ i = fls(pending) - 1;
+ pending &= ~(1 << i);
+ action = sm->action[i];
+
+ /* Acknowledge the interrupt */
+ sm_writel(sm, EIM_ICR, 1 << i);
+
+ spin_unlock(&sm->lock);
+
+ if (action->flags & SA_INTERRUPT)
+ local_irq_disable();
+ action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
+ local_irq_enable();
+ spin_lock(&sm->lock);
+ if (action->flags & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(sm->irqc.first_irq + i);
+ } while (pending);
+
+unlock:
+ spin_unlock(&sm->lock);
+ return IRQ_HANDLED;
+}
+
+static void eim_mask(struct irq_controller *irqc, unsigned int irq)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ unsigned int i;
+
+ i = irq - sm->irqc.first_irq;
+ sm_writel(sm, EIM_IDR, 1 << i);
+}
+
+static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ unsigned int i;
+
+ i = irq - sm->irqc.first_irq;
+ sm_writel(sm, EIM_IER, 1 << i);
+}
+
+static int eim_setup(struct irq_controller *irqc, unsigned int irq,
+ struct irqaction *action)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ sm->action[irq - sm->irqc.first_irq] = action;
+ /* Acknowledge earlier interrupts */
+ sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
+ eim_unmask(irqc, irq);
+ return 0;
+}
+
+static void eim_free(struct irq_controller *irqc, unsigned int irq,
+ void *dev)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ eim_mask(irqc, irq);
+ sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
+}
+
+static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
+ unsigned int type)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ unsigned long flags;
+ u32 value, pattern;
+
+ spin_lock_irqsave(&sm->lock, flags);
+
+ pattern = 1 << (irq - sm->irqc.first_irq);
+
+ value = sm_readl(sm, EIM_MODE);
+ if (type & IRQ_TYPE_LEVEL)
+ value |= pattern;
+ else
+ value &= ~pattern;
+ sm_writel(sm, EIM_MODE, value);
+ value = sm_readl(sm, EIM_EDGE);
+ if (type & IRQ_EDGE_RISING)
+ value |= pattern;
+ else
+ value &= ~pattern;
+ sm_writel(sm, EIM_EDGE, value);
+ value = sm_readl(sm, EIM_LEVEL);
+ if (type & IRQ_LEVEL_HIGH)
+ value |= pattern;
+ else
+ value &= ~pattern;
+ sm_writel(sm, EIM_LEVEL, value);
+
+ spin_unlock_irqrestore(&sm->lock, flags);
+
+ return 0;
+}
+
+static unsigned int eim_get_type(struct irq_controller *irqc,
+ unsigned int irq)
+{
+ struct at32_sm *sm = to_eim(irqc);
+ unsigned long flags;
+ unsigned int type = 0;
+ u32 mode, edge, level, pattern;
+
+ pattern = 1 << (irq - sm->irqc.first_irq);
+
+ spin_lock_irqsave(&sm->lock, flags);
+ mode = sm_readl(sm, EIM_MODE);
+ edge = sm_readl(sm, EIM_EDGE);
+ level = sm_readl(sm, EIM_LEVEL);
+ spin_unlock_irqrestore(&sm->lock, flags);
+
+ if (mode & pattern)
+ type |= IRQ_TYPE_LEVEL;
+ if (edge & pattern)
+ type |= IRQ_EDGE_RISING;
+ if (level & pattern)
+ type |= IRQ_LEVEL_HIGH;
+
+ return type;
+}
+
+static struct irq_controller_class eim_irq_class = {
+ .typename = "EIM",
+ .handle = eim_handle_irq,
+ .setup = eim_setup,
+ .free = eim_free,
+ .mask = eim_mask,
+ .unmask = eim_unmask,
+ .set_type = eim_set_type,
+ .get_type = eim_get_type,
+};
+
+static int __init eim_init(void)
+{
+ struct at32_sm *sm = &system_manager;
+ unsigned int i;
+ u32 pattern;
+ int ret;
+
+ /*
+ * The EIM is really the same module as SM, so register
+ * mapping, etc. has been taken care of already.
+ */
+
+ /*
+ * Find out how many interrupt lines that are actually
+ * implemented in hardware.
+ */
+ sm_writel(sm, EIM_IDR, ~0UL);
+ sm_writel(sm, EIM_MODE, ~0UL);
+ pattern = sm_readl(sm, EIM_MODE);
+ sm->irqc.nr_irqs = fls(pattern);
+
+ ret = -ENOMEM;
+ sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
+ GFP_KERNEL);
+ if (!sm->action)
+ goto out;
+
+ for (i = 0; i < sm->irqc.nr_irqs; i++)
+ sm->action[i] = &eim_spurious_action;
+
+ spin_lock_init(&sm->lock);
+ sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
+ sm->irqc.class = &eim_irq_class;
+
+ ret = intc_register_controller(&sm->irqc);
+ if (ret < 0)
+ goto out_free_actions;
+
+ printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
+ sm->regs, sm->irqc.irq_group);
+ printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
+ sm->irqc.nr_irqs, sm->irqc.first_irq);
+
+ return 0;
+
+out_free_actions:
+ kfree(sm->action);
+out:
+ return ret;
+}
+arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h
new file mode 100644
index 00000000000..27565822ae2
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.h
@@ -0,0 +1,240 @@
+/*
+ * Register definitions for SM
+ *
+ * System Manager
+ */
+#ifndef __ASM_AVR32_SM_H__
+#define __ASM_AVR32_SM_H__
+
+/* SM register offsets */
+#define SM_PM_MCCTRL 0x0000
+#define SM_PM_CKSEL 0x0004
+#define SM_PM_CPU_MASK 0x0008
+#define SM_PM_HSB_MASK 0x000c
+#define SM_PM_PBA_MASK 0x0010
+#define SM_PM_PBB_MASK 0x0014
+#define SM_PM_PLL0 0x0020
+#define SM_PM_PLL1 0x0024
+#define SM_PM_VCTRL 0x0030
+#define SM_PM_VMREF 0x0034
+#define SM_PM_VMV 0x0038
+#define SM_PM_IER 0x0040
+#define SM_PM_IDR 0x0044
+#define SM_PM_IMR 0x0048
+#define SM_PM_ISR 0x004c
+#define SM_PM_ICR 0x0050
+#define SM_PM_GCCTRL 0x0060
+#define SM_RTC_CTRL 0x0080
+#define SM_RTC_VAL 0x0084
+#define SM_RTC_TOP 0x0088
+#define SM_RTC_IER 0x0090
+#define SM_RTC_IDR 0x0094
+#define SM_RTC_IMR 0x0098
+#define SM_RTC_ISR 0x009c
+#define SM_RTC_ICR 0x00a0
+#define SM_WDT_CTRL 0x00b0
+#define SM_WDT_CLR 0x00b4
+#define SM_WDT_EXT 0x00b8
+#define SM_RC_RCAUSE 0x00c0
+#define SM_EIM_IER 0x0100
+#define SM_EIM_IDR 0x0104
+#define SM_EIM_IMR 0x0108
+#define SM_EIM_ISR 0x010c
+#define SM_EIM_ICR 0x0110
+#define SM_EIM_MODE 0x0114
+#define SM_EIM_EDGE 0x0118
+#define SM_EIM_LEVEL 0x011c
+#define SM_EIM_TEST 0x0120
+#define SM_EIM_NMIC 0x0124
+
+/* Bitfields in PM_MCCTRL */
+
+/* Bitfields in PM_CKSEL */
+#define SM_CPUSEL_OFFSET 0
+#define SM_CPUSEL_SIZE 3
+#define SM_CPUDIV_OFFSET 7
+#define SM_CPUDIV_SIZE 1
+#define SM_HSBSEL_OFFSET 8
+#define SM_HSBSEL_SIZE 3
+#define SM_HSBDIV_OFFSET 15
+#define SM_HSBDIV_SIZE 1
+#define SM_PBASEL_OFFSET 16
+#define SM_PBASEL_SIZE 3
+#define SM_PBADIV_OFFSET 23
+#define SM_PBADIV_SIZE 1
+#define SM_PBBSEL_OFFSET 24
+#define SM_PBBSEL_SIZE 3
+#define SM_PBBDIV_OFFSET 31
+#define SM_PBBDIV_SIZE 1
+
+/* Bitfields in PM_CPU_MASK */
+
+/* Bitfields in PM_HSB_MASK */
+
+/* Bitfields in PM_PBA_MASK */
+
+/* Bitfields in PM_PBB_MASK */
+
+/* Bitfields in PM_PLL0 */
+#define SM_PLLEN_OFFSET 0
+#define SM_PLLEN_SIZE 1
+#define SM_PLLOSC_OFFSET 1
+#define SM_PLLOSC_SIZE 1
+#define SM_PLLOPT_OFFSET 2
+#define SM_PLLOPT_SIZE 3
+#define SM_PLLDIV_OFFSET 8
+#define SM_PLLDIV_SIZE 8
+#define SM_PLLMUL_OFFSET 16
+#define SM_PLLMUL_SIZE 8
+#define SM_PLLCOUNT_OFFSET 24
+#define SM_PLLCOUNT_SIZE 6
+#define SM_PLLTEST_OFFSET 31
+#define SM_PLLTEST_SIZE 1
+
+/* Bitfields in PM_PLL1 */
+
+/* Bitfields in PM_VCTRL */
+#define SM_VAUTO_OFFSET 0
+#define SM_VAUTO_SIZE 1
+#define SM_PM_VCTRL_VAL_OFFSET 8
+#define SM_PM_VCTRL_VAL_SIZE 7
+
+/* Bitfields in PM_VMREF */
+#define SM_REFSEL_OFFSET 0
+#define SM_REFSEL_SIZE 4
+
+/* Bitfields in PM_VMV */
+#define SM_PM_VMV_VAL_OFFSET 0
+#define SM_PM_VMV_VAL_SIZE 8
+
+/* Bitfields in PM_IER */
+
+/* Bitfields in PM_IDR */
+
+/* Bitfields in PM_IMR */
+
+/* Bitfields in PM_ISR */
+
+/* Bitfields in PM_ICR */
+#define SM_LOCK0_OFFSET 0
+#define SM_LOCK0_SIZE 1
+#define SM_LOCK1_OFFSET 1
+#define SM_LOCK1_SIZE 1
+#define SM_WAKE_OFFSET 2
+#define SM_WAKE_SIZE 1
+#define SM_VOK_OFFSET 3
+#define SM_VOK_SIZE 1
+#define SM_VMRDY_OFFSET 4
+#define SM_VMRDY_SIZE 1
+#define SM_CKRDY_OFFSET 5
+#define SM_CKRDY_SIZE 1
+
+/* Bitfields in PM_GCCTRL */
+#define SM_OSCSEL_OFFSET 0
+#define SM_OSCSEL_SIZE 1
+#define SM_PLLSEL_OFFSET 1
+#define SM_PLLSEL_SIZE 1
+#define SM_CEN_OFFSET 2
+#define SM_CEN_SIZE 1
+#define SM_CPC_OFFSET 3
+#define SM_CPC_SIZE 1
+#define SM_DIVEN_OFFSET 4
+#define SM_DIVEN_SIZE 1
+#define SM_DIV_OFFSET 8
+#define SM_DIV_SIZE 8
+
+/* Bitfields in RTC_CTRL */
+#define SM_PCLR_OFFSET 1
+#define SM_PCLR_SIZE 1
+#define SM_TOPEN_OFFSET 2
+#define SM_TOPEN_SIZE 1
+#define SM_CLKEN_OFFSET 3
+#define SM_CLKEN_SIZE 1
+#define SM_PSEL_OFFSET 8
+#define SM_PSEL_SIZE 16
+
+/* Bitfields in RTC_VAL */
+#define SM_RTC_VAL_VAL_OFFSET 0
+#define SM_RTC_VAL_VAL_SIZE 31
+
+/* Bitfields in RTC_TOP */
+#define SM_RTC_TOP_VAL_OFFSET 0
+#define SM_RTC_TOP_VAL_SIZE 32
+
+/* Bitfields in RTC_IER */
+
+/* Bitfields in RTC_IDR */
+
+/* Bitfields in RTC_IMR */
+
+/* Bitfields in RTC_ISR */
+
+/* Bitfields in RTC_ICR */
+#define SM_TOPI_OFFSET 0
+#define SM_TOPI_SIZE 1
+
+/* Bitfields in WDT_CTRL */
+#define SM_KEY_OFFSET 24
+#define SM_KEY_SIZE 8
+
+/* Bitfields in WDT_CLR */
+
+/* Bitfields in WDT_EXT */
+
+/* Bitfields in RC_RCAUSE */
+#define SM_POR_OFFSET 0
+#define SM_POR_SIZE 1
+#define SM_BOD_OFFSET 1
+#define SM_BOD_SIZE 1
+#define SM_EXT_OFFSET 2
+#define SM_EXT_SIZE 1
+#define SM_WDT_OFFSET 3
+#define SM_WDT_SIZE 1
+#define SM_NTAE_OFFSET 4
+#define SM_NTAE_SIZE 1
+#define SM_SERP_OFFSET 5
+#define SM_SERP_SIZE 1
+
+/* Bitfields in EIM_IER */
+
+/* Bitfields in EIM_IDR */
+
+/* Bitfields in EIM_IMR */
+
+/* Bitfields in EIM_ISR */
+
+/* Bitfields in EIM_ICR */
+
+/* Bitfields in EIM_MODE */
+
+/* Bitfields in EIM_EDGE */
+#define SM_INT0_OFFSET 0
+#define SM_INT0_SIZE 1
+#define SM_INT1_OFFSET 1
+#define SM_INT1_SIZE 1
+#define SM_INT2_OFFSET 2
+#define SM_INT2_SIZE 1
+#define SM_INT3_OFFSET 3
+#define SM_INT3_SIZE 1
+
+/* Bitfields in EIM_LEVEL */
+
+/* Bitfields in EIM_TEST */
+#define SM_TESTEN_OFFSET 31
+#define SM_TESTEN_SIZE 1
+
+/* Bitfields in EIM_NMIC */
+#define SM_EN_OFFSET 0
+#define SM_EN_SIZE 1
+
+/* Bit manipulation macros */
+#define SM_BIT(name) (1 << SM_##name##_OFFSET)
+#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
+#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
+#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
+
+/* Register access macros */
+#define sm_readl(port,reg) readl((port)->regs + SM_##reg)
+#define sm_writel(port,reg,value) writel((value), (port)->regs + SM_##reg)
+
+#endif /* __ASM_AVR32_SM_H__ */
diff --git a/arch/avr32/mm/Makefile b/arch/avr32/mm/Makefile
new file mode 100644
index 00000000000..0066491f90d
--- /dev/null
+++ b/arch/avr32/mm/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux/AVR32 kernel.
+#
+
+obj-y += init.o clear_page.o copy_page.o dma-coherent.o
+obj-y += ioremap.o cache.o fault.o tlb.o
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
new file mode 100644
index 00000000000..450515b245a
--- /dev/null
+++ b/arch/avr32/mm/cache.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/highmem.h>
+#include <linux/unistd.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cachectl.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+/*
+ * If you attempt to flush anything more than this, you need superuser
+ * privileges. The value is completely arbitrary.
+ */
+#define CACHEFLUSH_MAX_LEN 1024
+
+void invalidate_dcache_region(void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = boot_cpu_data.dcache.linesz;
+
+ //printk("invalidate dcache: %p + %u\n", start, size);
+
+ /* You asked for it, you got it */
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ invalidate_dcache_line((void *)v);
+}
+
+void clean_dcache_region(void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = boot_cpu_data.dcache.linesz;
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ clean_dcache_line((void *)v);
+ flush_write_buffer();
+}
+
+void flush_dcache_region(void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = boot_cpu_data.dcache.linesz;
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ flush_dcache_line((void *)v);
+ flush_write_buffer();
+}
+
+void invalidate_icache_region(void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = boot_cpu_data.icache.linesz;
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ invalidate_icache_line((void *)v);
+}
+
+static inline void __flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long v, linesz;
+
+ linesz = boot_cpu_data.dcache.linesz;
+ for (v = start; v < end; v += linesz) {
+ clean_dcache_line((void *)v);
+ invalidate_icache_line((void *)v);
+ }
+
+ flush_write_buffer();
+}
+
+/*
+ * This one is called after a module has been loaded.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long linesz;
+
+ linesz = boot_cpu_data.dcache.linesz;
+ __flush_icache_range(start & ~(linesz - 1),
+ (end + linesz - 1) & ~(linesz - 1));
+}
+
+/*
+ * This one is called from do_no_page(), do_swap_page() and install_page().
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ if (vma->vm_flags & VM_EXEC) {
+ void *v = kmap(page);
+ __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE);
+ kunmap(v);
+ }
+}
+
+/*
+ * This one is used by copy_to_user_page()
+ */
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+ unsigned long addr, int len)
+{
+ if (vma->vm_flags & VM_EXEC)
+ flush_icache_range(addr, addr + len);
+}
+
+asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len)
+{
+ int ret;
+
+ if (len > CACHEFLUSH_MAX_LEN) {
+ ret = -EPERM;
+ if (!capable(CAP_SYS_ADMIN))
+ goto out;
+ }
+
+ ret = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, addr, len))
+ goto out;
+
+ switch (operation) {
+ case CACHE_IFLUSH:
+ flush_icache_range((unsigned long)addr,
+ (unsigned long)addr + len);
+ ret = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+out:
+ return ret;
+}
diff --git a/arch/avr32/mm/clear_page.S b/arch/avr32/mm/clear_page.S
new file mode 100644
index 00000000000..5d70dca0069
--- /dev/null
+++ b/arch/avr32/mm/clear_page.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/linkage.h>
+#include <asm/page.h>
+
+/*
+ * clear_page
+ * r12: P1 address (to)
+ */
+ .text
+ .global clear_page
+clear_page:
+ sub r9, r12, -PAGE_SIZE
+ mov r10, 0
+ mov r11, 0
+0: st.d r12++, r10
+ cp r12, r9
+ brne 0b
+ mov pc, lr
diff --git a/arch/avr32/mm/copy_page.S b/arch/avr32/mm/copy_page.S
new file mode 100644
index 00000000000..c2b3752946b
--- /dev/null
+++ b/arch/avr32/mm/copy_page.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/linkage.h>
+#include <asm/page.h>
+
+/*
+ * copy_page
+ *
+ * r12 to (P1 address)
+ * r11 from (P1 address)
+ * r8-r10 scratch
+ */
+ .text
+ .global copy_page
+copy_page:
+ sub r10, r11, -(1 << PAGE_SHIFT)
+ /* pref r11[0] */
+1: /* pref r11[8] */
+ ld.d r8, r11++
+ st.d r12++, r8
+ cp r11, r10
+ brlo 1b
+ mov pc, lr
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
new file mode 100644
index 00000000000..44ab8a7bdae
--- /dev/null
+++ b/arch/avr32/mm/dma-coherent.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/dma-mapping.h>
+
+#include <asm/addrspace.h>
+#include <asm/cacheflush.h>
+
+void dma_cache_sync(void *vaddr, size_t size, int direction)
+{
+ /*
+ * No need to sync an uncached area
+ */
+ if (PXSEG(vaddr) == P2SEG)
+ return;
+
+ switch (direction) {
+ case DMA_FROM_DEVICE: /* invalidate only */
+ dma_cache_inv(vaddr, size);
+ break;
+ case DMA_TO_DEVICE: /* writeback only */
+ dma_cache_wback(vaddr, size);
+ break;
+ case DMA_BIDIRECTIONAL: /* writeback and invalidate */
+ dma_cache_wback_inv(vaddr, size);
+ break;
+ default:
+ BUG();
+ }
+}
+EXPORT_SYMBOL(dma_cache_sync);
+
+static struct page *__dma_alloc(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ struct page *page, *free, *end;
+ int order;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(gfp, order);
+ if (!page)
+ return NULL;
+ split_page(page, order);
+
+ /*
+ * When accessing physical memory with valid cache data, we
+ * get a cache hit even if the virtual memory region is marked
+ * as uncached.
+ *
+ * Since the memory is newly allocated, there is no point in
+ * doing a writeback. If the previous owner cares, he should
+ * have flushed the cache before releasing the memory.
+ */
+ invalidate_dcache_region(phys_to_virt(page_to_phys(page)), size);
+
+ *handle = page_to_bus(page);
+ free = page + (size >> PAGE_SHIFT);
+ end = page + (1 << order);
+
+ /*
+ * Free any unused pages
+ */
+ while (free < end) {
+ __free_page(free);
+ free++;
+ }
+
+ return page;
+}
+
+static void __dma_free(struct device *dev, size_t size,
+ struct page *page, dma_addr_t handle)
+{
+ struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
+
+ while (page < end)
+ __free_page(page++);
+}
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ struct page *page;
+ void *ret = NULL;
+
+ page = __dma_alloc(dev, size, handle, gfp);
+ if (page)
+ ret = phys_to_uncached(page_to_phys(page));
+
+ return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t handle)
+{
+ void *addr = phys_to_cached(uncached_to_phys(cpu_addr));
+ struct page *page;
+
+ pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n",
+ cpu_addr, (unsigned long)handle, (unsigned)size);
+ BUG_ON(!virt_addr_valid(addr));
+ page = virt_to_page(addr);
+ __dma_free(dev, size, page, handle);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+#if 0
+void *dma_alloc_writecombine(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ struct page *page;
+
+ page = __dma_alloc(dev, size, handle, gfp);
+
+ /* Now, map the page into P3 with write-combining turned on */
+ return __ioremap(page_to_phys(page), size, _PAGE_BUFFER);
+}
+EXPORT_SYMBOL(dma_alloc_writecombine);
+
+void dma_free_writecombine(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t handle)
+{
+ struct page *page;
+
+ iounmap(cpu_addr);
+
+ page = bus_to_page(handle);
+ __dma_free(dev, size, page, handle);
+}
+EXPORT_SYMBOL(dma_free_writecombine);
+#endif
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
new file mode 100644
index 00000000000..678557260a3
--- /dev/null
+++ b/arch/avr32/mm/fault.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/sh/mm/fault.c:
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * 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/mm.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+
+#include <asm/kdebug.h>
+#include <asm/mmu_context.h>
+#include <asm/sysreg.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+
+#ifdef DEBUG
+static void dump_code(unsigned long pc)
+{
+ char *p = (char *)pc;
+ char val;
+ int i;
+
+
+ printk(KERN_DEBUG "Code:");
+ for (i = 0; i < 16; i++) {
+ if (__get_user(val, p + i))
+ break;
+ printk(" %02x", val);
+ }
+ printk("\n");
+}
+#endif
+
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
+ int trap, int sig)
+{
+ struct die_args args = {
+ .regs = regs,
+ .trapnr = trap,
+ };
+ return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
+ int trap, int sig)
+{
+ return NOTIFY_DONE;
+}
+#endif
+
+/*
+ * This routine handles page faults. It determines the address and the
+ * problem, and then passes it off to one of the appropriate routines.
+ *
+ * ecr is the Exception Cause Register. Possible values are:
+ * 5: Page not found (instruction access)
+ * 6: Protection fault (instruction access)
+ * 12: Page not found (read access)
+ * 13: Page not found (write access)
+ * 14: Protection fault (read access)
+ * 15: Protection fault (write access)
+ */
+asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ const struct exception_table_entry *fixup;
+ unsigned long address;
+ unsigned long page;
+ int writeaccess = 0;
+
+ if (notify_page_fault(DIE_PAGE_FAULT, regs,
+ ecr, SIGSEGV) == NOTIFY_STOP)
+ return;
+
+ address = sysreg_read(TLBEAR);
+
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * If we're in an interrupt or have no user context, we must
+ * not take the fault...
+ */
+ if (in_atomic() || !mm || regs->sr & SYSREG_BIT(GM))
+ goto no_context;
+
+ local_irq_enable();
+
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so we
+ * can handle it...
+ */
+good_area:
+ //pr_debug("good area: vm_flags = 0x%lx\n", vma->vm_flags);
+ switch (ecr) {
+ case ECR_PROTECTION_X:
+ case ECR_TLB_MISS_X:
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ break;
+ case ECR_PROTECTION_R:
+ case ECR_TLB_MISS_R:
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
+ goto bad_area;
+ break;
+ case ECR_PROTECTION_W:
+ case ECR_TLB_MISS_W:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ writeaccess = 1;
+ break;
+ default:
+ panic("Unhandled case %lu in do_page_fault!", ecr);
+ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+ * sure we exit gracefully rather than endlessly redo the
+ * fault.
+ */
+survive:
+ switch (handle_mm_fault(mm, vma, address, writeaccess)) {
+ case VM_FAULT_MINOR:
+ tsk->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ tsk->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ goto do_sigbus;
+ case VM_FAULT_OOM:
+ goto out_of_memory;
+ default:
+ BUG();
+ }
+
+ up_read(&mm->mmap_sem);
+ return;
+
+ /*
+ * Something tried to access memory that isn't in our memory
+ * map. Fix it, but check if it's kernel or user first...
+ */
+bad_area:
+ pr_debug("Bad area [%s:%u]: addr %08lx, ecr %lu\n",
+ tsk->comm, tsk->pid, address, ecr);
+
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ /* Hmm...we have to pass address and ecr somehow... */
+ /* tsk->thread.address = address;
+ tsk->thread.error_code = ecr; */
+#ifdef DEBUG
+ show_regs(regs);
+ dump_code(regs->pc);
+
+ page = sysreg_read(PTBR);
+ printk("ptbr = %08lx", page);
+ if (page) {
+ page = ((unsigned long *)page)[address >> 22];
+ printk(" pgd = %08lx", page);
+ if (page & _PAGE_PRESENT) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
+ printk(" pte = %08lx\n", page);
+ }
+ }
+#endif
+ pr_debug("Sending SIGSEGV to PID %d...\n",
+ tsk->pid);
+ force_sig(SIGSEGV, tsk);
+ return;
+ }
+
+no_context:
+ pr_debug("No context\n");
+
+ /* Are we prepared to handle this kernel fault? */
+ fixup = search_exception_tables(regs->pc);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ pr_debug("Found fixup at %08lx\n", fixup->fixup);
+ return;
+ }
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have
+ * to terminate things with extreme prejudice.
+ */
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT
+ "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT
+ "Unable to handle kernel paging request");
+ printk(" at virtual address %08lx\n", address);
+ printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+
+ page = sysreg_read(PTBR);
+ printk(KERN_ALERT "ptbr = %08lx", page);
+ if (page) {
+ page = ((unsigned long *)page)[address >> 22];
+ printk(" pgd = %08lx", page);
+ if (page & _PAGE_PRESENT) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
+ printk(" pte = %08lx\n", page);
+ }
+ }
+ die("\nOops", regs, ecr);
+ do_exit(SIGKILL);
+
+ /*
+ * We ran out of memory, or some other thing happened to us
+ * that made us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ printk("Out of memory\n");
+ up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ yield();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
+ printk("VM: Killing process %s\n", tsk->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel or
+ * user mode.
+ */
+ /* address, error_code, trap_no, ... */
+#ifdef DEBUG
+ show_regs(regs);
+ dump_code(regs->pc);
+#endif
+ pr_debug("Sending SIGBUS to PID %d...\n", tsk->pid);
+ force_sig(SIGBUS, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!user_mode(regs))
+ goto no_context;
+}
+
+asmlinkage void do_bus_error(unsigned long addr, int write_access,
+ struct pt_regs *regs)
+{
+ printk(KERN_ALERT
+ "Bus error at physical address 0x%08lx (%s access)\n",
+ addr, write_access ? "write" : "read");
+ printk(KERN_INFO "DTLB dump:\n");
+ dump_dtlb();
+ die("Bus Error", regs, write_access);
+ do_exit(SIGKILL);
+}
+
+/*
+ * This functionality is currently not possible to implement because
+ * we're using segmentation to ensure a fixed mapping of the kernel
+ * virtual address space.
+ *
+ * It would be possible to implement this, but it would require us to
+ * disable segmentation at startup and load the kernel mappings into
+ * the TLB like any other pages. There will be lots of trickery to
+ * avoid recursive invocation of the TLB miss handler, though...
+ */
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+
+}
+EXPORT_SYMBOL(kernel_map_pages);
+#endif
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
new file mode 100644
index 00000000000..3e6c4103980
--- /dev/null
+++ b/arch/avr32/mm/init.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/kernel.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/mmzone.h>
+#include <linux/bootmem.h>
+#include <linux/pagemap.h>
+#include <linux/pfn.h>
+#include <linux/nodemask.h>
+
+#include <asm/page.h>
+#include <asm/mmu_context.h>
+#include <asm/tlb.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/setup.h>
+#include <asm/sections.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+struct page *empty_zero_page;
+
+/*
+ * Cache of MMU context last used.
+ */
+unsigned long mmu_context_cache = NO_CONTEXT;
+
+#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
+
+void show_mem(void)
+{
+ int total = 0, reserved = 0, cached = 0;
+ int slab = 0, free = 0, shared = 0;
+ pg_data_t *pgdat;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+
+ for_each_online_pgdat(pgdat) {
+ struct page *page, *end;
+
+ page = pgdat->node_mem_map;
+ end = page + pgdat->node_spanned_pages;
+
+ do {
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (PageSlab(page))
+ slab++;
+ else if (!page_count(page))
+ free++;
+ else
+ shared += page_count(page) - 1;
+ page++;
+ } while (page < end);
+ }
+
+ printk ("%d pages of RAM\n", total);
+ printk ("%d free pages\n", free);
+ printk ("%d reserved pages\n", reserved);
+ printk ("%d slab pages\n", slab);
+ printk ("%d pages shared\n", shared);
+ printk ("%d pages swap cached\n", cached);
+}
+
+static void __init print_memory_map(const char *what,
+ struct tag_mem_range *mem)
+{
+ printk ("%s:\n", what);
+ for (; mem; mem = mem->next) {
+ printk (" %08lx - %08lx\n",
+ (unsigned long)mem->addr,
+ (unsigned long)(mem->addr + mem->size));
+ }
+}
+
+#define MAX_LOWMEM HIGHMEM_START
+#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM)
+
+/*
+ * Sort a list of memory regions in-place by ascending address.
+ *
+ * We're using bubble sort because we only have singly linked lists
+ * with few elements.
+ */
+static void __init sort_mem_list(struct tag_mem_range **pmem)
+{
+ int done;
+ struct tag_mem_range **a, **b;
+
+ if (!*pmem)
+ return;
+
+ do {
+ done = 1;
+ a = pmem, b = &(*pmem)->next;
+ while (*b) {
+ if ((*a)->addr > (*b)->addr) {
+ struct tag_mem_range *tmp;
+ tmp = (*b)->next;
+ (*b)->next = *a;
+ *a = *b;
+ *b = tmp;
+ done = 0;
+ }
+ a = &(*a)->next;
+ b = &(*a)->next;
+ }
+ } while (!done);
+}
+
+/*
+ * Find a free memory region large enough for storing the
+ * bootmem bitmap.
+ */
+static unsigned long __init
+find_bootmap_pfn(const struct tag_mem_range *mem)
+{
+ unsigned long bootmap_pages, bootmap_len;
+ unsigned long node_pages = PFN_UP(mem->size);
+ unsigned long bootmap_addr = mem->addr;
+ struct tag_mem_range *reserved = mem_reserved;
+ struct tag_mem_range *ramdisk = mem_ramdisk;
+ unsigned long kern_start = virt_to_phys(_stext);
+ unsigned long kern_end = virt_to_phys(_end);
+
+ bootmap_pages = bootmem_bootmap_pages(node_pages);
+ bootmap_len = bootmap_pages << PAGE_SHIFT;
+
+ /*
+ * Find a large enough region without reserved pages for
+ * storing the bootmem bitmap. We can take advantage of the
+ * fact that all lists have been sorted.
+ *
+ * We have to check explicitly reserved regions as well as the
+ * kernel image and any RAMDISK images...
+ *
+ * Oh, and we have to make sure we don't overwrite the taglist
+ * since we're going to use it until the bootmem allocator is
+ * fully up and running.
+ */
+ while (1) {
+ if ((bootmap_addr < kern_end) &&
+ ((bootmap_addr + bootmap_len) > kern_start))
+ bootmap_addr = kern_end;
+
+ while (reserved &&
+ (bootmap_addr >= (reserved->addr + reserved->size)))
+ reserved = reserved->next;
+
+ if (reserved &&
+ ((bootmap_addr + bootmap_len) >= reserved->addr)) {
+ bootmap_addr = reserved->addr + reserved->size;
+ continue;
+ }
+
+ while (ramdisk &&
+ (bootmap_addr >= (ramdisk->addr + ramdisk->size)))
+ ramdisk = ramdisk->next;
+
+ if (!ramdisk ||
+ ((bootmap_addr + bootmap_len) < ramdisk->addr))
+ break;
+
+ bootmap_addr = ramdisk->addr + ramdisk->size;
+ }
+
+ if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size))
+ return ~0UL;
+
+ return PFN_UP(bootmap_addr);
+}
+
+void __init setup_bootmem(void)
+{
+ unsigned bootmap_size;
+ unsigned long first_pfn, bootmap_pfn, pages;
+ unsigned long max_pfn, max_low_pfn;
+ unsigned long kern_start = virt_to_phys(_stext);
+ unsigned long kern_end = virt_to_phys(_end);
+ unsigned node = 0;
+ struct tag_mem_range *bank, *res;
+
+ sort_mem_list(&mem_phys);
+ sort_mem_list(&mem_reserved);
+
+ print_memory_map("Physical memory", mem_phys);
+ print_memory_map("Reserved memory", mem_reserved);
+
+ nodes_clear(node_online_map);
+
+ if (mem_ramdisk) {
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start = __va(mem_ramdisk->addr);
+ initrd_end = initrd_start + mem_ramdisk->size;
+
+ print_memory_map("RAMDISK images", mem_ramdisk);
+ if (mem_ramdisk->next)
+ printk(KERN_WARNING
+ "Warning: Only the first RAMDISK image "
+ "will be used\n");
+ sort_mem_list(&mem_ramdisk);
+#else
+ printk(KERN_WARNING "RAM disk image present, but "
+ "no initrd support in kernel!\n");
+#endif
+ }
+
+ if (mem_phys->next)
+ printk(KERN_WARNING "Only using first memory bank\n");
+
+ for (bank = mem_phys; bank; bank = NULL) {
+ first_pfn = PFN_UP(bank->addr);
+ max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size);
+ bootmap_pfn = find_bootmap_pfn(bank);
+ if (bootmap_pfn > max_pfn)
+ panic("No space for bootmem bitmap!\n");
+
+ if (max_low_pfn > MAX_LOWMEM_PFN) {
+ max_low_pfn = MAX_LOWMEM_PFN;
+#ifndef CONFIG_HIGHMEM
+ /*
+ * Lowmem is memory that can be addressed
+ * directly through P1/P2
+ */
+ printk(KERN_WARNING
+ "Node %u: Only %ld MiB of memory will be used.\n",
+ node, MAX_LOWMEM >> 20);
+ printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+#else
+#error HIGHMEM is not supported by AVR32 yet
+#endif
+ }
+
+ /* Initialize the boot-time allocator with low memory only. */
+ bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn,
+ first_pfn, max_low_pfn);
+
+ printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n",
+ node, NODE_DATA(node)->bdata,
+ NODE_DATA(node)->bdata->node_bootmem_map);
+
+ /*
+ * Register fully available RAM pages with the bootmem
+ * allocator.
+ */
+ pages = max_low_pfn - first_pfn;
+ free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn),
+ PFN_PHYS(pages));
+
+ /*
+ * Reserve space for the kernel image (if present in
+ * this node)...
+ */
+ if ((kern_start >= PFN_PHYS(first_pfn)) &&
+ (kern_start < PFN_PHYS(max_pfn))) {
+ printk("Node %u: Kernel image %08lx - %08lx\n",
+ node, kern_start, kern_end);
+ reserve_bootmem_node(NODE_DATA(node), kern_start,
+ kern_end - kern_start);
+ }
+
+ /* ...the bootmem bitmap... */
+ reserve_bootmem_node(NODE_DATA(node),
+ PFN_PHYS(bootmap_pfn),
+ bootmap_size);
+
+ /* ...any RAMDISK images... */
+ for (res = mem_ramdisk; res; res = res->next) {
+ if (res->addr > PFN_PHYS(max_pfn))
+ break;
+
+ if (res->addr >= PFN_PHYS(first_pfn)) {
+ printk("Node %u: RAMDISK %08lx - %08lx\n",
+ node,
+ (unsigned long)res->addr,
+ (unsigned long)(res->addr + res->size));
+ reserve_bootmem_node(NODE_DATA(node),
+ res->addr, res->size);
+ }
+ }
+
+ /* ...and any other reserved regions. */
+ for (res = mem_reserved; res; res = res->next) {
+ if (res->addr > PFN_PHYS(max_pfn))
+ break;
+
+ if (res->addr >= PFN_PHYS(first_pfn)) {
+ printk("Node %u: Reserved %08lx - %08lx\n",
+ node,
+ (unsigned long)res->addr,
+ (unsigned long)(res->addr + res->size));
+ reserve_bootmem_node(NODE_DATA(node),
+ res->addr, res->size);
+ }
+ }
+
+ node_set_online(node);
+ }
+}
+
+/*
+ * paging_init() sets up the page tables
+ *
+ * This routine also unmaps the page at virtual kernel address 0, so
+ * that we can trap those pesky NULL-reference errors in the kernel.
+ */
+void __init paging_init(void)
+{
+ extern unsigned long _evba;
+ void *zero_page;
+ int nid;
+
+ /*
+ * Make sure we can handle exceptions before enabling
+ * paging. Not that we should ever _get_ any exceptions this
+ * early, but you never know...
+ */
+ printk("Exception vectors start at %p\n", &_evba);
+ sysreg_write(EVBA, (unsigned long)&_evba);
+
+ /*
+ * Since we are ready to handle exceptions now, we should let
+ * the CPU generate them...
+ */
+ __asm__ __volatile__ ("csrf %0" : : "i"(SR_EM_BIT));
+
+ /*
+ * Allocate the zero page. The allocator will panic if it
+ * can't satisfy the request, so no need to check.
+ */
+ zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0),
+ PAGE_SIZE);
+
+ {
+ pgd_t *pg_dir;
+ int i;
+
+ pg_dir = swapper_pg_dir;
+ sysreg_write(PTBR, (unsigned long)pg_dir);
+
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pgd_val(pg_dir[i]) = 0;
+
+ enable_mmu();
+ printk ("CPU: Paging enabled\n");
+ }
+
+ for_each_online_node(nid) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ unsigned long zones_size[MAX_NR_ZONES];
+ unsigned long low, start_pfn;
+
+ start_pfn = pgdat->bdata->node_boot_start;
+ start_pfn >>= PAGE_SHIFT;
+ low = pgdat->bdata->node_low_pfn;
+
+ memset(zones_size, 0, sizeof(zones_size));
+ zones_size[ZONE_NORMAL] = low - start_pfn;
+
+ printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
+ nid, start_pfn, low);
+
+ free_area_init_node(nid, pgdat, zones_size, start_pfn, NULL);
+
+ printk("Node %u: mem_map starts at %p\n",
+ pgdat->node_id, pgdat->node_mem_map);
+ }
+
+ mem_map = NODE_DATA(0)->node_mem_map;
+
+ memset(zero_page, 0, PAGE_SIZE);
+ empty_zero_page = virt_to_page(zero_page);
+ flush_dcache_page(empty_zero_page);
+}
+
+void __init mem_init(void)
+{
+ int codesize, reservedpages, datasize, initsize;
+ int nid, i;
+
+ reservedpages = 0;
+ high_memory = NULL;
+
+ /* this will put all low memory onto the freelists */
+ for_each_online_node(nid) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ unsigned long node_pages = 0;
+ void *node_high_memory;
+
+ num_physpages += pgdat->node_present_pages;
+
+ if (pgdat->node_spanned_pages != 0)
+ node_pages = free_all_bootmem_node(pgdat);
+
+ totalram_pages += node_pages;
+
+ for (i = 0; i < node_pages; i++)
+ if (PageReserved(pgdat->node_mem_map + i))
+ reservedpages++;
+
+ node_high_memory = (void *)((pgdat->node_start_pfn
+ + pgdat->node_spanned_pages)
+ << PAGE_SHIFT);
+ if (node_high_memory > high_memory)
+ high_memory = node_high_memory;
+ }
+
+ max_mapnr = MAP_NR(high_memory);
+
+ codesize = (unsigned long)_etext - (unsigned long)_text;
+ datasize = (unsigned long)_edata - (unsigned long)_data;
+ initsize = (unsigned long)__init_end - (unsigned long)__init_begin;
+
+ printk ("Memory: %luk/%luk available (%dk kernel code, "
+ "%dk reserved, %dk data, %dk init)\n",
+ (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10),
+ totalram_pages << (PAGE_SHIFT - 10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT - 10),
+ datasize >> 10,
+ initsize >> 10);
+}
+
+static inline void free_area(unsigned long addr, unsigned long end, char *s)
+{
+ unsigned int size = (end - addr) >> 10;
+
+ for (; addr < end; addr += PAGE_SIZE) {
+ struct page *page = virt_to_page(addr);
+ ClearPageReserved(page);
+ init_page_count(page);
+ free_page(addr);
+ totalram_pages++;
+ }
+
+ if (size && s)
+ printk(KERN_INFO "Freeing %s memory: %dK (%lx - %lx)\n",
+ s, size, end - (size << 10), end);
+}
+
+void free_initmem(void)
+{
+ free_area((unsigned long)__init_begin, (unsigned long)__init_end,
+ "init");
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int keep_initrd;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ if (!keep_initrd)
+ free_area(start, end, "initrd");
+}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+ keep_initrd = 1;
+ return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
+#endif
diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c
new file mode 100644
index 00000000000..536021877df
--- /dev/null
+++ b/arch/avr32/mm/ioremap.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/vmalloc.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/addrspace.h>
+
+static inline int remap_area_pte(pte_t *pte, unsigned long address,
+ unsigned long end, unsigned long phys_addr,
+ pgprot_t prot)
+{
+ unsigned long pfn;
+
+ pfn = phys_addr >> PAGE_SHIFT;
+ do {
+ WARN_ON(!pte_none(*pte));
+
+ set_pte(pte, pfn_pte(pfn, prot));
+ address += PAGE_SIZE;
+ pfn++;
+ pte++;
+ } while (address && (address < end));
+
+ return 0;
+}
+
+static inline int remap_area_pmd(pmd_t *pmd, unsigned long address,
+ unsigned long end, unsigned long phys_addr,
+ pgprot_t prot)
+{
+ unsigned long next;
+
+ phys_addr -= address;
+
+ do {
+ pte_t *pte = pte_alloc_kernel(pmd, address);
+ if (!pte)
+ return -ENOMEM;
+
+ next = (address + PMD_SIZE) & PMD_MASK;
+ if (remap_area_pte(pte, address, next,
+ address + phys_addr, prot))
+ return -ENOMEM;
+
+ address = next;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+static int remap_area_pud(pud_t *pud, unsigned long address,
+ unsigned long end, unsigned long phys_addr,
+ pgprot_t prot)
+{
+ unsigned long next;
+
+ phys_addr -= address;
+
+ do {
+ pmd_t *pmd = pmd_alloc(&init_mm, pud, address);
+ if (!pmd)
+ return -ENOMEM;
+ next = (address + PUD_SIZE) & PUD_MASK;
+ if (remap_area_pmd(pmd, address, next,
+ phys_addr + address, prot))
+ return -ENOMEM;
+
+ address = next;
+ pud++;
+ } while (address && address < end);
+
+ return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ size_t size, pgprot_t prot)
+{
+ unsigned long end = address + size;
+ unsigned long next;
+ pgd_t *pgd;
+ int err = 0;
+
+ phys_addr -= address;
+
+ pgd = pgd_offset_k(address);
+ flush_cache_all();
+ BUG_ON(address >= end);
+
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pud_t *pud = pud_alloc(&init_mm, pgd, address);
+
+ err = -ENOMEM;
+ if (!pud)
+ break;
+
+ next = (address + PGDIR_SIZE) & PGDIR_MASK;
+ if (next < address || next > end)
+ next = end;
+ err = remap_area_pud(pud, address, next,
+ phys_addr + address, prot);
+ if (err)
+ break;
+
+ address = next;
+ pgd++;
+ } while (address && (address < end));
+
+ spin_unlock(&init_mm.page_table_lock);
+ flush_tlb_all();
+ return err;
+}
+
+/*
+ * Re-map an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access physical
+ * memory directly.
+ */
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+ unsigned long flags)
+{
+ void *addr;
+ struct vm_struct *area;
+ unsigned long offset, last_addr;
+ pgprot_t prot;
+
+ /*
+ * Check if we can simply use the P4 segment. This area is
+ * uncacheable, so if caching/buffering is requested, we can't
+ * use it.
+ */
+ if ((phys_addr >= P4SEG) && (flags == 0))
+ return (void __iomem *)phys_addr;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * XXX: When mapping regular RAM, we'd better make damn sure
+ * it's never used for anything else. But this is really the
+ * caller's responsibility...
+ */
+ if (PHYSADDR(P2SEGADDR(phys_addr)) == phys_addr)
+ return (void __iomem *)P2SEGADDR(phys_addr);
+
+ /* Mappings have to be page-aligned */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
+ | _PAGE_ACCESSED | _PAGE_TYPE_SMALL | flags);
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ area->phys_addr = phys_addr;
+ addr = area->addr;
+ if (remap_area_pages((unsigned long)addr, phys_addr, size, prot)) {
+ vunmap(addr);
+ return NULL;
+ }
+
+ return (void __iomem *)(offset + (char *)addr);
+}
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem *addr)
+{
+ struct vm_struct *p;
+
+ if ((unsigned long)addr >= P4SEG)
+ return;
+
+ p = remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
+ if (unlikely(!p)) {
+ printk (KERN_ERR "iounmap: bad address %p\n", addr);
+ return;
+ }
+
+ kfree (p);
+}
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c
new file mode 100644
index 00000000000..7b073052203
--- /dev/null
+++ b/arch/avr32/mm/tlb.c
@@ -0,0 +1,380 @@
+/*
+ * AVR32 TLB operations
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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/mm.h>
+
+#include <asm/mmu_context.h>
+
+#define _TLBEHI_I 0x100
+
+void show_dtlb_entry(unsigned int index)
+{
+ unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mmucr_save = sysreg_read(MMUCR);
+ tlbehi_save = sysreg_read(TLBEHI);
+ mmucr = mmucr_save & 0x13;
+ mmucr |= index << 14;
+ sysreg_write(MMUCR, mmucr);
+
+ asm volatile("tlbr" : : : "memory");
+ cpu_sync_pipeline();
+
+ tlbehi = sysreg_read(TLBEHI);
+ tlbelo = sysreg_read(TLBELO);
+
+ printk("%2u: %c %c %02x %05x %05x %o %o %c %c %c %c\n",
+ index,
+ (tlbehi & 0x200)?'1':'0',
+ (tlbelo & 0x100)?'1':'0',
+ (tlbehi & 0xff),
+ (tlbehi >> 12), (tlbelo >> 12),
+ (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
+ (tlbelo & 0x200)?'1':'0',
+ (tlbelo & 0x080)?'1':'0',
+ (tlbelo & 0x001)?'1':'0',
+ (tlbelo & 0x002)?'1':'0');
+
+ sysreg_write(MMUCR, mmucr_save);
+ sysreg_write(TLBEHI, tlbehi_save);
+ cpu_sync_pipeline();
+ local_irq_restore(flags);
+}
+
+void dump_dtlb(void)
+{
+ unsigned int i;
+
+ printk("ID V G ASID VPN PFN AP SZ C B W D\n");
+ for (i = 0; i < 32; i++)
+ show_dtlb_entry(i);
+}
+
+static unsigned long last_mmucr;
+
+static inline void set_replacement_pointer(unsigned shift)
+{
+ unsigned long mmucr, mmucr_save;
+
+ mmucr = mmucr_save = sysreg_read(MMUCR);
+
+ /* Does this mapping already exist? */
+ __asm__ __volatile__(
+ " tlbs\n"
+ " mfsr %0, %1"
+ : "=r"(mmucr)
+ : "i"(SYSREG_MMUCR));
+
+ if (mmucr & SYSREG_BIT(MMUCR_N)) {
+ /* Not found -- pick a not-recently-accessed entry */
+ unsigned long rp;
+ unsigned long tlbar = sysreg_read(TLBARLO);
+
+ rp = 32 - fls(tlbar);
+ if (rp == 32) {
+ rp = 0;
+ sysreg_write(TLBARLO, -1L);
+ }
+
+ mmucr &= 0x13;
+ mmucr |= (rp << shift);
+
+ sysreg_write(MMUCR, mmucr);
+ }
+
+ last_mmucr = mmucr;
+}
+
+static void update_dtlb(unsigned long address, pte_t pte, unsigned long asid)
+{
+ unsigned long vpn;
+
+ vpn = (address & MMU_VPN_MASK) | _TLBEHI_VALID | asid;
+ sysreg_write(TLBEHI, vpn);
+ cpu_sync_pipeline();
+
+ set_replacement_pointer(14);
+
+ sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);
+
+ /* Let's go */
+ asm volatile("nop\n\ttlbw" : : : "memory");
+ cpu_sync_pipeline();
+}
+
+void update_mmu_cache(struct vm_area_struct *vma,
+ unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+
+ /* ptrace may call this routine */
+ if (vma && current->active_mm != vma->vm_mm)
+ return;
+
+ local_irq_save(flags);
+ update_dtlb(address, pte, get_asid());
+ local_irq_restore(flags);
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+ unsigned long mmucr, tlbehi;
+
+ page |= asid;
+ sysreg_write(TLBEHI, page);
+ cpu_sync_pipeline();
+ asm volatile("tlbs");
+ mmucr = sysreg_read(MMUCR);
+
+ if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
+ unsigned long tlbarlo;
+ unsigned long entry;
+
+ /* Clear the "valid" bit */
+ tlbehi = sysreg_read(TLBEHI);
+ tlbehi &= ~_TLBEHI_VALID;
+ sysreg_write(TLBEHI, tlbehi);
+ cpu_sync_pipeline();
+
+ /* mark the entry as "not accessed" */
+ entry = (mmucr >> 14) & 0x3f;
+ tlbarlo = sysreg_read(TLBARLO);
+ tlbarlo |= (0x80000000 >> entry);
+ sysreg_write(TLBARLO, tlbarlo);
+
+ /* update the entry with valid bit clear */
+ asm volatile("tlbw");
+ cpu_sync_pipeline();
+ }
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
+ unsigned long flags, asid;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
+ page &= PAGE_MASK;
+
+ local_irq_save(flags);
+ if (vma->vm_mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+
+ __flush_tlb_page(asid, page);
+
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (mm->context != NO_CONTEXT) {
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
+ mm->context = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ } else {
+ unsigned long asid = mm->context & MMU_CONTEXT_ASID_MASK;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ if (mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * TODO: If this is only called for addresses > TASK_SIZE, we can probably
+ * skip the ASID stuff and just use the Global bit...
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
+ flush_tlb_all();
+ } else {
+ unsigned long asid = init_mm.context & MMU_CONTEXT_ASID_MASK;
+ unsigned long saved_asid = get_asid();
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ set_asid(asid);
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ /* Invalidate all TLB entries of this process by getting a new ASID */
+ if (mm->context != NO_CONTEXT) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mm->context = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_all(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sysreg_write(MMUCR, sysreg_read(MMUCR) | SYSREG_BIT(MMUCR_I));
+ local_irq_restore(flags);
+}
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+static void *tlb_start(struct seq_file *tlb, loff_t *pos)
+{
+ static unsigned long tlb_index;
+
+ if (*pos >= 32)
+ return NULL;
+
+ tlb_index = 0;
+ return &tlb_index;
+}
+
+static void *tlb_next(struct seq_file *tlb, void *v, loff_t *pos)
+{
+ unsigned long *index = v;
+
+ if (*index >= 31)
+ return NULL;
+
+ ++*pos;
+ ++*index;
+ return index;
+}
+
+static void tlb_stop(struct seq_file *tlb, void *v)
+{
+
+}
+
+static int tlb_show(struct seq_file *tlb, void *v)
+{
+ unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+ unsigned long flags;
+ unsigned long *index = v;
+
+ if (*index == 0)
+ seq_puts(tlb, "ID V G ASID VPN PFN AP SZ C B W D\n");
+
+ BUG_ON(*index >= 32);
+
+ local_irq_save(flags);
+ mmucr_save = sysreg_read(MMUCR);
+ tlbehi_save = sysreg_read(TLBEHI);
+ mmucr = mmucr_save & 0x13;
+ mmucr |= *index << 14;
+ sysreg_write(MMUCR, mmucr);
+
+ asm volatile("tlbr" : : : "memory");
+ cpu_sync_pipeline();
+
+ tlbehi = sysreg_read(TLBEHI);
+ tlbelo = sysreg_read(TLBELO);
+
+ sysreg_write(MMUCR, mmucr_save);
+ sysreg_write(TLBEHI, tlbehi_save);
+ cpu_sync_pipeline();
+ local_irq_restore(flags);
+
+ seq_printf(tlb, "%2lu: %c %c %02x %05x %05x %o %o %c %c %c %c\n",
+ *index,
+ (tlbehi & 0x200)?'1':'0',
+ (tlbelo & 0x100)?'1':'0',
+ (tlbehi & 0xff),
+ (tlbehi >> 12), (tlbelo >> 12),
+ (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
+ (tlbelo & 0x200)?'1':'0',
+ (tlbelo & 0x080)?'1':'0',
+ (tlbelo & 0x001)?'1':'0',
+ (tlbelo & 0x002)?'1':'0');
+
+ return 0;
+}
+
+static struct seq_operations tlb_ops = {
+ .start = tlb_start,
+ .next = tlb_next,
+ .stop = tlb_stop,
+ .show = tlb_show,
+};
+
+static int tlb_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &tlb_ops);
+}
+
+static struct file_operations proc_tlb_operations = {
+ .open = tlb_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init proctlb_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_entry("tlb", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_tlb_operations;
+ return 0;
+}
+late_initcall(proctlb_init);
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index a601a17cf56..f7b171b92ea 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -27,7 +27,11 @@ config GENERIC_CALIBRATE_DELAY
config GENERIC_HARDIRQS
bool
- default n
+ default y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+ bool
+ default y
config GENERIC_TIME
bool
@@ -251,6 +255,12 @@ config MB93091_NO_MB
endchoice
endif
+config FUJITSU_MB93493
+ bool "MB93493 Multimedia chip"
+ help
+ Select this option if the MB93493 multimedia chip is going to be
+ used.
+
choice
prompt "GP-Relative data support"
default GPREL_DATA_8
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index 5a827b349b5..32db3499c46 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -10,15 +10,14 @@ extra-y:= head.o init_task.o vmlinux.lds
obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
process.o traps.o ptrace.o signal.o dma.o \
sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
- debug-stub.o irq.o irq-routing.o sleep.o uaccess.o
+ debug-stub.o irq.o sleep.o uaccess.o
obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o
-obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o
-obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
obj-$(CONFIG_PM) += pm.o cmode.o
obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
+obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
obj-$(CONFIG_SYSCTL) += sysctl.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index 1381abcd5cc..369bc0a7443 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -24,7 +24,6 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
@@ -33,83 +32,131 @@
#define __get_IFR() ({ __reg16(0xffc0000c); })
#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
-static void frv_fpga_doirq(struct irq_source *source);
-static void frv_fpga_control(struct irq_group *group, int irq, int on);
-/*****************************************************************************/
/*
- * FPGA IRQ multiplexor
+ * on-motherboard FPGA PIC operations
*/
-static struct irq_source frv_fpga[4] = {
-#define __FPGA(X, M) \
- [X] = { \
- .muxname = "fpga."#X, \
- .irqmask = M, \
- .doirq = frv_fpga_doirq, \
- }
+static void frv_fpga_mask(unsigned int irq)
+{
+ uint16_t imr = __get_IMR();
- __FPGA(0, 0x0028),
- __FPGA(1, 0x0050),
- __FPGA(2, 0x1c00),
- __FPGA(3, 0x6386),
-};
+ imr |= 1 << (irq - IRQ_BASE_FPGA);
-static struct irq_group frv_fpga_irqs = {
- .first_irq = IRQ_BASE_FPGA,
- .control = frv_fpga_control,
- .sources = {
- [ 1] = &frv_fpga[3],
- [ 2] = &frv_fpga[3],
- [ 3] = &frv_fpga[0],
- [ 4] = &frv_fpga[1],
- [ 5] = &frv_fpga[0],
- [ 6] = &frv_fpga[1],
- [ 7] = &frv_fpga[3],
- [ 8] = &frv_fpga[3],
- [ 9] = &frv_fpga[3],
- [10] = &frv_fpga[2],
- [11] = &frv_fpga[2],
- [12] = &frv_fpga[2],
- [13] = &frv_fpga[3],
- [14] = &frv_fpga[3],
- },
-};
+ __set_IMR(imr);
+}
+static void frv_fpga_ack(unsigned int irq)
+{
+ __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+}
-static void frv_fpga_control(struct irq_group *group, int index, int on)
+static void frv_fpga_mask_ack(unsigned int irq)
{
uint16_t imr = __get_IMR();
- if (on)
- imr &= ~(1 << index);
- else
- imr |= 1 << index;
+ imr |= 1 << (irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+
+ __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+}
+
+static void frv_fpga_unmask(unsigned int irq)
+{
+ uint16_t imr = __get_IMR();
+
+ imr &= ~(1 << (irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
-static void frv_fpga_doirq(struct irq_source *source)
+static struct irq_chip frv_fpga_pic = {
+ .name = "mb93091",
+ .ack = frv_fpga_ack,
+ .mask = frv_fpga_mask,
+ .mask_ack = frv_fpga_mask_ack,
+ .unmask = frv_fpga_unmask,
+};
+
+/*
+ * FPGA PIC interrupt handler
+ */
+static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
{
- uint16_t mask, imr;
+ uint16_t imr, mask = (unsigned long) _mask;
imr = __get_IMR();
- mask = source->irqmask & ~imr & __get_IFR();
- if (mask) {
- __set_IMR(imr | mask);
- __clr_IFR(mask);
- distribute_irqs(&frv_fpga_irqs, mask);
- __set_IMR(imr);
+ mask = mask & ~imr & __get_IFR();
+
+ /* poll all the triggered IRQs */
+ while (mask) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
+ irq = 31 - irq;
+ mask &= ~(1 << irq);
+
+ generic_handle_irq(IRQ_BASE_FPGA + irq, regs);
}
+
+ return IRQ_HANDLED;
}
+/*
+ * define an interrupt action for each FPGA PIC output
+ * - use dev_id to indicate the FPGA PIC input to output mappings
+ */
+static struct irqaction fpga_irq[4] = {
+ [0] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "fpga.0",
+ .dev_id = (void *) 0x0028UL,
+ },
+ [1] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "fpga.1",
+ .dev_id = (void *) 0x0050UL,
+ },
+ [2] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "fpga.2",
+ .dev_id = (void *) 0x1c00UL,
+ },
+ [3] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "fpga.3",
+ .dev_id = (void *) 0x6386UL,
+ }
+};
+
+/*
+ * initialise the motherboard FPGA's PIC
+ */
void __init fpga_init(void)
{
+ int irq;
+
+ /* all PIC inputs are all set to be low-level driven, apart from the
+ * NMI button (15) which is fixed at falling-edge
+ */
__set_IMR(0x7ffe);
__clr_IFR(0x0000);
- frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0);
- frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1);
- frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2);
- frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3);
- frv_irq_set_group(&frv_fpga_irqs);
+ for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
+ set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
+
+ set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
+
+ /* the FPGA drives the first four external IRQ inputs on the CPU PIC */
+ setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
+ setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
+ setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
+ setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
}
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index 48b2a642088..a43a2215895 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -1,6 +1,6 @@
/* irq-mb93093.c: MB93093 FPGA interrupt handling
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
@@ -33,66 +32,102 @@
#define __get_IFR() ({ __reg16(0x02); })
#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0)
-static void frv_fpga_doirq(struct irq_source *source);
-static void frv_fpga_control(struct irq_group *group, int irq, int on);
-
-/*****************************************************************************/
/*
- * FPGA IRQ multiplexor
+ * off-CPU FPGA PIC operations
*/
-static struct irq_source frv_fpga[4] = {
-#define __FPGA(X, M) \
- [X] = { \
- .muxname = "fpga."#X, \
- .irqmask = M, \
- .doirq = frv_fpga_doirq, \
- }
+static void frv_fpga_mask(unsigned int irq)
+{
+ uint16_t imr = __get_IMR();
- __FPGA(0, 0x0700),
-};
+ imr |= 1 << (irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+}
-static struct irq_group frv_fpga_irqs = {
- .first_irq = IRQ_BASE_FPGA,
- .control = frv_fpga_control,
- .sources = {
- [ 8] = &frv_fpga[0],
- [ 9] = &frv_fpga[0],
- [10] = &frv_fpga[0],
- },
-};
+static void frv_fpga_ack(unsigned int irq)
+{
+ __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+}
+
+static void frv_fpga_mask_ack(unsigned int irq)
+{
+ uint16_t imr = __get_IMR();
+ imr |= 1 << (irq - IRQ_BASE_FPGA);
+ __set_IMR(imr);
+
+ __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+}
-static void frv_fpga_control(struct irq_group *group, int index, int on)
+static void frv_fpga_unmask(unsigned int irq)
{
uint16_t imr = __get_IMR();
- if (on)
- imr &= ~(1 << index);
- else
- imr |= 1 << index;
+ imr &= ~(1 << (irq - IRQ_BASE_FPGA));
__set_IMR(imr);
}
-static void frv_fpga_doirq(struct irq_source *source)
+static struct irq_chip frv_fpga_pic = {
+ .name = "mb93093",
+ .ack = frv_fpga_ack,
+ .mask = frv_fpga_mask,
+ .mask_ack = frv_fpga_mask_ack,
+ .unmask = frv_fpga_unmask,
+ .end = frv_fpga_end,
+};
+
+/*
+ * FPGA PIC interrupt handler
+ */
+static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
{
- uint16_t mask, imr;
+ uint16_t imr, mask = (unsigned long) _mask;
imr = __get_IMR();
- mask = source->irqmask & ~imr & __get_IFR();
- if (mask) {
- __set_IMR(imr | mask);
- __clr_IFR(mask);
- distribute_irqs(&frv_fpga_irqs, mask);
- __set_IMR(imr);
+ mask = mask & ~imr & __get_IFR();
+
+ /* poll all the triggered IRQs */
+ while (mask) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
+ irq = 31 - irq;
+ mask &= ~(1 << irq);
+
+ generic_irq_handle(IRQ_BASE_FPGA + irq, regs);
}
+
+ return IRQ_HANDLED;
}
+/*
+ * define an interrupt action for each FPGA PIC output
+ * - use dev_id to indicate the FPGA PIC input to output mappings
+ */
+static struct irqaction fpga_irq[1] = {
+ [0] = {
+ .handler = fpga_interrupt,
+ .flags = IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "fpga.0",
+ .dev_id = (void *) 0x0700UL,
+ }
+};
+
+/*
+ * initialise the motherboard FPGA's PIC
+ */
void __init fpga_init(void)
{
+ int irq;
+
+ /* all PIC inputs are all set to be edge triggered */
__set_IMR(0x0700);
__clr_IFR(0x0000);
- frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2);
- frv_irq_set_group(&frv_fpga_irqs);
+ for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
+ set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
+
+ /* the FPGA drives external IRQ input #2 on the CPU PIC */
+ setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
}
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index 988d035640e..39c0188a349 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -1,6 +1,6 @@
/* irq-mb93493.c: MB93493 companion chip interrupt handler
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -24,84 +24,126 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#include <asm/mb93493-irqs.h>
+#include <asm/mb93493-regs.h>
-static void frv_mb93493_doirq(struct irq_source *source);
+#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))
+
+#define IRQ_ROUTING \
+ (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \
+ IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))
-/*****************************************************************************/
/*
- * MB93493 companion chip IRQ multiplexor
+ * daughter board PIC operations
+ * - there is no way to ACK interrupts in the MB93493 chip
*/
-static struct irq_source frv_mb93493[2] = {
- [0] = {
- .muxname = "mb93493.0",
- .muxdata = __region_CS3 + 0x3d0,
- .doirq = frv_mb93493_doirq,
- .irqmask = 0x0000,
- },
- [1] = {
- .muxname = "mb93493.1",
- .muxdata = __region_CS3 + 0x3d4,
- .doirq = frv_mb93493_doirq,
- .irqmask = 0x0000,
- },
-};
-
-static void frv_mb93493_control(struct irq_group *group, int index, int on)
+static void frv_mb93493_mask(unsigned int irq)
{
- struct irq_source *source;
uint32_t iqsr;
+ volatile void *piqsr;
- if ((frv_mb93493[0].irqmask & (1 << index)))
- source = &frv_mb93493[0];
+ if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+ piqsr = __addr_MB93493_IQSR(1);
else
- source = &frv_mb93493[1];
+ piqsr = __addr_MB93493_IQSR(0);
+
+ iqsr = readl(piqsr);
+ iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
+ writel(iqsr, piqsr);
+}
- iqsr = readl(source->muxdata);
- if (on)
- iqsr |= 1 << (index + 16);
+static void frv_mb93493_ack(unsigned int irq)
+{
+}
+
+static void frv_mb93493_unmask(unsigned int irq)
+{
+ uint32_t iqsr;
+ volatile void *piqsr;
+
+ if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+ piqsr = __addr_MB93493_IQSR(1);
else
- iqsr &= ~(1 << (index + 16));
+ piqsr = __addr_MB93493_IQSR(0);
- writel(iqsr, source->muxdata);
+ iqsr = readl(piqsr);
+ iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
+ writel(iqsr, piqsr);
}
-static struct irq_group frv_mb93493_irqs = {
- .first_irq = IRQ_BASE_MB93493,
- .control = frv_mb93493_control,
+static struct irq_chip frv_mb93493_pic = {
+ .name = "mb93093",
+ .ack = frv_mb93493_ack,
+ .mask = frv_mb93493_mask,
+ .mask_ack = frv_mb93493_mask,
+ .unmask = frv_mb93493_unmask,
};
-static void frv_mb93493_doirq(struct irq_source *source)
+/*
+ * MB93493 PIC interrupt handler
+ */
+static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs)
{
- uint32_t mask = readl(source->muxdata);
- mask = mask & (mask >> 16) & 0xffff;
+ volatile void *piqsr = _piqsr;
+ uint32_t iqsr;
- if (mask)
- distribute_irqs(&frv_mb93493_irqs, mask);
-}
+ iqsr = readl(piqsr);
+ iqsr = iqsr & (iqsr >> 16) & 0xffff;
-static void __init mb93493_irq_route(int irq, int source)
-{
- frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493);
- frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source];
+ /* poll all the triggered IRQs */
+ while (iqsr) {
+ int irq;
+
+ asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
+ irq = 31 - irq;
+ iqsr &= ~(1 << irq);
+
+ generic_handle_irq(IRQ_BASE_MB93493 + irq, regs);
+ }
+
+ return IRQ_HANDLED;
}
-void __init route_mb93493_irqs(void)
+/*
+ * define an interrupt action for each MB93493 PIC output
+ * - use dev_id to indicate the MB93493 PIC input to output mappings
+ */
+static struct irqaction mb93493_irq[2] = {
+ [0] = {
+ .handler = mb93493_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "mb93493.0",
+ .dev_id = (void *) __addr_MB93493_IQSR(0),
+ },
+ [1] = {
+ .handler = mb93493_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED,
+ .mask = CPU_MASK_NONE,
+ .name = "mb93493.1",
+ .dev_id = (void *) __addr_MB93493_IQSR(1),
+ }
+};
+
+/*
+ * initialise the motherboard MB93493's PIC
+ */
+void __init mb93493_init(void)
{
- frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0);
- frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1);
-
- frv_irq_set_group(&frv_mb93493_irqs);
-
- mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE);
- mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE);
- mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE);
- mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE);
- mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE);
- mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE);
- mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE);
- mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE);
- mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE);
- mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE);
+ int irq;
+
+ for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
+ set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);
+
+ /* the MB93493 drives external IRQ inputs on the CPU PIC */
+ setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
+ setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
}
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
deleted file mode 100644
index 53886adf47d..00000000000
--- a/arch/frv/kernel/irq-routing.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/* irq-routing.c: IRQ routing
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/sched.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/serial_reg.h>
-#include <asm/io.h>
-#include <asm/irq-routing.h>
-#include <asm/irc-regs.h>
-#include <asm/serial-regs.h>
-#include <asm/dma.h>
-
-struct irq_level frv_irq_levels[16] = {
- [0 ... 15] = {
- .lock = SPIN_LOCK_UNLOCKED,
- }
-};
-
-struct irq_group *irq_groups[NR_IRQ_GROUPS];
-
-extern struct irq_group frv_cpu_irqs;
-
-void __init frv_irq_route(struct irq_source *source, int irqlevel)
-{
- source->level = &frv_irq_levels[irqlevel];
- source->next = frv_irq_levels[irqlevel].sources;
- frv_irq_levels[irqlevel].sources = source;
-}
-
-void __init frv_irq_route_external(struct irq_source *source, int irq)
-{
- int irqlevel = 0;
-
- switch (irq) {
- case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break;
- case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break;
- case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break;
- case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break;
- case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break;
- case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break;
- case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break;
- case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break;
- default: BUG();
- }
-
- source->level = &frv_irq_levels[irqlevel];
- source->next = frv_irq_levels[irqlevel].sources;
- frv_irq_levels[irqlevel].sources = source;
-}
-
-void __init frv_irq_set_group(struct irq_group *group)
-{
- irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group;
-}
-
-void distribute_irqs(struct irq_group *group, unsigned long irqmask)
-{
- struct irqaction *action;
- int irq;
-
- while (irqmask) {
- asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask));
- if (irq < 0 || irq > 31)
- asm volatile("break");
- irq = 31 - irq;
-
- irqmask &= ~(1 << irq);
- action = group->actions[irq];
-
- irq += group->first_irq;
-
- if (action) {
- int status = 0;
-
-// if (!(action->flags & IRQF_DISABLED))
-// local_irq_enable();
-
- do {
- status |= action->flags;
- action->handler(irq, action->dev_id, __frame);
- action = action->next;
- } while (action);
-
- if (status & IRQF_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- local_irq_disable();
- }
- }
-}
-
-/*****************************************************************************/
-/*
- * CPU UART interrupts
- */
-static void frv_cpuuart_doirq(struct irq_source *source)
-{
-// uint8_t iir = readb(source->muxdata + UART_IIR * 8);
-// if ((iir & 0x0f) != UART_IIR_NO_INT)
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpuuart[2] = {
-#define __CPUUART(X, A) \
- [X] = { \
- .muxname = "uart", \
- .muxdata = (volatile void __iomem *)(unsigned long)A,\
- .irqmask = 1 << IRQ_CPU_UART##X, \
- .doirq = frv_cpuuart_doirq, \
- }
-
- __CPUUART(0, UART0_BASE),
- __CPUUART(1, UART1_BASE),
-};
-
-/*****************************************************************************/
-/*
- * CPU DMA interrupts
- */
-static void frv_cpudma_doirq(struct irq_source *source)
-{
- uint32_t cstr = readl(source->muxdata + DMAC_CSTRx);
- if (cstr & DMAC_CSTRx_INT)
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpudma[8] = {
-#define __CPUDMA(X, A) \
- [X] = { \
- .muxname = "dma", \
- .muxdata = (volatile void __iomem *)(unsigned long)A,\
- .irqmask = 1 << IRQ_CPU_DMA##X, \
- .doirq = frv_cpudma_doirq, \
- }
-
- __CPUDMA(0, 0xfe000900),
- __CPUDMA(1, 0xfe000980),
- __CPUDMA(2, 0xfe000a00),
- __CPUDMA(3, 0xfe000a80),
- __CPUDMA(4, 0xfe001000),
- __CPUDMA(5, 0xfe001080),
- __CPUDMA(6, 0xfe001100),
- __CPUDMA(7, 0xfe001180),
-};
-
-/*****************************************************************************/
-/*
- * CPU timer interrupts - can't tell whether they've generated an interrupt or not
- */
-static void frv_cputimer_doirq(struct irq_source *source)
-{
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cputimer[3] = {
-#define __CPUTIMER(X) \
- [X] = { \
- .muxname = "timer", \
- .muxdata = NULL, \
- .irqmask = 1 << IRQ_CPU_TIMER##X, \
- .doirq = frv_cputimer_doirq, \
- }
-
- __CPUTIMER(0),
- __CPUTIMER(1),
- __CPUTIMER(2),
-};
-
-/*****************************************************************************/
-/*
- * external CPU interrupts - can't tell directly whether they've generated an interrupt or not
- */
-static void frv_cpuexternal_doirq(struct irq_source *source)
-{
- distribute_irqs(&frv_cpu_irqs, source->irqmask);
-}
-
-struct irq_source frv_cpuexternal[8] = {
-#define __CPUEXTERNAL(X) \
- [X] = { \
- .muxname = "ext", \
- .muxdata = NULL, \
- .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \
- .doirq = frv_cpuexternal_doirq, \
- }
-
- __CPUEXTERNAL(0),
- __CPUEXTERNAL(1),
- __CPUEXTERNAL(2),
- __CPUEXTERNAL(3),
- __CPUEXTERNAL(4),
- __CPUEXTERNAL(5),
- __CPUEXTERNAL(6),
- __CPUEXTERNAL(7),
-};
-
-#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
-
-struct irq_group frv_cpu_irqs = {
- .sources = {
- [IRQ_CPU_UART0] = &frv_cpuuart[0],
- [IRQ_CPU_UART1] = &frv_cpuuart[1],
- [IRQ_CPU_TIMER0] = &frv_cputimer[0],
- [IRQ_CPU_TIMER1] = &frv_cputimer[1],
- [IRQ_CPU_TIMER2] = &frv_cputimer[2],
- [IRQ_CPU_DMA0] = &frv_cpudma[0],
- [IRQ_CPU_DMA1] = &frv_cpudma[1],
- [IRQ_CPU_DMA2] = &frv_cpudma[2],
- [IRQ_CPU_DMA3] = &frv_cpudma[3],
- [IRQ_CPU_DMA4] = &frv_cpudma[4],
- [IRQ_CPU_DMA5] = &frv_cpudma[5],
- [IRQ_CPU_DMA6] = &frv_cpudma[6],
- [IRQ_CPU_DMA7] = &frv_cpudma[7],
- [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0],
- [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1],
- [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2],
- [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3],
- [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4],
- [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5],
- [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6],
- [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7],
- },
-};
-
-/*****************************************************************************/
-/*
- * route the CPU's interrupt sources
- */
-void __init route_cpu_irqs(void)
-{
- frv_irq_set_group(&frv_cpu_irqs);
-
- __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */
- __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */
-
- /* route UART and error interrupts */
- frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL);
- frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL);
-
- set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
-
- /* route DMA channel interrupts */
- frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL);
- frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL);
- frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL);
- frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL);
- frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL);
- frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL);
- frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL);
- frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL);
-
- set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL);
- set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL);
-
- /* route timer interrupts */
- frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL);
- frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL);
- frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL);
-
- set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
-
- /* route external interrupts */
- frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL);
- frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL);
- frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL);
- frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL);
- frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL);
- frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL);
- frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL);
- frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL);
-
- set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL);
- set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL);
-
-#if defined(CONFIG_MB93091_VDK)
- __set_TM1(0x55550000); /* XIRQ7-0 all active low */
-#elif defined(CONFIG_MB93093_PDK)
- __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
-#else
-#error dont know external IRQ trigger levels for this setup
-#endif
-
-} /* end route_cpu_irqs() */
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 08967010be0..5ac041c7c0a 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -1,6 +1,6 @@
/* irq.c: FRV IRQ handling
*
- * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -9,13 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-/*
- * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
- *
- * IRQs are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -43,19 +36,16 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
-#include <asm/irq-routing.h>
#include <asm/gdb-stub.h>
-extern void __init fpga_init(void);
-extern void __init route_mb93493_irqs(void);
-
-static void register_irq_proc (unsigned int irq);
+#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
-/*
- * Special irq handlers.
- */
+extern void __init fpga_init(void);
+#ifdef CONFIG_FUJITSU_MB93493
+extern void __init mb93493_init(void);
+#endif
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; }
+#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
atomic_t irq_err_count;
@@ -64,215 +54,86 @@ atomic_t irq_err_count;
*/
int show_interrupts(struct seq_file *p, void *v)
{
- struct irqaction *action;
- struct irq_group *group;
+ int i = *(loff_t *) v, cpu;
+ struct irqaction * action;
unsigned long flags;
- int level, grp, ix, i, j;
-
- i = *(loff_t *) v;
-
- switch (i) {
- case 0:
- seq_printf(p, " ");
- for_each_online_cpu(j)
- seq_printf(p, "CPU%d ",j);
-
- seq_putc(p, '\n');
- break;
- case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP:
- local_irq_save(flags);
-
- grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP;
- group = irq_groups[grp];
- if (!group)
- goto skip;
-
- ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP;
- action = group->actions[ix];
- if (!action)
- goto skip;
-
- seq_printf(p, "%3d: ", i - 1);
-
-#ifndef CONFIG_SMP
- seq_printf(p, "%10u ", kstat_irqs(i));
-#else
- for_each_online_cpu(j)
- seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]);
-#endif
-
- level = group->sources[ix]->level - frv_irq_levels;
-
- seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level);
- seq_printf(p, " %s", action->name);
-
- for (action = action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
+ if (i == 0) {
+ char cpuname[12];
+ seq_printf(p, " ");
+ for_each_present_cpu(cpu) {
+ sprintf(cpuname, "CPU%d", cpu);
+ seq_printf(p, " %10s", cpuname);
+ }
seq_putc(p, '\n');
-skip:
- local_irq_restore(flags);
- break;
+ }
- case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1:
- seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
- break;
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (action) {
+ seq_printf(p, "%3d: ", i);
+ for_each_present_cpu(cpu)
+ seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+ seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
+ seq_printf(p, " %s", action->name);
+ for (action = action->next;
+ action;
+ action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+ }
- default:
- break;
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
}
return 0;
}
-
/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
+ * on-CPU PIC operations
*/
-
-/**
- * disable_irq_nosync - disable an irq without waiting
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Disables and Enables are
- * nested.
- * Unlike disable_irq(), this function does not ensure existing
- * instances of the IRQ handler have completed before returning.
- *
- * This function may be called from IRQ context.
- */
-
-void disable_irq_nosync(unsigned int irq)
+static void frv_cpupic_ack(unsigned int irqlevel)
{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- unsigned long flags;
- int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[idx];
- if (!source)
- BUG();
-
- level = source->level;
-
- spin_lock_irqsave(&level->lock, flags);
-
- if (group->control) {
- if (!group->disable_cnt[idx]++)
- group->control(group, idx, 0);
- } else if (!level->disable_count++) {
- __set_MASK(level - frv_irq_levels);
- }
-
- spin_unlock_irqrestore(&level->lock, flags);
+ __clr_RC(irqlevel);
+ __clr_IRL();
}
-EXPORT_SYMBOL(disable_irq_nosync);
-
-/**
- * disable_irq - disable an irq and wait for completion
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Enables and Disables are
- * nested.
- * This function waits for any pending IRQ handlers for this interrupt
- * to complete before returning. If you use this function while
- * holding a resource the IRQ handler may need you will deadlock.
- *
- * This function may be called - with care - from IRQ context.
- */
-
-void disable_irq(unsigned int irq)
+static void frv_cpupic_mask(unsigned int irqlevel)
{
- disable_irq_nosync(irq);
-
-#ifdef CONFIG_SMP
- if (!local_irq_count(smp_processor_id())) {
- do {
- barrier();
- } while (irq_desc[irq].status & IRQ_INPROGRESS);
- }
-#endif
+ __set_MASK(irqlevel);
}
-EXPORT_SYMBOL(disable_irq);
-
-/**
- * enable_irq - enable handling of an irq
- * @irq: Interrupt to enable
- *
- * Undoes the effect of one call to disable_irq(). If this
- * matches the last disable, processing of interrupts on this
- * IRQ line is re-enabled.
- *
- * This function may be called from IRQ context.
- */
-
-void enable_irq(unsigned int irq)
+static void frv_cpupic_mask_ack(unsigned int irqlevel)
{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- unsigned long flags;
- int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
- int count;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[idx];
- if (!source)
- BUG();
-
- level = source->level;
-
- spin_lock_irqsave(&level->lock, flags);
-
- if (group->control)
- count = group->disable_cnt[idx];
- else
- count = level->disable_count;
-
- switch (count) {
- case 1:
- if (group->control) {
- if (group->actions[idx])
- group->control(group, idx, 1);
- } else {
- if (level->usage)
- __clr_MASK(level - frv_irq_levels);
- }
- /* fall-through */
-
- default:
- count--;
- break;
-
- case 0:
- printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0));
- }
+ __set_MASK(irqlevel);
+ __clr_RC(irqlevel);
+ __clr_IRL();
+}
- if (group->control)
- group->disable_cnt[idx] = count;
- else
- level->disable_count = count;
+static void frv_cpupic_unmask(unsigned int irqlevel)
+{
+ __clr_MASK(irqlevel);
+}
- spin_unlock_irqrestore(&level->lock, flags);
+static void frv_cpupic_end(unsigned int irqlevel)
+{
+ __clr_MASK(irqlevel);
}
-EXPORT_SYMBOL(enable_irq);
+static struct irq_chip frv_cpu_pic = {
+ .name = "cpu",
+ .ack = frv_cpupic_ack,
+ .mask = frv_cpupic_mask,
+ .mask_ack = frv_cpupic_mask_ack,
+ .unmask = frv_cpupic_unmask,
+ .end = frv_cpupic_end,
+};
-/*****************************************************************************/
/*
* handles all normal device IRQ's
* - registers are referred to by the __frame variable (GR28)
@@ -281,463 +142,65 @@ EXPORT_SYMBOL(enable_irq);
*/
asmlinkage void do_IRQ(void)
{
- struct irq_source *source;
- int level, cpu;
-
irq_enter();
-
- level = (__frame->tbr >> 4) & 0xf;
- cpu = smp_processor_id();
-
- if ((unsigned long) __frame - (unsigned long) (current + 1) < 512)
- BUG();
-
- __set_MASK(level);
- __clr_RC(level);
- __clr_IRL();
-
- kstat_this_cpu.irqs[level]++;
-
- for (source = frv_irq_levels[level].sources; source; source = source->next)
- source->doirq(source);
-
- __clr_MASK(level);
-
+ generic_handle_irq(__get_IRL(), __frame);
irq_exit();
+}
-} /* end do_IRQ() */
-
-/*****************************************************************************/
/*
* handles all NMIs when not co-opted by the debugger
* - registers are referred to by the __frame variable (GR28)
*/
asmlinkage void do_NMI(void)
{
-} /* end do_NMI() */
-
-/*****************************************************************************/
-/**
- * request_irq - allocate an interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs
- * @irqflags: Interrupt type flags
- * @devname: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. From the point this
- * call is made your handler function may be invoked. Since
- * your handler function must clear any interrupt the board
- * raises, you must take care both to initialise your hardware
- * and to set up the interrupt handler in the right order.
- *
- * Dev_id must be globally unique. Normally the address of the
- * device data structure is used as the cookie. Since the handler
- * receives this value it makes sense to use it.
- *
- * If your interrupt is shared you must pass a non NULL dev_id
- * as this is required when freeing the interrupt.
- *
- * Flags:
- *
- * IRQF_SHARED Interrupt is shared
- *
- * IRQF_DISABLED Disable local interrupts while processing
- *
- * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
- *
- */
-
-int request_irq(unsigned int irq,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
-{
- int retval;
- struct irqaction *action;
-
-#if 1
- /*
- * Sanity-check: shared interrupts should REALLY pass in
- * a real dev-ID, otherwise we'll have trouble later trying
- * to figure out which interrupt is which (messes up the
- * interrupt freeing logic etc).
- */
- if (irqflags & IRQF_SHARED) {
- if (!dev_id)
- printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n",
- devname, (&irq)[-1]);
- }
-#endif
-
- if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
- return -EINVAL;
- if (!handler)
- return -EINVAL;
-
- action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- action->handler = handler;
- action->flags = irqflags;
- action->mask = CPU_MASK_NONE;
- action->name = devname;
- action->next = NULL;
- action->dev_id = dev_id;
-
- retval = setup_irq(irq, action);
- if (retval)
- kfree(action);
- return retval;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-/**
- * free_irq - free an interrupt
- * @irq: Interrupt line to free
- * @dev_id: Device identity to free
- *
- * Remove an interrupt handler. The handler is removed and if the
- * interrupt line is no longer in use by any driver it is disabled.
- * On a shared IRQ the caller must ensure the interrupt is disabled
- * on the card it drives before calling this function. The function
- * does not return until any executing interrupts for this IRQ
- * have completed.
- *
- * This function may be called from interrupt context.
- *
- * Bugs: Attempting to free an irq in a handler for the same irq hangs
- * the machine.
- */
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- struct irqaction **p, **pp;
- unsigned long flags;
-
- if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
- return;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
- if (!source)
- BUG();
-
- level = source->level;
- p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
-
- spin_lock_irqsave(&level->lock, flags);
-
- for (pp = p; *pp; pp = &(*pp)->next) {
- struct irqaction *action = *pp;
-
- if (action->dev_id != dev_id)
- continue;
-
- /* found it - remove from the list of entries */
- *pp = action->next;
-
- level->usage--;
-
- if (p == pp && group->control)
- group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0);
-
- if (level->usage == 0)
- __set_MASK(level - frv_irq_levels);
-
- spin_unlock_irqrestore(&level->lock,flags);
-
-#ifdef CONFIG_SMP
- /* Wait to make sure it's not being used on another CPU */
- while (desc->status & IRQ_INPROGRESS)
- barrier();
-#endif
- kfree(action);
- return;
- }
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that comes in on to an
- * unassigned IRQ will cause GxICR_DETECT to be set
- */
-
-static DECLARE_MUTEX(probe_sem);
-
-/**
- * probe_irq_on - begin an interrupt autodetect
- *
- * Commence probing for an interrupt. The interrupts are scanned
- * and a mask of potential interrupt lines is returned.
- *
- */
-
-unsigned long probe_irq_on(void)
-{
- down(&probe_sem);
- return 0;
}
-EXPORT_SYMBOL(probe_irq_on);
-
/*
- * Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
- */
-
-/**
- * probe_irq_mask - scan a bitmap of interrupt lines
- * @val: mask of interrupts to consider
- *
- * Scan the ISA bus interrupt lines and return a bitmap of
- * active interrupts. The interrupt probe logic state is then
- * returned to its previous value.
- *
- * Note: we need to scan all the irq's even though we will
- * only return ISA irq numbers - just so that we reset them
- * all to a known state.
- */
-unsigned int probe_irq_mask(unsigned long xmask)
-{
- up(&probe_sem);
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_mask);
-
-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source).
- */
-
-/**
- * probe_irq_off - end an interrupt autodetect
- * @xmask: mask of potential interrupts (unused)
- *
- * Scans the unused interrupt lines and returns the line which
- * appears to have triggered the interrupt. If no interrupt was
- * found then zero is returned. If more than one interrupt is
- * found then minus the first candidate is returned to indicate
- * their is doubt.
- *
- * The interrupt probe logic state is returned to its previous
- * value.
- *
- * BUGS: When used in a module (which arguably shouldnt happen)
- * nothing prevents two IRQ probe callers from overlapping. The
- * results of this are non-optimal.
+ * initialise the interrupt system
*/
-
-int probe_irq_off(unsigned long xmask)
-{
- up(&probe_sem);
- return -1;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-/* this was setup_x86_irq but it seems pretty generic */
-int setup_irq(unsigned int irq, struct irqaction *new)
-{
- struct irq_source *source;
- struct irq_group *group;
- struct irq_level *level;
- struct irqaction **p, **pp;
- unsigned long flags;
-
- group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
- if (!group)
- BUG();
-
- source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
- if (!source)
- BUG();
-
- level = source->level;
-
- p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
-
- /*
- * Some drivers like serial.c use request_irq() heavily,
- * so we have to be careful not to interfere with a
- * running system.
- */
- if (new->flags & IRQF_SAMPLE_RANDOM) {
- /*
- * This function might sleep, we want to call it first,
- * outside of the atomic block.
- * Yes, this might clear the entropy pool if the wrong
- * driver is attempted to be loaded, without actually
- * installing a new handler, but is this really a problem,
- * only the sysadmin is able to do this.
- */
- rand_initialize_irq(irq);
- }
-
- /* must juggle the interrupt processing stuff with interrupts disabled */
- spin_lock_irqsave(&level->lock, flags);
-
- /* can't share interrupts unless all parties agree to */
- if (level->usage != 0 && !(level->flags & new->flags & IRQF_SHARED)) {
- spin_unlock_irqrestore(&level->lock,flags);
- return -EBUSY;
- }
-
- /* add new interrupt at end of irq queue */
- pp = p;
- while (*pp)
- pp = &(*pp)->next;
-
- *pp = new;
-
- level->usage++;
- level->flags = new->flags;
-
- /* turn the interrupts on */
- if (level->usage == 1)
- __clr_MASK(level - frv_irq_levels);
-
- if (p == pp && group->control)
- group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1);
-
- spin_unlock_irqrestore(&level->lock, flags);
- register_irq_proc(irq);
- return 0;
-}
-
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-
-#define HEX_DIGITS 8
-
-static unsigned int parse_hex_value (const char __user *buffer,
- unsigned long count, unsigned long *ret)
-{
- unsigned char hexnum [HEX_DIGITS];
- unsigned long value;
- int i;
-
- if (!count)
- return -EINVAL;
- if (count > HEX_DIGITS)
- count = HEX_DIGITS;
- if (copy_from_user(hexnum, buffer, count))
- return -EFAULT;
-
- /*
- * Parse the first 8 characters as a hex string, any non-hex char
- * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
- */
- value = 0;
-
- for (i = 0; i < count; i++) {
- unsigned int c = hexnum[i];
-
- switch (c) {
- case '0' ... '9': c -= '0'; break;
- case 'a' ... 'f': c -= 'a'-10; break;
- case 'A' ... 'F': c -= 'A'-10; break;
- default:
- goto out;
- }
- value = (value << 4) | c;
- }
-out:
- *ret = value;
- return 0;
-}
-
-
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- unsigned long *mask = (unsigned long *) data;
- if (count < HEX_DIGITS+1)
- return -EINVAL;
- return sprintf (page, "%08lx\n", *mask);
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- unsigned long *mask = (unsigned long *) data, full_count = count, err;
- unsigned long new_value;
-
- show_state();
- err = parse_hex_value(buffer, count, &new_value);
- if (err)
- return err;
-
- *mask = new_value;
- return full_count;
-}
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
- char name [MAX_NAMELEN];
-
- if (!root_irq_dir || irq_dir[irq])
- return;
-
- memset(name, 0, MAX_NAMELEN);
- sprintf(name, "%d", irq);
-
- /* create /proc/irq/1234 */
- irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-}
-
-unsigned long prof_cpu_mask = -1;
-
-void init_irq_proc (void)
+void __init init_IRQ(void)
{
- struct proc_dir_entry *entry;
- int i;
+ int level;
- /* create /proc/irq */
- root_irq_dir = proc_mkdir("irq", NULL);
+ for (level = 1; level <= 14; level++)
+ set_irq_chip_and_handler(level, &frv_cpu_pic,
+ handle_level_irq);
- /* create /proc/irq/prof_cpu_mask */
- entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
- if (!entry)
- return;
+ set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
- entry->nlink = 1;
- entry->data = (void *)&prof_cpu_mask;
- entry->read_proc = prof_cpu_mask_read_proc;
- entry->write_proc = prof_cpu_mask_write_proc;
-
- /*
- * Create entries for all existing IRQs.
+ /* set the trigger levels for internal interrupt sources
+ * - timers all falling-edge
+ * - ERR0 is rising-edge
+ * - all others are high-level
*/
- for (i = 0; i < NR_IRQS; i++)
- register_irq_proc(i);
-}
+ __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */
+ __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */
+
+ /* route internal interrupts */
+ set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL,
+ IRQ_DMA0_LEVEL);
+ set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
+ set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL,
+ IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
+ set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL,
+ IRQ_DMA4_LEVEL);
+
+ /* route external interrupts */
+ set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL,
+ IRQ_XIRQ4_LEVEL);
+ set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL,
+ IRQ_XIRQ0_LEVEL);
+
+#if defined(CONFIG_MB93091_VDK)
+ __set_TM1(0x55550000); /* XIRQ7-0 all active low */
+#elif defined(CONFIG_MB93093_PDK)
+ __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
+#else
+#error dont know external IRQ trigger levels for this setup
+#endif
-/*****************************************************************************/
-/*
- * initialise the interrupt system
- */
-void __init init_IRQ(void)
-{
- route_cpu_irqs();
fpga_init();
#ifdef CONFIG_FUJITSU_MB93493
- route_mb93493_irqs();
+ mb93493_init();
#endif
-} /* end init_IRQ() */
+}
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index af08ccd4ed6..d96a57e5f03 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -43,7 +43,6 @@
#include <asm/mb-regs.h>
#include <asm/mb93493-regs.h>
#include <asm/gdb-stub.h>
-#include <asm/irq-routing.h>
#include <asm/io.h>
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 68a77fe3bb4..3d0284bccb9 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -26,7 +26,6 @@
#include <asm/timer-regs.h>
#include <asm/mb-regs.h>
#include <asm/mb86943a.h>
-#include <asm/irq-routing.h>
#include <linux/timex.h>
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 2278c80bd88..ba587523c01 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -15,7 +15,6 @@
#include <asm/io.h>
#include <asm/smp.h>
-#include <asm/irq-routing.h>
#include "pci-frv.h"
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index b5b4286f9dd..3f3a0ed3539 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -98,7 +98,7 @@ void show_mem(void)
*/
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
/* allocate some pages for kernel housekeeping tasks */
empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
index d3d40bdc2d6..e4f4199f97a 100644
--- a/arch/h8300/mm/init.c
+++ b/arch/h8300/mm/init.c
@@ -138,7 +138,7 @@ void paging_init(void)
#endif
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b2751eadbc5..3fd2f256f2b 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -166,7 +166,6 @@ config X86_VISWS
config X86_GENERICARCH
bool "Generic architecture (Summit, bigsmp, ES7000, default)"
- depends on SMP
help
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
It is intended for a generic binary kernel.
@@ -263,7 +262,7 @@ source "kernel/Kconfig.preempt"
config X86_UP_APIC
bool "Local APIC support on uniprocessors"
- depends on !SMP && !(X86_VISWS || X86_VOYAGER)
+ depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
help
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
@@ -288,12 +287,12 @@ config X86_UP_IOAPIC
config X86_LOCAL_APIC
bool
- depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER)
+ depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH
default y
config X86_IO_APIC
bool
- depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER))
+ depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH
default y
config X86_VISWS_APIC
@@ -402,6 +401,7 @@ config X86_REBOOTFIXUPS
config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
+ select FW_LOADER
---help---
If you say Y here and also to "/dev file system support" in the
'File systems' section, you will be able to update the microcode on
@@ -417,6 +417,11 @@ config MICROCODE
To compile this driver as a module, choose M here: the
module will be called microcode.
+config MICROCODE_OLD_INTERFACE
+ bool
+ depends on MICROCODE
+ default y
+
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
help
@@ -494,7 +499,7 @@ config HIGHMEM64G
endchoice
choice
- depends on EXPERIMENTAL && !X86_PAE
+ depends on EXPERIMENTAL
prompt "Memory split" if EMBEDDED
default VMSPLIT_3G
help
@@ -516,6 +521,7 @@ choice
config VMSPLIT_3G
bool "3G/1G user/kernel split"
config VMSPLIT_3G_OPT
+ depends on !HIGHMEM
bool "3G/1G user/kernel split (for full 1G low memory)"
config VMSPLIT_2G
bool "2G/2G user/kernel split"
@@ -598,12 +604,10 @@ config ARCH_SELECT_MEMORY_MODEL
def_bool y
depends on ARCH_SPARSEMEM_ENABLE
-source "mm/Kconfig"
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
-config HAVE_ARCH_EARLY_PFN_TO_NID
- bool
- default y
- depends on NUMA
+source "mm/Kconfig"
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
@@ -740,8 +744,7 @@ config SECCOMP
source kernel/Kconfig.hz
config KEXEC
- bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "kexec system call"
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -762,6 +765,13 @@ config CRASH_DUMP
depends on HIGHMEM
help
Generate crash dump after being started by kexec.
+ This should be normally only set in special crash dump kernels
+ which are loaded in the main kernel with kexec-tools into
+ a specially reserved region and then later executed after
+ a crash by kdump/kexec. The crash dump kernel must be compiled
+ to a memory address not used by the main kernel or BIOS using
+ PHYSICAL_START.
+ For more details see Documentation/kdump/kdump.txt
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
@@ -794,6 +804,7 @@ config HOTPLUG_CPU
config COMPAT_VDSO
bool "Compat VDSO support"
default y
+ depends on !PARAVIRT
help
Map the VDSO to the predictable old-style address too.
---help---
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 3e4adb1e224..7cc0b189b82 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -46,6 +46,14 @@ cflags-y += -ffreestanding
# a lot more stack due to the lack of sharing of stacklots:
CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
+# do binutils support CFI?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
+# is .cfi_signal_frame supported too?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
CFLAGS += $(cflags-y)
# Default subarch .c files
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
index 4b84ea216f2..34321368011 100644
--- a/arch/i386/boot/edd.S
+++ b/arch/i386/boot/edd.S
@@ -15,42 +15,95 @@
#include <asm/setup.h>
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+# It is assumed that %ds == INITSEG here
+
movb $0, (EDD_MBR_SIG_NR_BUF)
movb $0, (EDDNR)
-# Check the command line for two options:
+# Check the command line for options:
# edd=of disables EDD completely (edd=off)
# edd=sk skips the MBR test (edd=skipmbr)
+# edd=on re-enables EDD (edd=on)
+
pushl %esi
- cmpl $0, %cs:cmd_line_ptr
- jz done_cl
+ movw $edd_mbr_sig_start, %di # Default to edd=on
+
movl %cs:(cmd_line_ptr), %esi
-# ds:esi has the pointer to the command line now
- movl $(COMMAND_LINE_SIZE-7), %ecx
-# loop through kernel command line one byte at a time
-cl_loop:
- cmpl $EDD_CL_EQUALS, (%si)
+ andl %esi, %esi
+ jz old_cl # Old boot protocol?
+
+# Convert to a real-mode pointer in fs:si
+ movl %esi, %eax
+ shrl $4, %eax
+ movw %ax, %fs
+ andw $0xf, %si
+ jmp have_cl_pointer
+
+# Old-style boot protocol?
+old_cl:
+ push %ds # aka INITSEG
+ pop %fs
+
+ cmpw $0xa33f, (0x20)
+ jne done_cl # No command line at all?
+ movw (0x22), %si # Pointer relative to INITSEG
+
+# fs:si has the pointer to the command line now
+have_cl_pointer:
+
+# Loop through kernel command line one byte at a time. Just in
+# case the loader is buggy and failed to null-terminate the command line
+# terminate if we get close enough to the end of the segment that we
+# cannot fit "edd=XX"...
+cl_atspace:
+ cmpw $-5, %si # Watch for segment wraparound
+ jae done_cl
+ movl %fs:(%si), %eax
+ andb %al, %al # End of line?
+ jz done_cl
+ cmpl $EDD_CL_EQUALS, %eax
jz found_edd_equals
- incl %esi
- loop cl_loop
- jmp done_cl
+ cmpb $0x20, %al # <= space consider whitespace
+ ja cl_skipword
+ incw %si
+ jmp cl_atspace
+
+cl_skipword:
+ cmpw $-5, %si # Watch for segment wraparound
+ jae done_cl
+ movb %fs:(%si), %al # End of string?
+ andb %al, %al
+ jz done_cl
+ cmpb $0x20, %al
+ jbe cl_atspace
+ incw %si
+ jmp cl_skipword
+
found_edd_equals:
# only looking at first two characters after equals
- addl $4, %esi
- cmpw $EDD_CL_OFF, (%si) # edd=of
- jz do_edd_off
- cmpw $EDD_CL_SKIP, (%si) # edd=sk
- jz do_edd_skipmbr
- jmp done_cl
+# late overrides early on the command line, so keep going after finding something
+ movw %fs:4(%si), %ax
+ cmpw $EDD_CL_OFF, %ax # edd=of
+ je do_edd_off
+ cmpw $EDD_CL_SKIP, %ax # edd=sk
+ je do_edd_skipmbr
+ cmpw $EDD_CL_ON, %ax # edd=on
+ je do_edd_on
+ jmp cl_skipword
do_edd_skipmbr:
- popl %esi
- jmp edd_start
+ movw $edd_start, %di
+ jmp cl_skipword
do_edd_off:
- popl %esi
- jmp edd_done
+ movw $edd_done, %di
+ jmp cl_skipword
+do_edd_on:
+ movw $edd_mbr_sig_start, %di
+ jmp cl_skipword
+
done_cl:
popl %esi
-
+ jmpw *%di
# Read the first sector of each BIOS disk device and store the 4-byte signature
edd_mbr_sig_start:
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index d2b684cd620..3aec4538a11 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -494,12 +494,12 @@ no_voyager:
movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG
movw %ax, %ds
- movw $0, (0x1ff) # default is no pointing device
+ movb $0, (0x1ff) # default is no pointing device
int $0x11 # int 0x11: equipment list
testb $0x04, %al # check if mouse installed
jz no_psmouse
- movw $0xAA, (0x1ff) # device present
+ movb $0xAA, (0x1ff) # device present
no_psmouse:
#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 89ebb7a316a..1a29bfa26d0 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,41 +1,51 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-git5
+# Tue Sep 26 09:30:47 2006
#
CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_X86=y
CONFIG_MMU=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
-# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
-CONFIG_VM86=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -45,11 +55,9 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=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_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -60,41 +68,45 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
#
# Block layer
#
-# CONFIG_LBD is not set
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Processor type and features
#
-CONFIG_X86_PC=y
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
# CONFIG_X86_ELAN is not set
# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_NUMAQ is not set
# CONFIG_X86_SUMMIT is not set
# CONFIG_X86_BIGSMP is not set
# CONFIG_X86_VISWS is not set
-# CONFIG_X86_GENERICARCH is not set
+CONFIG_X86_GENERICARCH=y
# CONFIG_X86_ES7000 is not set
+CONFIG_X86_CYCLONE_TIMER=y
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
@@ -102,11 +114,11 @@ CONFIG_X86_PC=y
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
-# CONFIG_MPENTIUMIII is not set
+CONFIG_MPENTIUMIII=y
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
-CONFIG_MK7=y
+# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
@@ -117,10 +129,10 @@ CONFIG_MK7=y
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
-# CONFIG_X86_GENERIC is not set
+CONFIG_X86_GENERIC=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_XADD=y
-CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_WP_WORKS_OK=y
@@ -131,26 +143,28 @@ CONFIG_X86_CMPXCHG64=y
CONFIG_X86_GOOD_APIC=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_USE_3DNOW=y
CONFIG_X86_TSC=y
-# CONFIG_HPET_TIMER is not set
-# CONFIG_SMP is not set
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=32
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
-CONFIG_X86_UP_APIC=y
-CONFIG_X86_UP_IOAPIC=y
+CONFIG_PREEMPT_BKL=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
CONFIG_X86_MCE=y
CONFIG_X86_MCE_NONFATAL=y
-# CONFIG_X86_MCE_P4THERMAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
# CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set
# CONFIG_X86_REBOOTFIXUPS is not set
-# CONFIG_MICROCODE is not set
-# CONFIG_X86_MSR is not set
-# CONFIG_X86_CPUID is not set
+CONFIG_MICROCODE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
#
# Firmware Drivers
@@ -158,68 +172,67 @@ CONFIG_X86_MCE_NONFATAL=y
# CONFIG_EDD is not set
# CONFIG_DELL_RBU is not set
# CONFIG_DCDBAS is not set
-CONFIG_NOHIGHMEM=y
-# CONFIG_HIGHMEM4G is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
# CONFIG_HIGHMEM64G is not set
-CONFIG_VMSPLIT_3G=y
-# CONFIG_VMSPLIT_3G_OPT is not set
-# CONFIG_VMSPLIT_2G is not set
-# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_HIGHMEM=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+# CONFIG_HIGHPTE is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_MTRR=y
# CONFIG_EFI is not set
+# CONFIG_IRQBALANCE is not set
CONFIG_REGPARM=y
-# CONFIG_SECCOMP is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x100000
-CONFIG_DOUBLEFAULT=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_COMPAT_VDSO=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
#
# Power management options (ACPI, APM)
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
+CONFIG_PM_LEGACY=y
# CONFIG_PM_DEBUG is not set
-CONFIG_SOFTWARE_SUSPEND=y
-CONFIG_PM_STD_PARTITION=""
#
# ACPI (Advanced Configuration and Power Interface) Support
#
CONFIG_ACPI=y
-# CONFIG_ACPI_SLEEP is not set
-# CONFIG_ACPI_AC is not set
-# CONFIG_ACPI_BATTERY is not set
-# CONFIG_ACPI_BUTTON is not set
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
# CONFIG_ACPI_VIDEO is not set
# CONFIG_ACPI_HOTKEY is not set
-# CONFIG_ACPI_FAN is not set
-# CONFIG_ACPI_PROCESSOR is not set
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_ASUS is not set
# CONFIG_ACPI_IBM is not set
# CONFIG_ACPI_TOSHIBA is not set
-CONFIG_ACPI_BLACKLIST_YEAR=0
-# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+CONFIG_ACPI_DEBUG=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_SYSTEM=y
-# CONFIG_X86_PM_TIMER is not set
+CONFIG_X86_PM_TIMER=y
# CONFIG_ACPI_CONTAINER is not set
#
@@ -230,7 +243,41 @@ CONFIG_ACPI_SYSTEM=y
#
# CPU Frequency scaling
#
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+# CONFIG_X86_LONGRUN is not set
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+# CONFIG_X86_SPEEDSTEP_LIB is not set
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -244,12 +291,13 @@ CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
# CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
-# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
CONFIG_ISA_DMA_API=y
# CONFIG_ISA is not set
# CONFIG_MCA is not set
# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -278,93 +326,54 @@ CONFIG_NET=y
#
# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
+# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+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_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK is not set
-CONFIG_NETFILTER_XTABLES=y
-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=y
-# 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=y
-# CONFIG_IP_NF_IRC is not set
-# 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 is not set
-CONFIG_IP_NF_IPTABLES=y
-# CONFIG_IP_NF_MATCH_IPRANGE is not set
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_TOS is not set
-# 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 is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_OWNER is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-CONFIG_IP_NF_FILTER=y
-# CONFIG_IP_NF_TARGET_REJECT is not set
-CONFIG_IP_NF_TARGET_LOG=y
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
-# CONFIG_IP_NF_NAT is not set
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_RAW is not set
-# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -389,7 +398,6 @@ CONFIG_IP_NF_TARGET_LOG=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -402,6 +410,7 @@ CONFIG_IP_NF_TARGET_LOG=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
@@ -416,7 +425,9 @@ CONFIG_IP_NF_TARGET_LOG=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
@@ -431,13 +442,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Parallel port support
#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-# CONFIG_PARPORT_SERIAL is not set
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_GSC is not set
-CONFIG_PARPORT_1284=y
+# CONFIG_PARPORT is not set
#
# Plug and Play support
@@ -447,8 +452,7 @@ CONFIG_PARPORT_1284=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -459,8 +463,11 @@ CONFIG_BLK_DEV_LOOP=y
# 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 is not set
+CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -476,7 +483,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_IDE_SATA is not set
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_MULTI_MODE=y
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -486,10 +493,10 @@ CONFIG_BLK_DEV_IDECD=y
#
# IDE chipset support/bugfixes
#
-# CONFIG_IDE_GENERIC is not set
+CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_CMD640 is not set
CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -500,7 +507,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK 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_AMD74XX=y
# CONFIG_BLK_DEV_ATIIXP is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
@@ -511,7 +518,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -521,7 +528,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
@@ -533,6 +540,7 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
#
@@ -541,8 +549,9 @@ CONFIG_SCSI=y
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_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not set
#
@@ -553,29 +562,44 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOGGING is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=y
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=4000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -584,11 +608,9 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -598,22 +620,114 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_DEBUG is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_SVW=y
+CONFIG_ATA_PIIX=y
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=y
+# 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=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+CONFIG_SATA_VIA=y
+# CONFIG_SATA_VITESSE is not set
+CONFIG_SATA_INTEL_COMBINED=y
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CS5535 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_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX 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_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_QDI 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
+
+#
# Multi-device support (RAID and LVM)
#
-# CONFIG_MD is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
# CONFIG_FUSION_FC is not set
# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
+CONFIG_IEEE1394=y
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# Protocol Drivers
+#
+# CONFIG_IEEE1394_VIDEO1394 is not set
+# CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+# CONFIG_IEEE1394_DV1394 is not set
+CONFIG_IEEE1394_RAWIO=y
#
# I2O device support
@@ -652,46 +766,63 @@ CONFIG_MII=y
#
# Tulip family network device support
#
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
# CONFIG_HP100 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_B44=y
+CONFIG_FORCEDETH=y
+# CONFIG_FORCEDETH_NAPI is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
+CONFIG_SKY2=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
+CONFIG_TIGON3=y
+CONFIG_BNX2=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -699,6 +830,7 @@ CONFIG_E100=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
#
# Token Ring devices
@@ -716,14 +848,15 @@ CONFIG_E100=y
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-# CONFIG_PLIP 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
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
#
# ISDN subsystem
@@ -745,8 +878,8 @@ CONFIG_INPUT=y
#
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
+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=y
@@ -776,7 +909,6 @@ CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
@@ -788,14 +920,15 @@ CONFIG_SERIO_LIBPS2=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -804,14 +937,11 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
#
# IPMI
@@ -822,8 +952,12 @@ CONFIG_PRINTER=y
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_NVRAM=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=y
+CONFIG_HW_RANDOM_AMD=y
+CONFIG_HW_RANDOM_GEODE=y
+CONFIG_HW_RANDOM_VIA=y
+# CONFIG_NVRAM is not set
CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -833,31 +967,28 @@ CONFIG_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
CONFIG_AGP=y
# CONFIG_AGP_ALI is not set
# CONFIG_AGP_ATI is not set
# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD64 is not set
-# CONFIG_AGP_INTEL is not set
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
# CONFIG_AGP_NVIDIA is not set
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_SWORKS is not set
-CONFIG_AGP_VIA=y
+# CONFIG_AGP_VIA is not set
# CONFIG_AGP_EFFICEON is not set
-CONFIG_DRM=y
-# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_R128 is not set
-CONFIG_DRM_RADEON=y
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-# CONFIG_DRM_SAVAGE is not set
+# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
# CONFIG_CS5535_GPIO is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HPET is not set
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=y
#
# TPM devices
@@ -868,59 +999,7 @@ CONFIG_DRM_RADEON=y
#
# I2C support
#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_ISA=y
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT 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_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-CONFIG_I2C_VIAPRO=y
-# 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_SENSORS_EEPROM is not set
-# 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_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
+# CONFIG_I2C is not set
#
# SPI support
@@ -931,51 +1010,12 @@ CONFIG_I2C_VIAPRO=y
#
# Dallas's 1-wire bus
#
-# CONFIG_W1 is not set
#
# Hardware Monitoring support
#
-CONFIG_HWMON=y
-CONFIG_HWMON_VID=y
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-CONFIG_SENSORS_IT87=y
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_HDAPS is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
#
# Misc devices
@@ -983,117 +1023,31 @@ CONFIG_SENSORS_IT87=y
# CONFIG_IBM_ASM is not set
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
-CONFIG_VIDEO_DEV=y
-
-#
-# Video For Linux
-#
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_BT848 is not set
-# CONFIG_VIDEO_BWQCAM is not set
-# CONFIG_VIDEO_CQCAM is not set
-# CONFIG_VIDEO_W9966 is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-CONFIG_VIDEO_SAA7134=y
-# CONFIG_VIDEO_SAA7134_ALSA is not set
-# CONFIG_VIDEO_MXB is not set
-# CONFIG_VIDEO_DPC is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-# CONFIG_VIDEO_CX88 is not set
-# CONFIG_VIDEO_EM28XX is not set
-# CONFIG_VIDEO_OVCAMCHIP is not set
-# CONFIG_VIDEO_AUDIO_DECODER is not set
-# CONFIG_VIDEO_DECODER is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
-CONFIG_VIDEO_TUNER=y
-CONFIG_VIDEO_BUF=y
-CONFIG_VIDEO_IR=y
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_MACMODES is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ARC is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_VESA is not set
-CONFIG_VIDEO_SELECT=y
-# CONFIG_FB_HGA is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_I810 is not set
-# CONFIG_FB_INTEL is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-# CONFIG_FB_RADEON_DEBUG is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_GEODE is not set
-# CONFIG_FB_VIRTUAL is not set
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=128
+CONFIG_VIDEO_SELECT=y
CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1104,97 +1058,30 @@ CONFIG_SOUND=y
#
# Advanced Linux Sound Architecture
#
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_RAWMIDI=y
-CONFIG_SND_SEQUENCER=y
-# CONFIG_SND_SEQ_DUMMY is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_SEQUENCER_OSS is not set
-CONFIG_SND_RTCTIMER=y
-CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_MPU401_UART=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5535AUDIO is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-CONFIG_SND_VIA82XX=y
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-
-#
-# USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND is not set
#
# Open Sound System
#
-# CONFIG_SOUND_PRIME is not set
+CONFIG_SOUND_PRIME=y
+CONFIG_OSS_OBSOLETE_DRIVER=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_ES1371 is not set
+CONFIG_SOUND_ICH=y
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1213,17 +1100,19 @@ CONFIG_USB_DEVICEFS=y
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 is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+CONFIG_USB_PRINTER=y
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1248,21 +1137,17 @@ CONFIG_USB_STORAGE=y
#
# USB Input Devices
#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
# CONFIG_USB_AIPTEK is not set
# CONFIG_USB_WACOM is not set
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1277,21 +1162,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_STV680 is not set
-# CONFIG_USB_PWC is not set
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1299,12 +1169,11 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
+CONFIG_USB_MON=y
#
# USB port drivers
#
-# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
@@ -1321,10 +1190,12 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TEST is not set
@@ -1344,56 +1215,96 @@ CONFIG_USB_STORAGE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
-# EDAC - error detection and reporting (RAS)
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
#
-# CONFIG_EDAC is not set
#
# File systems
#
CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_REISERFS_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
-# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=y
-# CONFIG_MSDOS_FS is not set
+CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
@@ -1404,10 +1315,9 @@ CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1430,13 +1340,26 @@ CONFIG_RAMFS=y
#
# Network File Systems
#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
-CONFIG_CIFS=y
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1445,33 +1368,18 @@ CONFIG_CIFS=y
#
# Partition Types
#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# 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_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-15"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_850 is not set
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
@@ -1491,7 +1399,7 @@ CONFIG_NLS_CODEPAGE_850=y
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -1510,20 +1418,50 @@ CONFIG_NLS_UTF8=y
#
# Instrumentation Support
#
-# CONFIG_PROFILING is not set
-# CONFIG_KPROBES is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB 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_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING 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_HIGHMEM 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_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
#
# Security options
@@ -1537,10 +1475,6 @@ CONFIG_X86_MPPARSE=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
# CONFIG_CRC_CCITT is not set
@@ -1548,7 +1482,12 @@ CONFIG_X86_MPPARSE=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
CONFIG_KTIME_SCALAR=y
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5427a842e84..1a884b6e6e5 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -4,7 +4,7 @@
extra-y := head.o init_task.o vmlinux.lds
-obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
+obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
pci-dma.o i386_ksyms.o i387.o bootflag.o \
quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
@@ -81,4 +81,5 @@ $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
$(call if_changed,syscall)
k8-y += ../../x86_64/kernel/k8.o
+stacktrace-y += ../../x86_64/kernel/stacktrace.o
diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile
index 7e9ac99354f..7f7be01f44e 100644
--- a/arch/i386/kernel/acpi/Makefile
+++ b/arch/i386/kernel/acpi/Makefile
@@ -1,5 +1,7 @@
obj-$(CONFIG_ACPI) += boot.o
+ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o
+endif
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
ifneq ($(CONFIG_ACPI_PROCESSOR),)
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index ee003bc0e8b..1aaea6ab8c4 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -26,9 +26,12 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/efi.h>
+#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
#include <asm/pgtable.h>
#include <asm/io_apic.h>
@@ -36,11 +39,17 @@
#include <asm/io.h>
#include <asm/mpspec.h>
-#ifdef CONFIG_X86_64
+static int __initdata acpi_force = 0;
-extern void __init clustered_apic_check(void);
+#ifdef CONFIG_ACPI
+int acpi_disabled = 0;
+#else
+int acpi_disabled = 1;
+#endif
+EXPORT_SYMBOL(acpi_disabled);
+
+#ifdef CONFIG_X86_64
-extern int gsi_irq_sharing(int gsi);
#include <asm/proto.h>
static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
@@ -506,16 +515,76 @@ EXPORT_SYMBOL(acpi_register_gsi);
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int acpi_map_lsapic(acpi_handle handle, int *pcpu)
{
- /* TBD */
- return -EINVAL;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ struct acpi_table_lapic *lapic;
+ cpumask_t tmp_map, new_map;
+ u8 physid;
+ int cpu;
+
+ if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+ return -EINVAL;
+
+ if (!buffer.length || !buffer.pointer)
+ return -EINVAL;
+
+ obj = buffer.pointer;
+ if (obj->type != ACPI_TYPE_BUFFER ||
+ obj->buffer.length < sizeof(*lapic)) {
+ kfree(buffer.pointer);
+ return -EINVAL;
+ }
+
+ lapic = (struct acpi_table_lapic *)obj->buffer.pointer;
+
+ if ((lapic->header.type != ACPI_MADT_LAPIC) ||
+ (!lapic->flags.enabled)) {
+ kfree(buffer.pointer);
+ return -EINVAL;
+ }
+
+ physid = lapic->id;
+
+ kfree(buffer.pointer);
+ buffer.length = ACPI_ALLOCATE_BUFFER;
+ buffer.pointer = NULL;
+
+ tmp_map = cpu_present_map;
+ mp_register_lapic(physid, lapic->flags.enabled);
+
+ /*
+ * If mp_register_lapic successfully generates a new logical cpu
+ * number, then the following will get us exactly what was mapped
+ */
+ cpus_andnot(new_map, cpu_present_map, tmp_map);
+ if (cpus_empty(new_map)) {
+ printk ("Unable to map lapic to logical cpu number\n");
+ return -EINVAL;
+ }
+
+ cpu = first_cpu(new_map);
+
+ *pcpu = cpu;
+ return 0;
}
EXPORT_SYMBOL(acpi_map_lsapic);
int acpi_unmap_lsapic(int cpu)
{
- /* TBD */
- return -EINVAL;
+ int i;
+
+ for_each_possible_cpu(i) {
+ if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) {
+ x86_acpiid_to_apicid[i] = -1;
+ break;
+ }
+ }
+ x86_cpu_to_apicid[cpu] = -1;
+ cpu_clear(cpu, cpu_present_map);
+ num_processors--;
+
+ return (0);
}
EXPORT_SYMBOL(acpi_unmap_lsapic);
@@ -579,6 +648,8 @@ static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
{
struct acpi_table_hpet *hpet_tbl;
+ struct resource *hpet_res;
+ resource_size_t res_start;
if (!phys || !size)
return -EINVAL;
@@ -594,12 +665,26 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
"memory.\n");
return -1;
}
+
+#define HPET_RESOURCE_NAME_SIZE 9
+ hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
+ if (hpet_res) {
+ memset(hpet_res, 0, sizeof(*hpet_res));
+ hpet_res->name = (void *)&hpet_res[1];
+ hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
+ "HPET %u", hpet_tbl->number);
+ hpet_res->end = (1 * 1024) - 1;
+ }
+
#ifdef CONFIG_X86_64
vxtime.hpet_address = hpet_tbl->addr.addrl |
((long)hpet_tbl->addr.addrh << 32);
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
hpet_tbl->id, vxtime.hpet_address);
+
+ res_start = vxtime.hpet_address;
#else /* X86 */
{
extern unsigned long hpet_address;
@@ -607,9 +692,17 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
hpet_address = hpet_tbl->addr.addrl;
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
hpet_tbl->id, hpet_address);
+
+ res_start = hpet_address;
}
#endif /* X86 */
+ if (hpet_res) {
+ hpet_res->start = res_start;
+ hpet_res->end += res_start;
+ insert_resource(&iomem_resource, hpet_res);
+ }
+
return 0;
}
#else
@@ -860,8 +953,6 @@ static void __init acpi_process_madt(void)
return;
}
-extern int acpi_force;
-
#ifdef __i386__
static int __init disable_acpi_irq(struct dmi_system_id *d)
@@ -1163,3 +1254,75 @@ int __init acpi_boot_init(void)
return 0;
}
+
+static int __init parse_acpi(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ /* "acpi=off" disables both ACPI table parsing and interpreter */
+ if (strcmp(arg, "off") == 0) {
+ disable_acpi();
+ }
+ /* acpi=force to over-ride black-list */
+ else if (strcmp(arg, "force") == 0) {
+ acpi_force = 1;
+ acpi_ht = 1;
+ acpi_disabled = 0;
+ }
+ /* acpi=strict disables out-of-spec workarounds */
+ else if (strcmp(arg, "strict") == 0) {
+ acpi_strict = 1;
+ }
+ /* Limit ACPI just to boot-time to enable HT */
+ else if (strcmp(arg, "ht") == 0) {
+ if (!acpi_force)
+ disable_acpi();
+ acpi_ht = 1;
+ }
+ /* "acpi=noirq" disables ACPI interrupt routing */
+ else if (strcmp(arg, "noirq") == 0) {
+ acpi_noirq_set();
+ } else {
+ /* Core will printk when we return error. */
+ return -EINVAL;
+ }
+ return 0;
+}
+early_param("acpi", parse_acpi);
+
+/* FIXME: Using pci= for an ACPI parameter is a travesty. */
+static int __init parse_pci(char *arg)
+{
+ if (arg && strcmp(arg, "noacpi") == 0)
+ acpi_disable_pci();
+ return 0;
+}
+early_param("pci", parse_pci);
+
+#ifdef CONFIG_X86_IO_APIC
+static int __init parse_acpi_skip_timer_override(char *arg)
+{
+ acpi_skip_timer_override = 1;
+ return 0;
+}
+early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override);
+#endif /* CONFIG_X86_IO_APIC */
+
+static int __init setup_acpi_sci(char *s)
+{
+ if (!s)
+ return -EINVAL;
+ if (!strcmp(s, "edge"))
+ acpi_sci_flags.trigger = 1;
+ else if (!strcmp(s, "level"))
+ acpi_sci_flags.trigger = 3;
+ else if (!strcmp(s, "high"))
+ acpi_sci_flags.polarity = 1;
+ else if (!strcmp(s, "low"))
+ acpi_sci_flags.polarity = 3;
+ else
+ return -EINVAL;
+ return 0;
+}
+early_param("acpi_sci", setup_acpi_sci);
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 1649a175a20..fe799b11ac0 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -48,7 +48,11 @@ void __init check_acpi_pci(void)
int num, slot, func;
/* Assume the machine supports type 1. If not it will
- always read ffffffff and should not have any side effect. */
+ always read ffffffff and should not have any side effect.
+ Actually a few buggy systems can machine check. Allow the user
+ to disable it by command line option at least -AK */
+ if (!early_pci_allowed())
+ return;
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++) {
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 8c844d07862..90faae5c5d3 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -52,7 +52,18 @@ static cpumask_t timer_bcast_ipi;
/*
* Knob to control our willingness to enable the local APIC.
*/
-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+static inline void lapic_disable(void)
+{
+ enable_local_apic = -1;
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+}
+
+static inline void lapic_enable(void)
+{
+ enable_local_apic = 1;
+}
/*
* Debug level
@@ -586,8 +597,7 @@ void __devinit setup_local_APIC(void)
printk("No ESR for 82489DX.\n");
}
- if (nmi_watchdog == NMI_LOCAL_APIC)
- setup_apic_nmi_watchdog();
+ setup_apic_nmi_watchdog(NULL);
apic_pm_activate();
}
@@ -1373,3 +1383,18 @@ int __init APIC_init_uniprocessor (void)
return 0;
}
+
+static int __init parse_lapic(char *arg)
+{
+ lapic_enable();
+ return 0;
+}
+early_param("lapic", parse_lapic);
+
+static int __init parse_nolapic(char *arg)
+{
+ lapic_disable();
+ return 0;
+}
+early_param("nolapic", parse_nolapic);
+
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 8591f2fa920..ff9ce4b5eaa 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1154,9 +1154,11 @@ out:
static void set_time(void)
{
+ struct timespec ts;
if (got_clock_diff) { /* Must know time zone in order to set clock */
- xtime.tv_sec = get_cmos_time() + clock_cmos_diff;
- xtime.tv_nsec = 0;
+ ts.tv_sec = get_cmos_time() + clock_cmos_diff;
+ ts.tv_nsec = 0;
+ do_settimeofday(&ts);
}
}
@@ -1232,13 +1234,8 @@ static int suspend(int vetoable)
restore_processor_state();
local_irq_disable();
- write_seqlock(&xtime_lock);
- spin_lock(&i8253_lock);
- reinit_timer();
set_time();
-
- spin_unlock(&i8253_lock);
- write_sequnlock(&xtime_lock);
+ reinit_timer();
if (err == APM_NO_ERROR)
err = APM_SUCCESS;
@@ -1365,9 +1362,7 @@ static void check_events(void)
ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
- write_seqlock_irq(&xtime_lock);
set_time();
- write_sequnlock_irq(&xtime_lock);
device_resume();
pm_send_all(PM_RESUME, (void *)0);
queue_event(event, NULL);
@@ -1383,9 +1378,7 @@ static void check_events(void)
break;
case APM_UPDATE_TIME:
- write_seqlock_irq(&xtime_lock);
set_time();
- write_sequnlock_irq(&xtime_lock);
break;
case APM_CRITICAL_SUSPEND:
@@ -2339,6 +2332,7 @@ static int __init apm_init(void)
ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
if (ret < 0) {
printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
+ remove_proc_entry("apm", NULL);
return -ENOMEM;
}
@@ -2348,7 +2342,13 @@ static int __init apm_init(void)
return 0;
}
- misc_register(&apm_device);
+ /*
+ * Note we don't actually care if the misc_device cannot be registered.
+ * this driver can do its job without it, even if userspace can't
+ * control it. just log the error
+ */
+ if (misc_register(&apm_device))
+ printk(KERN_WARNING "apm: Could not register misc device.\n");
if (HZ != 100)
idle_period = (idle_period * HZ) / 100;
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index e6a2d6b80cd..e4758095d87 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -22,7 +22,7 @@
extern void vide(void);
__asm__(".align 4\nvide: ret");
-static void __init init_amd(struct cpuinfo_x86 *c)
+static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
@@ -246,7 +246,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
num_cache_leaves = 3;
}
-static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
{
/* AMD errata T13 (order #21922) */
if ((c->x86 == 6)) {
@@ -259,7 +259,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
return size;
}
-static struct cpu_dev amd_cpu_dev __initdata = {
+static struct cpu_dev amd_cpu_dev __cpuinitdata = {
.c_vendor = "AMD",
.c_ident = { "AuthenticAMD" },
.c_models = {
@@ -275,7 +275,6 @@ static struct cpu_dev amd_cpu_dev __initdata = {
},
},
.c_init = init_amd,
- .c_identify = generic_identify,
.c_size_cache = amd_size_cache,
};
diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
index bd75629dd26..8c25047975c 100644
--- a/arch/i386/kernel/cpu/centaur.c
+++ b/arch/i386/kernel/cpu/centaur.c
@@ -9,7 +9,7 @@
#ifdef CONFIG_X86_OOSTORE
-static u32 __init power2(u32 x)
+static u32 __cpuinit power2(u32 x)
{
u32 s=1;
while(s<=x)
@@ -22,7 +22,7 @@ static u32 __init power2(u32 x)
* Set up an actual MCR
*/
-static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
{
u32 lo, hi;
@@ -40,7 +40,7 @@ static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key)
* Shortcut: We know you can't put 4Gig of RAM on a winchip
*/
-static u32 __init ramtop(void) /* 16388 */
+static u32 __cpuinit ramtop(void) /* 16388 */
{
int i;
u32 top = 0;
@@ -91,7 +91,7 @@ static u32 __init ramtop(void) /* 16388 */
* Compute a set of MCR's to give maximum coverage
*/
-static int __init centaur_mcr_compute(int nr, int key)
+static int __cpuinit centaur_mcr_compute(int nr, int key)
{
u32 mem = ramtop();
u32 root = power2(mem);
@@ -166,7 +166,7 @@ static int __init centaur_mcr_compute(int nr, int key)
return ct;
}
-static void __init centaur_create_optimal_mcr(void)
+static void __cpuinit centaur_create_optimal_mcr(void)
{
int i;
/*
@@ -189,7 +189,7 @@ static void __init centaur_create_optimal_mcr(void)
wrmsr(MSR_IDT_MCR0+i, 0, 0);
}
-static void __init winchip2_create_optimal_mcr(void)
+static void __cpuinit winchip2_create_optimal_mcr(void)
{
u32 lo, hi;
int i;
@@ -227,7 +227,7 @@ static void __init winchip2_create_optimal_mcr(void)
* Handle the MCR key on the Winchip 2.
*/
-static void __init winchip2_unprotect_mcr(void)
+static void __cpuinit winchip2_unprotect_mcr(void)
{
u32 lo, hi;
u32 key;
@@ -239,7 +239,7 @@ static void __init winchip2_unprotect_mcr(void)
wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
}
-static void __init winchip2_protect_mcr(void)
+static void __cpuinit winchip2_protect_mcr(void)
{
u32 lo, hi;
@@ -257,7 +257,7 @@ static void __init winchip2_protect_mcr(void)
#define RNG_ENABLED (1 << 3)
#define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */
-static void __init init_c3(struct cpuinfo_x86 *c)
+static void __cpuinit init_c3(struct cpuinfo_x86 *c)
{
u32 lo, hi;
@@ -303,7 +303,7 @@ static void __init init_c3(struct cpuinfo_x86 *c)
display_cacheinfo(c);
}
-static void __init init_centaur(struct cpuinfo_x86 *c)
+static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
{
enum {
ECX8=1<<1,
@@ -442,7 +442,7 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
}
}
-static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
{
/* VIA C3 CPUs (670-68F) need further shifting. */
if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
@@ -457,7 +457,7 @@ static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size
return size;
}
-static struct cpu_dev centaur_cpu_dev __initdata = {
+static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
.c_vendor = "Centaur",
.c_ident = { "CentaurHauls" },
.c_init = init_centaur,
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 70c87de582c..2799baaadf4 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -36,7 +36,7 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
extern int disable_pse;
-static void default_init(struct cpuinfo_x86 * c)
+static void __cpuinit default_init(struct cpuinfo_x86 * c)
{
/* Not much we can do here... */
/* Check if at least it has cpuid */
@@ -49,7 +49,7 @@ static void default_init(struct cpuinfo_x86 * c)
}
}
-static struct cpu_dev default_cpu = {
+static struct cpu_dev __cpuinitdata default_cpu = {
.c_init = default_init,
.c_vendor = "Unknown",
};
@@ -265,7 +265,7 @@ static void __init early_cpu_detect(void)
}
}
-void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
{
u32 tfms, xlvl;
int ebx;
@@ -675,7 +675,7 @@ old_gdt:
#endif
/* Clear %fs and %gs. */
- asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
+ asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
/* Clear all 6 debug registers: */
set_debugreg(0, 0);
diff --git a/arch/i386/kernel/cpu/cpu.h b/arch/i386/kernel/cpu/cpu.h
index 5a1d4f163e8..2f6432cef6f 100644
--- a/arch/i386/kernel/cpu/cpu.h
+++ b/arch/i386/kernel/cpu/cpu.h
@@ -24,7 +24,5 @@ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
extern int get_model_name(struct cpuinfo_x86 *c);
extern void display_cacheinfo(struct cpuinfo_x86 *c);
-extern void generic_identify(struct cpuinfo_x86 * c);
-
extern void early_intel_workaround(struct cpuinfo_x86 *c);
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index f03b7f94c30..c0c3b59de32 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -12,7 +12,7 @@
/*
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
*/
-static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
{
unsigned char ccr2, ccr3;
unsigned long flags;
@@ -52,25 +52,25 @@ static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
* Actually since bugs.h doesn't even reference this perhaps someone should
* fix the documentation ???
*/
-static unsigned char Cx86_dir0_msb __initdata = 0;
+static unsigned char Cx86_dir0_msb __cpuinitdata = 0;
-static char Cx86_model[][9] __initdata = {
+static char Cx86_model[][9] __cpuinitdata = {
"Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
"M II ", "Unknown"
};
-static char Cx486_name[][5] __initdata = {
+static char Cx486_name[][5] __cpuinitdata = {
"SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
"SRx2", "DRx2"
};
-static char Cx486S_name[][4] __initdata = {
+static char Cx486S_name[][4] __cpuinitdata = {
"S", "S2", "Se", "S2e"
};
-static char Cx486D_name[][4] __initdata = {
+static char Cx486D_name[][4] __cpuinitdata = {
"DX", "DX2", "?", "?", "?", "DX4"
};
-static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
-static char cyrix_model_mult1[] __initdata = "12??43";
-static char cyrix_model_mult2[] __initdata = "12233445";
+static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock";
+static char cyrix_model_mult1[] __cpuinitdata = "12??43";
+static char cyrix_model_mult2[] __cpuinitdata = "12233445";
/*
* Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
@@ -82,7 +82,7 @@ static char cyrix_model_mult2[] __initdata = "12233445";
extern void calibrate_delay(void) __init;
-static void __init check_cx686_slop(struct cpuinfo_x86 *c)
+static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
{
unsigned long flags;
@@ -107,7 +107,7 @@ static void __init check_cx686_slop(struct cpuinfo_x86 *c)
}
-static void __init set_cx86_reorder(void)
+static void __cpuinit set_cx86_reorder(void)
{
u8 ccr3;
@@ -122,7 +122,7 @@ static void __init set_cx86_reorder(void)
setCx86(CX86_CCR3, ccr3);
}
-static void __init set_cx86_memwb(void)
+static void __cpuinit set_cx86_memwb(void)
{
u32 cr0;
@@ -137,7 +137,7 @@ static void __init set_cx86_memwb(void)
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
}
-static void __init set_cx86_inc(void)
+static void __cpuinit set_cx86_inc(void)
{
unsigned char ccr3;
@@ -158,7 +158,7 @@ static void __init set_cx86_inc(void)
* Configure later MediaGX and/or Geode processor.
*/
-static void __init geode_configure(void)
+static void __cpuinit geode_configure(void)
{
unsigned long flags;
u8 ccr3, ccr4;
@@ -184,14 +184,14 @@ static void __init geode_configure(void)
#ifdef CONFIG_PCI
-static struct pci_device_id __initdata cyrix_55x0[] = {
+static struct pci_device_id __cpuinitdata cyrix_55x0[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
{ },
};
#endif
-static void __init init_cyrix(struct cpuinfo_x86 *c)
+static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
{
unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
char *buf = c->x86_model_id;
@@ -346,7 +346,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
/*
* Handle National Semiconductor branded processors
*/
-static void __init init_nsc(struct cpuinfo_x86 *c)
+static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
{
/* There may be GX1 processors in the wild that are branded
* NSC and not Cyrix.
@@ -394,7 +394,7 @@ static inline int test_cyrix_52div(void)
return (unsigned char) (test >> 8) == 0x02;
}
-static void cyrix_identify(struct cpuinfo_x86 * c)
+static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
{
/* Detect Cyrix with disabled CPUID */
if ( c->x86 == 4 && test_cyrix_52div() ) {
@@ -427,10 +427,9 @@ static void cyrix_identify(struct cpuinfo_x86 * c)
local_irq_restore(flags);
}
}
- generic_identify(c);
}
-static struct cpu_dev cyrix_cpu_dev __initdata = {
+static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
.c_vendor = "Cyrix",
.c_ident = { "CyrixInstead" },
.c_init = init_cyrix,
@@ -453,11 +452,10 @@ static int __init cyrix_exit_cpu(void)
late_initcall(cyrix_exit_cpu);
-static struct cpu_dev nsc_cpu_dev __initdata = {
+static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
.c_vendor = "NSC",
.c_ident = { "Geode by NSC" },
.c_init = init_nsc,
- .c_identify = generic_identify,
};
int __init nsc_init_cpu(void)
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 5a2e270924b..94a95aa5227 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -198,7 +198,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
}
-static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
{
/* Intel PIII Tualatin. This comes in two flavours.
* One has 256kb of cache, the other 512. We have no way
@@ -263,7 +263,6 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
},
},
.c_init = init_intel,
- .c_identify = generic_identify,
.c_size_cache = intel_size_cache,
};
diff --git a/arch/i386/kernel/cpu/mcheck/Makefile b/arch/i386/kernel/cpu/mcheck/Makefile
index 30808f3d671..f1ebe1c1c17 100644
--- a/arch/i386/kernel/cpu/mcheck/Makefile
+++ b/arch/i386/kernel/cpu/mcheck/Makefile
@@ -1,2 +1,2 @@
-obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o
+obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o therm_throt.o
obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
index b95f1b3d53a..504434a4601 100644
--- a/arch/i386/kernel/cpu/mcheck/p4.c
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -13,6 +13,8 @@
#include <asm/msr.h>
#include <asm/apic.h>
+#include <asm/therm_throt.h>
+
#include "mce.h"
/* as supported by the P4/Xeon family */
@@ -44,25 +46,12 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs)
/* P4/Xeon Thermal transition interrupt handler */
static void intel_thermal_interrupt(struct pt_regs *regs)
{
- u32 l, h;
- unsigned int cpu = smp_processor_id();
- static unsigned long next[NR_CPUS];
+ __u64 msr_val;
ack_APIC_irq();
- if (time_after(next[cpu], jiffies))
- return;
-
- next[cpu] = jiffies + HZ*5;
- rdmsr(MSR_IA32_THERM_STATUS, l, h);
- if (l & 0x1) {
- printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu);
- printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n",
- cpu);
- add_taint(TAINT_MACHINE_CHECK);
- } else {
- printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
- }
+ rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+ therm_throt_process(msr_val & 0x1);
}
/* Thermal interrupt handler for this CPU setup */
@@ -122,10 +111,13 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
rdmsr (MSR_IA32_MISC_ENABLE, l, h);
wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h);
-
+
l = apic_read (APIC_LVTTHMR);
apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
+
+ /* enable thermal throttle processing */
+ atomic_set(&therm_throt_en, 1);
return;
}
#endif /* CONFIG_X86_MCE_P4THERMAL */
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
new file mode 100644
index 00000000000..4f43047de40
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c
@@ -0,0 +1,180 @@
+/*
+ * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c
+ *
+ * Thermal throttle event support code (such as syslog messaging and rate
+ * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
+ * This allows consistent reporting of CPU thermal throttle events.
+ *
+ * Maintains a counter in /sys that keeps track of the number of thermal
+ * events, such that the user knows how bad the thermal problem might be
+ * (since the logging to syslog and mcelog is rate limited).
+ *
+ * Author: Dmitriy Zavin (dmitriyz@google.com)
+ *
+ * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
+ * Inspired by Ross Biro's and Al Borchers' counter code.
+ */
+
+#include <linux/percpu.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <asm/cpu.h>
+#include <linux/notifier.h>
+#include <asm/therm_throt.h>
+
+/* How long to wait between reporting thermal events */
+#define CHECK_INTERVAL (300 * HZ)
+
+static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
+static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
+atomic_t therm_throt_en = ATOMIC_INIT(0);
+
+#ifdef CONFIG_SYSFS
+#define define_therm_throt_sysdev_one_ro(_name) \
+ static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
+
+#define define_therm_throt_sysdev_show_func(name) \
+static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \
+ char *buf) \
+{ \
+ unsigned int cpu = dev->id; \
+ ssize_t ret; \
+ \
+ preempt_disable(); /* CPU hotplug */ \
+ if (cpu_online(cpu)) \
+ ret = sprintf(buf, "%lu\n", \
+ per_cpu(thermal_throttle_##name, cpu)); \
+ else \
+ ret = 0; \
+ preempt_enable(); \
+ \
+ return ret; \
+}
+
+define_therm_throt_sysdev_show_func(count);
+define_therm_throt_sysdev_one_ro(count);
+
+static struct attribute *thermal_throttle_attrs[] = {
+ &attr_count.attr,
+ NULL
+};
+
+static struct attribute_group thermal_throttle_attr_group = {
+ .attrs = thermal_throttle_attrs,
+ .name = "thermal_throttle"
+};
+#endif /* CONFIG_SYSFS */
+
+/***
+ * therm_throt_process - Process thermal throttling event from interrupt
+ * @curr: Whether the condition is current or not (boolean), since the
+ * thermal interrupt normally gets called both when the thermal
+ * event begins and once the event has ended.
+ *
+ * This function is called by the thermal interrupt after the
+ * IRQ has been acknowledged.
+ *
+ * It will take care of rate limiting and printing messages to the syslog.
+ *
+ * Returns: 0 : Event should NOT be further logged, i.e. still in
+ * "timeout" from previous log message.
+ * 1 : Event should be logged further, and a message has been
+ * printed to the syslog.
+ */
+int therm_throt_process(int curr)
+{
+ unsigned int cpu = smp_processor_id();
+ __u64 tmp_jiffs = get_jiffies_64();
+
+ if (curr)
+ __get_cpu_var(thermal_throttle_count)++;
+
+ if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
+ return 0;
+
+ __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
+
+ /* if we just entered the thermal event */
+ if (curr) {
+ printk(KERN_CRIT "CPU%d: Temperature above threshold, "
+ "cpu clock throttled (total events = %lu)\n", cpu,
+ __get_cpu_var(thermal_throttle_count));
+
+ add_taint(TAINT_MACHINE_CHECK);
+ } else {
+ printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
+ }
+
+ return 1;
+}
+
+#ifdef CONFIG_SYSFS
+/* Add/Remove thermal_throttle interface for CPU device */
+static __cpuinit int thermal_throttle_add_dev(struct sys_device * sys_dev)
+{
+ sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+ return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static __cpuinit int thermal_throttle_remove_dev(struct sys_device * sys_dev)
+{
+ sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+ return 0;
+}
+
+/* Mutex protecting device creation against CPU hotplug */
+static DEFINE_MUTEX(therm_cpu_lock);
+
+/* Get notified when a cpu comes on/off. Be hotplug friendly. */
+static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ struct sys_device *sys_dev;
+
+ sys_dev = get_cpu_sysdev(cpu);
+ mutex_lock(&therm_cpu_lock);
+ switch (action) {
+ case CPU_ONLINE:
+ thermal_throttle_add_dev(sys_dev);
+ break;
+ case CPU_DEAD:
+ thermal_throttle_remove_dev(sys_dev);
+ break;
+ }
+ mutex_unlock(&therm_cpu_lock);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block thermal_throttle_cpu_notifier =
+{
+ .notifier_call = thermal_throttle_cpu_callback,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static __init int thermal_throttle_init_device(void)
+{
+ unsigned int cpu = 0;
+
+ if (!atomic_read(&therm_throt_en))
+ return 0;
+
+ register_hotcpu_notifier(&thermal_throttle_cpu_notifier);
+
+#ifdef CONFIG_HOTPLUG_CPU
+ mutex_lock(&therm_cpu_lock);
+#endif
+ /* connect live CPUs to sysfs */
+ for_each_online_cpu(cpu)
+ thermal_throttle_add_dev(get_cpu_sysdev(cpu));
+#ifdef CONFIG_HOTPLUG_CPU
+ mutex_unlock(&therm_cpu_lock);
+#endif
+
+ return 0;
+}
+
+device_initcall(thermal_throttle_init_device);
+#endif /* CONFIG_SYSFS */
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index 169ac8e0db6..0b61eed8bbd 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -243,7 +243,7 @@ static DEFINE_SPINLOCK(set_atomicity_lock);
* has been called.
*/
-static void prepare_set(void)
+static void prepare_set(void) __acquires(set_atomicity_lock)
{
unsigned long cr0;
@@ -274,7 +274,7 @@ static void prepare_set(void)
mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
}
-static void post_set(void)
+static void post_set(void) __releases(set_atomicity_lock)
{
/* Flush TLBs (no need to flush caches - they are disabled) */
__flush_tlb();
diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
index ad87fa58058..8bf23cc80c6 100644
--- a/arch/i386/kernel/cpu/nexgen.c
+++ b/arch/i386/kernel/cpu/nexgen.c
@@ -10,7 +10,7 @@
* to have CPUID. (Thanks to Herbert Oppmann)
*/
-static int __init deep_magic_nexgen_probe(void)
+static int __cpuinit deep_magic_nexgen_probe(void)
{
int ret;
@@ -27,21 +27,20 @@ static int __init deep_magic_nexgen_probe(void)
return ret;
}
-static void __init init_nexgen(struct cpuinfo_x86 * c)
+static void __cpuinit init_nexgen(struct cpuinfo_x86 * c)
{
c->x86_cache_size = 256; /* A few had 1 MB... */
}
-static void __init nexgen_identify(struct cpuinfo_x86 * c)
+static void __cpuinit nexgen_identify(struct cpuinfo_x86 * c)
{
/* Detect NexGen with old hypercode */
if ( deep_magic_nexgen_probe() ) {
strcpy(c->x86_vendor_id, "NexGenDriven");
}
- generic_identify(c);
}
-static struct cpu_dev nexgen_cpu_dev __initdata = {
+static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
.c_vendor = "Nexgen",
.c_ident = { "NexGenDriven" },
.c_models = {
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index f54a15268ed..76aac088a32 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -46,8 +46,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Intel-defined (#2) */
"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
- "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+ NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* VIA/Cyrix/Centaur-defined */
diff --git a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c
index d08d5a2811c..9317f741498 100644
--- a/arch/i386/kernel/cpu/rise.c
+++ b/arch/i386/kernel/cpu/rise.c
@@ -5,7 +5,7 @@
#include "cpu.h"
-static void __init init_rise(struct cpuinfo_x86 *c)
+static void __cpuinit init_rise(struct cpuinfo_x86 *c)
{
printk("CPU: Rise iDragon");
if (c->x86_model > 2)
@@ -28,7 +28,7 @@ static void __init init_rise(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_CX8, c->x86_capability);
}
-static struct cpu_dev rise_cpu_dev __initdata = {
+static struct cpu_dev rise_cpu_dev __cpuinitdata = {
.c_vendor = "Rise",
.c_ident = { "RiseRiseRise" },
.c_models = {
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
index 7214c9b577a..4056fb7d2cd 100644
--- a/arch/i386/kernel/cpu/transmeta.c
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -5,7 +5,7 @@
#include <asm/msr.h>
#include "cpu.h"
-static void __init init_transmeta(struct cpuinfo_x86 *c)
+static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
{
unsigned int cap_mask, uk, max, dummy;
unsigned int cms_rev1, cms_rev2;
@@ -85,10 +85,9 @@ static void __init init_transmeta(struct cpuinfo_x86 *c)
#endif
}
-static void __init transmeta_identify(struct cpuinfo_x86 * c)
+static void __cpuinit transmeta_identify(struct cpuinfo_x86 * c)
{
u32 xlvl;
- generic_identify(c);
/* Transmeta-defined flags: level 0x80860001 */
xlvl = cpuid_eax(0x80860000);
@@ -98,7 +97,7 @@ static void __init transmeta_identify(struct cpuinfo_x86 * c)
}
}
-static struct cpu_dev transmeta_cpu_dev __initdata = {
+static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
.c_vendor = "Transmeta",
.c_ident = { "GenuineTMx86", "TransmetaCPU" },
.c_init = init_transmeta,
diff --git a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c
index 2cd988f6dc5..1bf3f87e9c5 100644
--- a/arch/i386/kernel/cpu/umc.c
+++ b/arch/i386/kernel/cpu/umc.c
@@ -5,12 +5,8 @@
/* UMC chips appear to be only either 386 or 486, so no special init takes place.
*/
-static void __init init_umc(struct cpuinfo_x86 * c)
-{
-
-}
-static struct cpu_dev umc_cpu_dev __initdata = {
+static struct cpu_dev umc_cpu_dev __cpuinitdata = {
.c_vendor = "UMC",
.c_ident = { "UMC UMC UMC" },
.c_models = {
@@ -21,7 +17,6 @@ static struct cpu_dev umc_cpu_dev __initdata = {
}
},
},
- .c_init = init_umc,
};
int __init umc_init_cpu(void)
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 5b96f038367..67d297dc100 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -22,6 +22,8 @@
#include <asm/nmi.h>
#include <asm/hw_irq.h>
#include <asm/apic.h>
+#include <asm/kdebug.h>
+
#include <mach_ipi.h>
@@ -93,16 +95,25 @@ static void crash_save_self(struct pt_regs *regs)
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
static atomic_t waiting_for_crash_ipi;
-static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+static int crash_nmi_callback(struct notifier_block *self,
+ unsigned long val, void *data)
{
+ struct pt_regs *regs;
struct pt_regs fixed_regs;
+ int cpu;
+
+ if (val != DIE_NMI_IPI)
+ return NOTIFY_OK;
+
+ regs = ((struct die_args *)data)->regs;
+ cpu = raw_smp_processor_id();
/* Don't do anything if this handler is invoked on crashing cpu.
* Otherwise, system will completely hang. Crashing cpu can get
* an NMI if system was initially booted with nmi_watchdog parameter.
*/
if (cpu == crashing_cpu)
- return 1;
+ return NOTIFY_STOP;
local_irq_disable();
if (!user_mode_vm(regs)) {
@@ -125,13 +136,18 @@ static void smp_send_nmi_allbutself(void)
send_IPI_allbutself(NMI_VECTOR);
}
+static struct notifier_block crash_nmi_nb = {
+ .notifier_call = crash_nmi_callback,
+};
+
static void nmi_shootdown_cpus(void)
{
unsigned long msecs;
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
/* Would it be better to replace the trap vector here? */
- set_nmi_callback(crash_nmi_callback);
+ if (register_die_notifier(&crash_nmi_nb))
+ return; /* return what? */
/* Ensure the new callback function is set before sending
* out the NMI
*/
diff --git a/arch/i386/kernel/efi_stub.S b/arch/i386/kernel/efi_stub.S
index d3ee73a3eee..ef00bb77d7e 100644
--- a/arch/i386/kernel/efi_stub.S
+++ b/arch/i386/kernel/efi_stub.S
@@ -7,7 +7,6 @@
#include <linux/linkage.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
/*
* efi_call_phys(void *, ...) is a function with variable parameters.
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 87f9f60b803..5a63d6fdb70 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -76,8 +76,15 @@ DF_MASK = 0x00000400
NT_MASK = 0x00004000
VM_MASK = 0x00020000
+/* These are replaces for paravirtualization */
+#define DISABLE_INTERRUPTS cli
+#define ENABLE_INTERRUPTS sti
+#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
+#define INTERRUPT_RETURN iret
+#define GET_CR0_INTO_EAX movl %cr0, %eax
+
#ifdef CONFIG_PREEMPT
-#define preempt_stop cli; TRACE_IRQS_OFF
+#define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF
#else
#define preempt_stop
#define resume_kernel restore_nocheck
@@ -176,18 +183,21 @@ VM_MASK = 0x00020000
#define RING0_INT_FRAME \
CFI_STARTPROC simple;\
+ CFI_SIGNAL_FRAME;\
CFI_DEF_CFA esp, 3*4;\
/*CFI_OFFSET cs, -2*4;*/\
CFI_OFFSET eip, -3*4
#define RING0_EC_FRAME \
CFI_STARTPROC simple;\
+ CFI_SIGNAL_FRAME;\
CFI_DEF_CFA esp, 4*4;\
/*CFI_OFFSET cs, -2*4;*/\
CFI_OFFSET eip, -3*4
#define RING0_PTREGS_FRAME \
CFI_STARTPROC simple;\
+ CFI_SIGNAL_FRAME;\
CFI_DEF_CFA esp, OLDESP-EBX;\
/*CFI_OFFSET cs, CS-OLDESP;*/\
CFI_OFFSET eip, EIP-OLDESP;\
@@ -233,10 +243,11 @@ ret_from_intr:
check_userspace:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
- testl $(VM_MASK | 3), %eax
- jz resume_kernel
+ andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
+ cmpl $USER_RPL, %eax
+ jb resume_kernel # not returning to v8086 or userspace
ENTRY(resume_userspace)
- cli # make sure we don't miss an interrupt
+ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
movl TI_flags(%ebp), %ecx
@@ -247,7 +258,7 @@ ENTRY(resume_userspace)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
- cli
+ DISABLE_INTERRUPTS
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
jnz restore_nocheck
need_resched:
@@ -267,6 +278,7 @@ need_resched:
# sysenter call handler stub
ENTRY(sysenter_entry)
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA esp, 0
CFI_REGISTER esp, ebp
movl TSS_sysenter_esp0(%esp),%esp
@@ -275,7 +287,7 @@ sysenter_past_esp:
* No need to follow this irqs on/off section: the syscall
* disabled irqs and here we enable it straight after entry:
*/
- sti
+ ENABLE_INTERRUPTS
pushl $(__USER_DS)
CFI_ADJUST_CFA_OFFSET 4
/*CFI_REL_OFFSET ss, 0*/
@@ -320,7 +332,7 @@ sysenter_past_esp:
jae syscall_badsys
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp)
- cli
+ DISABLE_INTERRUPTS
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx
@@ -330,8 +342,7 @@ sysenter_past_esp:
movl OLDESP(%esp), %ecx
xorl %ebp,%ebp
TRACE_IRQS_ON
- sti
- sysexit
+ ENABLE_INTERRUPTS_SYSEXIT
CFI_ENDPROC
@@ -356,7 +367,7 @@ syscall_call:
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp) # store the return value
syscall_exit:
- cli # make sure we don't miss an interrupt
+ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
@@ -371,8 +382,8 @@ restore_all:
# See comments in process.c:copy_thread() for details.
movb OLDSS(%esp), %ah
movb CS(%esp), %al
- andl $(VM_MASK | (4 << 8) | 3), %eax
- cmpl $((4 << 8) | 3), %eax
+ andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+ cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
restore_nocheck:
@@ -381,11 +392,11 @@ restore_nocheck_notrace:
RESTORE_REGS
addl $4, %esp
CFI_ADJUST_CFA_OFFSET -4
-1: iret
+1: INTERRUPT_RETURN
.section .fixup,"ax"
iret_exc:
TRACE_IRQS_ON
- sti
+ ENABLE_INTERRUPTS
pushl $0 # no error code
pushl $do_iret_error
jmp error_code
@@ -409,7 +420,7 @@ ldt_ss:
* dosemu and wine happy. */
subl $8, %esp # reserve space for switch16 pointer
CFI_ADJUST_CFA_OFFSET 8
- cli
+ DISABLE_INTERRUPTS
TRACE_IRQS_OFF
movl %esp, %eax
/* Set up the 16bit stack frame with switch32 pointer on top,
@@ -419,7 +430,7 @@ ldt_ss:
TRACE_IRQS_IRET
RESTORE_REGS
lss 20+4(%esp), %esp # switch to 16bit stack
-1: iret
+1: INTERRUPT_RETURN
.section __ex_table,"a"
.align 4
.long 1b,iret_exc
@@ -434,7 +445,7 @@ work_pending:
jz work_notifysig
work_resched:
call schedule
- cli # make sure we don't miss an interrupt
+ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
@@ -490,7 +501,7 @@ syscall_exit_work:
testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
jz work_pending
TRACE_IRQS_ON
- sti # could let do_syscall_trace() call
+ ENABLE_INTERRUPTS # could let do_syscall_trace() call
# schedule() instead
movl %esp, %eax
movl $1, %edx
@@ -591,11 +602,9 @@ ENTRY(name) \
/* The include is where all of the SMP etc. interrupts come from */
#include "entry_arch.h"
-ENTRY(divide_error)
- RING0_INT_FRAME
- pushl $0 # no error code
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_divide_error
+KPROBE_ENTRY(page_fault)
+ RING0_EC_FRAME
+ pushl $do_page_fault
CFI_ADJUST_CFA_OFFSET 4
ALIGN
error_code:
@@ -645,6 +654,7 @@ error_code:
call *%edi
jmp ret_from_exception
CFI_ENDPROC
+KPROBE_END(page_fault)
ENTRY(coprocessor_error)
RING0_INT_FRAME
@@ -669,7 +679,7 @@ ENTRY(device_not_available)
pushl $-1 # mark this as an int
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
- movl %cr0, %eax
+ GET_CR0_INTO_EAX
testl $0x4, %eax # EM (math emulation bit)
jne device_not_available_emulate
preempt_stop
@@ -702,9 +712,15 @@ device_not_available_emulate:
jne ok; \
label: \
movl TSS_sysenter_esp0+offset(%esp),%esp; \
+ CFI_DEF_CFA esp, 0; \
+ CFI_UNDEFINED eip; \
pushfl; \
+ CFI_ADJUST_CFA_OFFSET 4; \
pushl $__KERNEL_CS; \
- pushl $sysenter_past_esp
+ CFI_ADJUST_CFA_OFFSET 4; \
+ pushl $sysenter_past_esp; \
+ CFI_ADJUST_CFA_OFFSET 4; \
+ CFI_REL_OFFSET eip, 0
KPROBE_ENTRY(debug)
RING0_INT_FRAME
@@ -720,7 +736,8 @@ debug_stack_correct:
call do_debug
jmp ret_from_exception
CFI_ENDPROC
- .previous .text
+KPROBE_END(debug)
+
/*
* NMI is doubly nasty. It can happen _while_ we're handling
* a debug fault, and the debug fault hasn't yet been able to
@@ -729,7 +746,7 @@ debug_stack_correct:
* check whether we got an NMI on the debug path where the debug
* fault happened on the sysenter path.
*/
-ENTRY(nmi)
+KPROBE_ENTRY(nmi)
RING0_INT_FRAME
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
@@ -754,6 +771,7 @@ ENTRY(nmi)
cmpl $sysenter_entry,12(%esp)
je nmi_debug_stack_check
nmi_stack_correct:
+ /* We have a RING0_INT_FRAME here */
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
@@ -764,9 +782,12 @@ nmi_stack_correct:
CFI_ENDPROC
nmi_stack_fixup:
+ RING0_INT_FRAME
FIX_STACK(12,nmi_stack_correct, 1)
jmp nmi_stack_correct
+
nmi_debug_stack_check:
+ /* We have a RING0_INT_FRAME here */
cmpw $__KERNEL_CS,16(%esp)
jne nmi_stack_correct
cmpl $debug,(%esp)
@@ -777,8 +798,10 @@ nmi_debug_stack_check:
jmp nmi_stack_correct
nmi_16bit_stack:
- RING0_INT_FRAME
- /* create the pointer to lss back */
+ /* We have a RING0_INT_FRAME here.
+ *
+ * create the pointer to lss back
+ */
pushl %ss
CFI_ADJUST_CFA_OFFSET 4
pushl %esp
@@ -799,12 +822,13 @@ nmi_16bit_stack:
call do_nmi
RESTORE_REGS
lss 12+4(%esp), %esp # back to 16bit stack
-1: iret
+1: INTERRUPT_RETURN
CFI_ENDPROC
.section __ex_table,"a"
.align 4
.long 1b,iret_exc
.previous
+KPROBE_END(nmi)
KPROBE_ENTRY(int3)
RING0_INT_FRAME
@@ -816,7 +840,7 @@ KPROBE_ENTRY(int3)
call do_int3
jmp ret_from_exception
CFI_ENDPROC
- .previous .text
+KPROBE_END(int3)
ENTRY(overflow)
RING0_INT_FRAME
@@ -881,7 +905,7 @@ KPROBE_ENTRY(general_protection)
CFI_ADJUST_CFA_OFFSET 4
jmp error_code
CFI_ENDPROC
- .previous .text
+KPROBE_END(general_protection)
ENTRY(alignment_check)
RING0_EC_FRAME
@@ -890,13 +914,14 @@ ENTRY(alignment_check)
jmp error_code
CFI_ENDPROC
-KPROBE_ENTRY(page_fault)
- RING0_EC_FRAME
- pushl $do_page_fault
+ENTRY(divide_error)
+ RING0_INT_FRAME
+ pushl $0 # no error code
+ CFI_ADJUST_CFA_OFFSET 4
+ pushl $do_divide_error
CFI_ADJUST_CFA_OFFSET 4
jmp error_code
CFI_ENDPROC
- .previous .text
#ifdef CONFIG_X86_MCE
ENTRY(machine_check)
@@ -949,6 +974,19 @@ ENTRY(arch_unwind_init_running)
ENDPROC(arch_unwind_init_running)
#endif
+ENTRY(kernel_thread_helper)
+ pushl $0 # fake return address for unwinder
+ CFI_STARTPROC
+ movl %edx,%eax
+ push %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ call *%ebx
+ push %eax
+ CFI_ADJUST_CFA_OFFSET 4
+ call do_exit
+ CFI_ENDPROC
+ENDPROC(kernel_thread_helper)
+
.section .rodata,"a"
#include "syscall_table.S"
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index a6b8bd89aa2..be9d883c62c 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -371,8 +371,65 @@ rp_sidt:
addl $8,%edi
dec %ecx
jne rp_sidt
+
+.macro set_early_handler handler,trapno
+ lea \handler,%edx
+ movl $(__KERNEL_CS << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
+ lea idt_table,%edi
+ movl %eax,8*\trapno(%edi)
+ movl %edx,8*\trapno+4(%edi)
+.endm
+
+ set_early_handler handler=early_divide_err,trapno=0
+ set_early_handler handler=early_illegal_opcode,trapno=6
+ set_early_handler handler=early_protection_fault,trapno=13
+ set_early_handler handler=early_page_fault,trapno=14
+
ret
+early_divide_err:
+ xor %edx,%edx
+ pushl $0 /* fake errcode */
+ jmp early_fault
+
+early_illegal_opcode:
+ movl $6,%edx
+ pushl $0 /* fake errcode */
+ jmp early_fault
+
+early_protection_fault:
+ movl $13,%edx
+ jmp early_fault
+
+early_page_fault:
+ movl $14,%edx
+ jmp early_fault
+
+early_fault:
+ cld
+#ifdef CONFIG_PRINTK
+ movl $(__KERNEL_DS),%eax
+ movl %eax,%ds
+ movl %eax,%es
+ cmpl $2,early_recursion_flag
+ je hlt_loop
+ incl early_recursion_flag
+ movl %cr2,%eax
+ pushl %eax
+ pushl %edx /* trapno */
+ pushl $fault_msg
+#ifdef CONFIG_EARLY_PRINTK
+ call early_printk
+#else
+ call printk
+#endif
+#endif
+hlt_loop:
+ hlt
+ jmp hlt_loop
+
/* This is the default interrupt "handler" :-) */
ALIGN
ignore_int:
@@ -386,6 +443,9 @@ ignore_int:
movl $(__KERNEL_DS),%eax
movl %eax,%ds
movl %eax,%es
+ cmpl $2,early_recursion_flag
+ je hlt_loop
+ incl early_recursion_flag
pushl 16(%esp)
pushl 24(%esp)
pushl 32(%esp)
@@ -431,9 +491,16 @@ ENTRY(stack_start)
ready: .byte 0
+early_recursion_flag:
+ .long 0
+
int_msg:
.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
+fault_msg:
+ .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n"
+ .asciz "Stack: %p %p %p %p %p %p %p %p\n"
+
/*
* The IDT and GDT 'descriptors' are a strange 48-bit object
* only used by the lidt and lgdt instructions. They are not
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index d4756d154f4..ea5f4e7958d 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -45,6 +45,8 @@ static void end_8259A_irq (unsigned int irq)
#define shutdown_8259A_irq disable_8259A_irq
+static int i8259A_auto_eoi;
+
static void mask_and_ack_8259A(unsigned int);
unsigned int startup_8259A_irq(unsigned int irq)
@@ -253,7 +255,7 @@ static void save_ELCR(char *trigger)
static int i8259A_resume(struct sys_device *dev)
{
- init_8259A(0);
+ init_8259A(i8259A_auto_eoi);
restore_ELCR(irq_trigger);
return 0;
}
@@ -301,6 +303,8 @@ void init_8259A(int auto_eoi)
{
unsigned long flags;
+ i8259A_auto_eoi = auto_eoi;
+
spin_lock_irqsave(&i8259A_lock, flags);
outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 4fb32c551fe..fd0df75cfbd 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -40,6 +40,7 @@
#include <asm/nmi.h>
#include <mach_apic.h>
+#include <mach_apicdef.h>
#include "io_ports.h"
@@ -65,7 +66,7 @@ int sis_apic_bug = -1;
*/
int nr_ioapic_registers[MAX_IO_APICS];
-int disable_timer_pin_1 __initdata;
+static int disable_timer_pin_1 __initdata;
/*
* Rough estimation of how many shared IRQs there are, can
@@ -93,6 +94,34 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
#define vector_to_irq(vector) (vector)
#endif
+
+union entry_union {
+ struct { u32 w1, w2; };
+ struct IO_APIC_route_entry entry;
+};
+
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+ union entry_union eu;
+ unsigned long flags;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+ eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ return eu.entry;
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+ unsigned long flags;
+ union entry_union eu;
+ eu.entry = e;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+ io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
@@ -200,13 +229,9 @@ static void unmask_IO_APIC_irq (unsigned int irq)
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
- unsigned long flags;
/* Check delivery_mode to be sure we're not clearing an SMI pin */
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
- *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry = ioapic_read_entry(apic, pin);
if (entry.delivery_mode == dest_SMI)
return;
@@ -215,10 +240,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
*/
memset(&entry, 0, sizeof(entry));
entry.mask = 1;
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(apic, pin, entry);
}
static void clear_IO_APIC (void)
@@ -1283,9 +1305,8 @@ static void __init setup_IO_APIC_irqs(void)
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}
+ ioapic_write_entry(apic, pin, entry);
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
@@ -1301,7 +1322,6 @@ static void __init setup_IO_APIC_irqs(void)
static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
- unsigned long flags;
memset(&entry,0,sizeof(entry));
@@ -1331,10 +1351,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
/*
* Add it to the IO-APIC irq-routing table:
*/
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(apic, pin, entry);
enable_8259A_irq(0);
}
@@ -1444,10 +1461,7 @@ void __init print_IO_APIC(void)
for (i = 0; i <= reg_01.bits.entries; i++) {
struct IO_APIC_route_entry entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
- *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry = ioapic_read_entry(apic, i);
printk(KERN_DEBUG " %02x %03X %02X ",
i,
@@ -1666,10 +1680,7 @@ static void __init enable_IO_APIC(void)
/* See if any of the pins is in ExtINT mode */
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
- *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry = ioapic_read_entry(apic, pin);
/* If the interrupt line is enabled and in ExtInt mode
@@ -1726,7 +1737,6 @@ void disable_IO_APIC(void)
*/
if (ioapic_i8259.pin != -1) {
struct IO_APIC_route_entry entry;
- unsigned long flags;
memset(&entry, 0, sizeof(entry));
entry.mask = 0; /* Enabled */
@@ -1743,12 +1753,7 @@ void disable_IO_APIC(void)
/*
* Add it to the IO-APIC irq-routing table:
*/
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
- *(((int *)&entry)+1));
- io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
- *(((int *)&entry)+0));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
}
disconnect_bsp_APIC(ioapic_i8259.pin != -1);
}
@@ -2213,17 +2218,13 @@ static inline void unlock_ExtINT_logic(void)
int apic, pin, i;
struct IO_APIC_route_entry entry0, entry1;
unsigned char save_control, save_freq_select;
- unsigned long flags;
pin = find_isa_irq_pin(8, mp_INT);
apic = find_isa_irq_apic(8, mp_INT);
if (pin == -1)
return;
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
- *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry0 = ioapic_read_entry(apic, pin);
clear_IO_APIC_pin(apic, pin);
memset(&entry1, 0, sizeof(entry1));
@@ -2236,10 +2237,7 @@ static inline void unlock_ExtINT_logic(void)
entry1.trigger = 0;
entry1.vector = 0;
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(apic, pin, entry1);
save_control = CMOS_READ(RTC_CONTROL);
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
@@ -2258,10 +2256,7 @@ static inline void unlock_ExtINT_logic(void)
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
clear_IO_APIC_pin(apic, pin);
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(apic, pin, entry0);
}
int timer_uses_ioapic_pin_0;
@@ -2461,17 +2456,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
{
struct IO_APIC_route_entry *entry;
struct sysfs_ioapic_data *data;
- unsigned long flags;
int i;
data = container_of(dev, struct sysfs_ioapic_data, dev);
entry = data->entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
- *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
- }
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+ entry[i] = ioapic_read_entry(dev->id, i);
return 0;
}
@@ -2493,11 +2483,9 @@ static int ioapic_resume(struct sys_device *dev)
reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
io_apic_write(dev->id, 0, reg_00.raw);
}
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
- io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
- }
spin_unlock_irqrestore(&ioapic_lock, flags);
+ for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+ ioapic_write_entry(dev->id, i, entry[i]);
return 0;
}
@@ -2694,9 +2682,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
if (!ioapic && (irq < 16))
disable_8259A_irq(irq);
+ ioapic_write_entry(ioapic, pin, entry);
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -2704,3 +2691,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
}
#endif /* CONFIG_ACPI */
+
+static int __init parse_disable_timer_pin_1(char *arg)
+{
+ disable_timer_pin_1 = 1;
+ return 0;
+}
+early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
+
+static int __init parse_enable_timer_pin_1(char *arg)
+{
+ disable_timer_pin_1 = -1;
+ return 0;
+}
+early_param("enable_timer_pin_1", parse_enable_timer_pin_1);
+
+static int __init parse_noapic(char *arg)
+{
+ /* disable IO-APIC */
+ disable_ioapic_setup();
+ return 0;
+}
+early_param("noapic", parse_noapic);
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
index 6b1ae6ba76f..91966bafb3d 100644
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/kexec.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -20,70 +21,13 @@
#include <asm/system.h>
#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
-
-#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define L2_ATTR (_PAGE_PRESENT)
-
-#define LEVEL0_SIZE (1UL << 12UL)
-
-#ifndef CONFIG_X86_PAE
-#define LEVEL1_SIZE (1UL << 22UL)
-static u32 pgtable_level1[1024] PAGE_ALIGNED;
-
-static void identity_map_page(unsigned long address)
-{
- unsigned long level1_index, level2_index;
- u32 *pgtable_level2;
-
- /* Find the current page table */
- pgtable_level2 = __va(read_cr3());
-
- /* Find the indexes of the physical address to identity map */
- level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
- level2_index = address / LEVEL1_SIZE;
-
- /* Identity map the page table entry */
- pgtable_level1[level1_index] = address | L0_ATTR;
- pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
-
- /* Flush the tlb so the new mapping takes effect.
- * Global tlb entries are not flushed but that is not an issue.
- */
- load_cr3(pgtable_level2);
-}
-
-#else
-#define LEVEL1_SIZE (1UL << 21UL)
-#define LEVEL2_SIZE (1UL << 30UL)
-static u64 pgtable_level1[512] PAGE_ALIGNED;
-static u64 pgtable_level2[512] PAGE_ALIGNED;
-
-static void identity_map_page(unsigned long address)
-{
- unsigned long level1_index, level2_index, level3_index;
- u64 *pgtable_level3;
-
- /* Find the current page table */
- pgtable_level3 = __va(read_cr3());
-
- /* Find the indexes of the physical address to identity map */
- level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
- level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
- level3_index = address / LEVEL2_SIZE;
-
- /* Identity map the page table entry */
- pgtable_level1[level1_index] = address | L0_ATTR;
- pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
- set_64bit(&pgtable_level3[level3_index],
- __pa(pgtable_level2) | L2_ATTR);
-
- /* Flush the tlb so the new mapping takes effect.
- * Global tlb entries are not flushed but that is not an issue.
- */
- load_cr3(pgtable_level3);
-}
+static u32 kexec_pgd[1024] PAGE_ALIGNED;
+#ifdef CONFIG_X86_PAE
+static u32 kexec_pmd0[1024] PAGE_ALIGNED;
+static u32 kexec_pmd1[1024] PAGE_ALIGNED;
#endif
+static u32 kexec_pte0[1024] PAGE_ALIGNED;
+static u32 kexec_pte1[1024] PAGE_ALIGNED;
static void set_idt(void *newidt, __u16 limit)
{
@@ -127,16 +71,6 @@ static void load_segments(void)
#undef __STR
}
-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
- unsigned long indirection_page,
- unsigned long reboot_code_buffer,
- unsigned long start_address,
- unsigned int has_pae) ATTRIB_NORET;
-
-extern const unsigned char relocate_new_kernel[];
-extern void relocate_new_kernel_end(void);
-extern const unsigned int relocate_new_kernel_size;
-
/*
* A architecture hook called to validate the
* proposed image and prepare the control pages
@@ -169,25 +103,29 @@ void machine_kexec_cleanup(struct kimage *image)
*/
NORET_TYPE void machine_kexec(struct kimage *image)
{
- unsigned long page_list;
- unsigned long reboot_code_buffer;
-
- relocate_new_kernel_t rnk;
+ unsigned long page_list[PAGES_NR];
+ void *control_page;
/* Interrupts aren't acceptable while we reboot */
local_irq_disable();
- /* Compute some offsets */
- reboot_code_buffer = page_to_pfn(image->control_code_page)
- << PAGE_SHIFT;
- page_list = image->head;
-
- /* Set up an identity mapping for the reboot_code_buffer */
- identity_map_page(reboot_code_buffer);
-
- /* copy it out */
- memcpy((void *)reboot_code_buffer, relocate_new_kernel,
- relocate_new_kernel_size);
+ control_page = page_address(image->control_code_page);
+ memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+ page_list[PA_CONTROL_PAGE] = __pa(control_page);
+ page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
+ page_list[PA_PGD] = __pa(kexec_pgd);
+ page_list[VA_PGD] = (unsigned long)kexec_pgd;
+#ifdef CONFIG_X86_PAE
+ page_list[PA_PMD_0] = __pa(kexec_pmd0);
+ page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
+ page_list[PA_PMD_1] = __pa(kexec_pmd1);
+ page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
+#endif
+ page_list[PA_PTE_0] = __pa(kexec_pte0);
+ page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
+ page_list[PA_PTE_1] = __pa(kexec_pte1);
+ page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
/* The segment registers are funny things, they have both a
* visible and an invisible part. Whenever the visible part is
@@ -206,6 +144,28 @@ NORET_TYPE void machine_kexec(struct kimage *image)
set_idt(phys_to_virt(0),0);
/* now call it */
- rnk = (relocate_new_kernel_t) reboot_code_buffer;
- (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
+ relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
+ image->start, cpu_has_pae);
+}
+
+/* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel. By reserving this memory we guarantee
+ * that linux never sets it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+static int __init parse_crashkernel(char *arg)
+{
+ unsigned long size, base;
+ size = memparse(arg, &arg);
+ if (*arg == '@') {
+ base = memparse(arg+1, &arg);
+ /* FIXME: Do I want a sanity check
+ * to validate the memory range?
+ */
+ crashk_res.start = base;
+ crashk_res.end = base + size - 1;
+ }
+ return 0;
}
+early_param("crashkernel", parse_crashkernel);
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index cd5456f14af..eb57a851789 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -42,6 +42,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mca.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/io.h>
#include <linux/proc_fs.h>
@@ -414,7 +415,8 @@ subsys_initcall(mca_init);
/*--------------------------------------------------------------------*/
-static void mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
+static __kprobes void
+mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
{
int slot = mca_dev->slot;
@@ -444,7 +446,7 @@ static void mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
/*--------------------------------------------------------------------*/
-static int mca_handle_nmi_callback(struct device *dev, void *data)
+static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
{
struct mca_device *mca_dev = to_mca_device(dev);
unsigned char pos5;
@@ -462,7 +464,7 @@ static int mca_handle_nmi_callback(struct device *dev, void *data)
return 0;
}
-void mca_handle_nmi(void)
+void __kprobes mca_handle_nmi(void)
{
/* First try - scan the various adapters and see if a specific
* adapter was responsible for the error.
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 40b44cc0d14..9b9479768d5 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -2,6 +2,7 @@
* Intel CPU Microcode Update Driver for Linux
*
* Copyright (C) 2000-2004 Tigran Aivazian
+ * 2006 Shaohua Li <shaohua.li@intel.com>
*
* This driver allows to upgrade microcode on Intel processors
* belonging to IA-32 family - PentiumPro, Pentium II,
@@ -82,6 +83,9 @@
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
@@ -91,9 +95,6 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
MODULE_LICENSE("GPL");
-static int verbose;
-module_param(verbose, int, 0644);
-
#define MICROCODE_VERSION "1.14a"
#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
@@ -120,55 +121,40 @@ static DEFINE_SPINLOCK(microcode_update_lock);
/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
static DEFINE_MUTEX(microcode_mutex);
-static void __user *user_buffer; /* user area microcode data buffer */
-static unsigned int user_buffer_size; /* it's size */
-
-typedef enum mc_error_code {
- MC_SUCCESS = 0,
- MC_IGNORED = 1,
- MC_NOTFOUND = 2,
- MC_MARKED = 3,
- MC_ALLOCATED = 4,
-} mc_error_code_t;
-
static struct ucode_cpu_info {
+ int valid;
unsigned int sig;
- unsigned int pf, orig_pf;
+ unsigned int pf;
unsigned int rev;
- unsigned int cksum;
- mc_error_code_t err;
microcode_t *mc;
} ucode_cpu_info[NR_CPUS];
-
-static int microcode_open (struct inode *unused1, struct file *unused2)
-{
- return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-}
-static void collect_cpu_info (void *unused)
+static void collect_cpu_info(int cpu_num)
{
- int cpu_num = smp_processor_id();
struct cpuinfo_x86 *c = cpu_data + cpu_num;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
unsigned int val[2];
- uci->sig = uci->pf = uci->rev = uci->cksum = 0;
- uci->err = MC_NOTFOUND;
+ /* We should bind the task to the CPU */
+ BUG_ON(raw_smp_processor_id() != cpu_num);
+ uci->pf = uci->rev = 0;
uci->mc = NULL;
+ uci->valid = 1;
if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
cpu_has(c, X86_FEATURE_IA64)) {
- printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
+ printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+ "processor\n", cpu_num);
+ uci->valid = 0;
return;
- } else {
- uci->sig = cpuid_eax(0x00000001);
+ }
- if ((c->x86_model >= 5) || (c->x86 > 6)) {
- /* get processor flags from MSR 0x17 */
- rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
- uci->pf = 1 << ((val[1] >> 18) & 7);
- }
- uci->orig_pf = uci->pf;
+ uci->sig = cpuid_eax(0x00000001);
+
+ if ((c->x86_model >= 5) || (c->x86 > 6)) {
+ /* get processor flags from MSR 0x17 */
+ rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+ uci->pf = 1 << ((val[1] >> 18) & 7);
}
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -180,218 +166,159 @@ static void collect_cpu_info (void *unused)
uci->sig, uci->pf, uci->rev);
}
-static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum)
+static inline int microcode_update_match(int cpu_num,
+ microcode_header_t *mc_header, int sig, int pf)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
- pr_debug("Microcode Found.\n");
- pr_debug(" Header Revision 0x%x\n", mc_header->hdrver);
- pr_debug(" Loader Revision 0x%x\n", mc_header->ldrver);
- pr_debug(" Revision 0x%x \n", mc_header->rev);
- pr_debug(" Date %x/%x/%x\n",
- ((mc_header->date >> 24 ) & 0xff),
- ((mc_header->date >> 16 ) & 0xff),
- (mc_header->date & 0xFFFF));
- pr_debug(" Signature 0x%x\n", sig);
- pr_debug(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
- ((sig >> 12) & 0x3),
- ((sig >> 8) & 0xf),
- ((sig >> 4) & 0xf),
- ((sig & 0xf)));
- pr_debug(" Processor Flags 0x%x\n", pf);
- pr_debug(" Checksum 0x%x\n", cksum);
-
- if (mc_header->rev < uci->rev) {
- if (uci->err == MC_NOTFOUND) {
- uci->err = MC_IGNORED;
- uci->cksum = mc_header->rev;
- } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
- uci->cksum = mc_header->rev;
- } else if (mc_header->rev == uci->rev) {
- if (uci->err < MC_MARKED) {
- /* notify the caller of success on this cpu */
- uci->err = MC_SUCCESS;
- }
- } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
- pr_debug("microcode: CPU%d found a matching microcode update with "
- " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
- uci->cksum = cksum;
- uci->pf = pf; /* keep the original mc pf for cksum calculation */
- uci->err = MC_MARKED; /* found the match */
- for_each_online_cpu(cpu_num) {
- if (ucode_cpu_info + cpu_num != uci
- && ucode_cpu_info[cpu_num].mc == uci->mc) {
- uci->mc = NULL;
- break;
- }
- }
- if (uci->mc != NULL) {
- vfree(uci->mc);
- uci->mc = NULL;
- }
- }
- return;
+ if (!sigmatch(sig, uci->sig, pf, uci->pf)
+ || mc_header->rev <= uci->rev)
+ return 0;
+ return 1;
}
-static int find_matching_ucodes (void)
+static int microcode_sanity_check(void *mc)
{
- int cursor = 0;
- int error = 0;
-
- while (cursor + MC_HEADER_SIZE < user_buffer_size) {
- microcode_header_t mc_header;
- void *newmc = NULL;
- int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size;
+ microcode_header_t *mc_header = mc;
+ struct extended_sigtable *ext_header = NULL;
+ struct extended_signature *ext_sig;
+ unsigned long total_size, data_size, ext_table_size;
+ int sum, orig_sum, ext_sigcount = 0, i;
+
+ total_size = get_totalsize(mc_header);
+ data_size = get_datasize(mc_header);
+ if (data_size + MC_HEADER_SIZE > total_size) {
+ printk(KERN_ERR "microcode: error! "
+ "Bad data size in microcode data file\n");
+ return -EINVAL;
+ }
- if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- error = -EFAULT;
- goto out;
+ if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+ printk(KERN_ERR "microcode: error! "
+ "Unknown microcode update format\n");
+ return -EINVAL;
+ }
+ ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+ if (ext_table_size) {
+ if ((ext_table_size < EXT_HEADER_SIZE)
+ || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+ printk(KERN_ERR "microcode: error! "
+ "Small exttable size in microcode data file\n");
+ return -EINVAL;
}
-
- total_size = get_totalsize(&mc_header);
- if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
- printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- error = -EINVAL;
- goto out;
+ ext_header = mc + MC_HEADER_SIZE + data_size;
+ if (ext_table_size != exttable_size(ext_header)) {
+ printk(KERN_ERR "microcode: error! "
+ "Bad exttable size in microcode data file\n");
+ return -EFAULT;
}
+ ext_sigcount = ext_header->count;
+ }
- data_size = get_datasize(&mc_header);
- if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
- printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- error = -EINVAL;
- goto out;
+ /* check extended table checksum */
+ if (ext_table_size) {
+ int ext_table_sum = 0;
+ int *ext_tablep = (int *)ext_header;
+
+ i = ext_table_size / DWSIZE;
+ while (i--)
+ ext_table_sum += ext_tablep[i];
+ if (ext_table_sum) {
+ printk(KERN_WARNING "microcode: aborting, "
+ "bad extended signature table checksum\n");
+ return -EINVAL;
}
+ }
- if (mc_header.ldrver != 1 || mc_header.hdrver != 1) {
- printk(KERN_ERR "microcode: error! Unknown microcode update format\n");
- error = -EINVAL;
- goto out;
+ /* calculate the checksum */
+ orig_sum = 0;
+ i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+ while (i--)
+ orig_sum += ((int *)mc)[i];
+ if (orig_sum) {
+ printk(KERN_ERR "microcode: aborting, bad checksum\n");
+ return -EINVAL;
+ }
+ if (!ext_table_size)
+ return 0;
+ /* check extended signature checksum */
+ for (i = 0; i < ext_sigcount; i++) {
+ ext_sig = (struct extended_signature *)((void *)ext_header
+ + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
+ sum = orig_sum
+ - (mc_header->sig + mc_header->pf + mc_header->cksum)
+ + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+ if (sum) {
+ printk(KERN_ERR "microcode: aborting, bad checksum\n");
+ return -EINVAL;
}
+ }
+ return 0;
+}
- for_each_online_cpu(cpu_num) {
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
- if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
- mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
- }
+/*
+ * return 0 - no update found
+ * return 1 - found update
+ * return < 0 - error
+ */
+static int get_maching_microcode(void *mc, int cpu)
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ microcode_header_t *mc_header = mc;
+ struct extended_sigtable *ext_header;
+ unsigned long total_size = get_totalsize(mc_header);
+ int ext_sigcount, i;
+ struct extended_signature *ext_sig;
+ void *new_mc;
+
+ if (microcode_update_match(cpu, mc_header,
+ mc_header->sig, mc_header->pf))
+ goto find;
+
+ if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
+ return 0;
+
+ ext_header = (struct extended_sigtable *)(mc +
+ get_datasize(mc_header) + MC_HEADER_SIZE);
+ ext_sigcount = ext_header->count;
+ ext_sig = (struct extended_signature *)((void *)ext_header
+ + EXT_HEADER_SIZE);
+ for (i = 0; i < ext_sigcount; i++) {
+ if (microcode_update_match(cpu, mc_header,
+ ext_sig->sig, ext_sig->pf))
+ goto find;
+ ext_sig++;
+ }
+ return 0;
+find:
+ pr_debug("microcode: CPU %d found a matching microcode update with"
+ " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
+ new_mc = vmalloc(total_size);
+ if (!new_mc) {
+ printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+ return -ENOMEM;
+ }
- ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
- if (ext_table_size) {
- struct extended_sigtable ext_header;
- struct extended_signature ext_sig;
- int ext_sigcount;
+ /* free previous update file */
+ vfree(uci->mc);
- if ((ext_table_size < EXT_HEADER_SIZE)
- || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
- printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- error = -EINVAL;
- goto out;
- }
- if (copy_from_user(&ext_header, user_buffer + cursor
- + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- error = -EFAULT;
- goto out;
- }
- if (ext_table_size != exttable_size(&ext_header)) {
- printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- error = -EFAULT;
- goto out;
- }
-
- ext_sigcount = ext_header.count;
-
- for (i = 0; i < ext_sigcount; i++) {
- if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE
- + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- error = -EFAULT;
- goto out;
- }
- for_each_online_cpu(cpu_num) {
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
- if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
- mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
- }
- }
- }
- }
- /* now check if any cpu has matched */
- allocated_flag = 0;
- sum = 0;
- for_each_online_cpu(cpu_num) {
- if (ucode_cpu_info[cpu_num].err == MC_MARKED) {
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
- if (!allocated_flag) {
- allocated_flag = 1;
- newmc = vmalloc(total_size);
- if (!newmc) {
- printk(KERN_ERR "microcode: error! Can not allocate memory\n");
- error = -ENOMEM;
- goto out;
- }
- if (copy_from_user(newmc + MC_HEADER_SIZE,
- user_buffer + cursor + MC_HEADER_SIZE,
- total_size - MC_HEADER_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- vfree(newmc);
- error = -EFAULT;
- goto out;
- }
- memcpy(newmc, &mc_header, MC_HEADER_SIZE);
- /* check extended table checksum */
- if (ext_table_size) {
- int ext_table_sum = 0;
- int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
- i = ext_table_size / DWSIZE;
- while (i--) ext_table_sum += ext_tablep[i];
- if (ext_table_sum) {
- printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
- vfree(newmc);
- error = -EINVAL;
- goto out;
- }
- }
-
- /* calculate the checksum */
- i = (MC_HEADER_SIZE + data_size) / DWSIZE;
- while (i--) sum += ((int *)newmc)[i];
- sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
- }
- ucode_cpu_info[cpu_num].mc = newmc;
- ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
- if (sum + uci->sig + uci->pf + uci->cksum != 0) {
- printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
- error = -EINVAL;
- goto out;
- }
- }
- }
- cursor += total_size; /* goto the next update patch */
- } /* end of while */
-out:
- return error;
+ memcpy(new_mc, mc, total_size);
+ uci->mc = new_mc;
+ return 1;
}
-static void do_update_one (void * unused)
+static void apply_microcode(int cpu)
{
unsigned long flags;
unsigned int val[2];
- int cpu_num = smp_processor_id();
+ int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
- if (uci->mc == NULL) {
- if (verbose) {
- if (uci->err == MC_SUCCESS)
- printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
- cpu_num, uci->rev);
- else
- printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
- }
+ /* We should bind the task to the CPU */
+ BUG_ON(cpu_num != cpu);
+
+ if (uci->mc == NULL)
return;
- }
/* serialize access to the physical write to MSR 0x79 */
spin_lock_irqsave(&microcode_update_lock, flags);
@@ -408,68 +335,107 @@ static void do_update_one (void * unused)
/* get the current revision from MSR 0x8B */
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
- /* notify the caller of success on this cpu */
- uci->err = MC_SUCCESS;
spin_unlock_irqrestore(&microcode_update_lock, flags);
- printk(KERN_INFO "microcode: CPU%d updated from revision "
+ if (val[1] != uci->mc->hdr.rev) {
+ printk(KERN_ERR "microcode: CPU%d updated from revision "
+ "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+ return;
+ }
+ pr_debug("microcode: CPU%d updated from revision "
"0x%x to 0x%x, date = %08x \n",
cpu_num, uci->rev, val[1], uci->mc->hdr.date);
- return;
+ uci->rev = val[1];
}
-static int do_microcode_update (void)
-{
- int i, error;
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+static void __user *user_buffer; /* user area microcode data buffer */
+static unsigned int user_buffer_size; /* it's size */
- if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
- printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
- error = -EIO;
- goto out;
+static long get_next_ucode(void **mc, long offset)
+{
+ microcode_header_t mc_header;
+ unsigned long total_size;
+
+ /* No more data */
+ if (offset >= user_buffer_size)
+ return 0;
+ if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
+ printk(KERN_ERR "microcode: error! Can not read user data\n");
+ return -EFAULT;
}
-
- if ((error = find_matching_ucodes())) {
- printk(KERN_ERR "microcode: Error in the microcode data\n");
- goto out_free;
+ total_size = get_totalsize(&mc_header);
+ if (offset + total_size > user_buffer_size) {
+ printk(KERN_ERR "microcode: error! Bad total size in microcode "
+ "data file\n");
+ return -EINVAL;
}
-
- if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
- printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
- error = -EIO;
+ *mc = vmalloc(total_size);
+ if (!*mc)
+ return -ENOMEM;
+ if (copy_from_user(*mc, user_buffer + offset, total_size)) {
+ printk(KERN_ERR "microcode: error! Can not read user data\n");
+ vfree(*mc);
+ return -EFAULT;
}
+ return offset + total_size;
+}
+
+static int do_microcode_update (void)
+{
+ long cursor = 0;
+ int error = 0;
+ void *new_mc;
+ int cpu;
+ cpumask_t old;
+
+ old = current->cpus_allowed;
-out_free:
- for_each_online_cpu(i) {
- if (ucode_cpu_info[i].mc) {
- int j;
- void *tmp = ucode_cpu_info[i].mc;
- vfree(tmp);
- for_each_online_cpu(j) {
- if (ucode_cpu_info[j].mc == tmp)
- ucode_cpu_info[j].mc = NULL;
- }
+ while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
+ error = microcode_sanity_check(new_mc);
+ if (error)
+ goto out;
+ /*
+ * It's possible the data file has multiple matching ucode,
+ * lets keep searching till the latest version
+ */
+ for_each_online_cpu(cpu) {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+ if (!uci->valid)
+ continue;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ error = get_maching_microcode(new_mc, cpu);
+ if (error < 0)
+ goto out;
+ if (error == 1)
+ apply_microcode(cpu);
}
- if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
- printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
- " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
+ vfree(new_mc);
}
out:
+ if (cursor > 0)
+ vfree(new_mc);
+ if (cursor < 0)
+ error = cursor;
+ set_cpus_allowed(current, old);
return error;
}
+static int microcode_open (struct inode *unused1, struct file *unused2)
+{
+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
{
ssize_t ret;
- if (len < DEFAULT_UCODE_TOTALSIZE) {
- printk(KERN_ERR "microcode: not enough data\n");
- return -EINVAL;
- }
-
if ((len >> PAGE_SHIFT) > num_physpages) {
printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
return -EINVAL;
}
+ lock_cpu_hotplug();
mutex_lock(&microcode_mutex);
user_buffer = (void __user *) buf;
@@ -480,6 +446,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
ret = (ssize_t)len;
mutex_unlock(&microcode_mutex);
+ unlock_cpu_hotplug();
return ret;
}
@@ -496,7 +463,7 @@ static struct miscdevice microcode_dev = {
.fops = &microcode_fops,
};
-static int __init microcode_init (void)
+static int __init microcode_dev_init (void)
{
int error;
@@ -508,6 +475,280 @@ static int __init microcode_init (void)
return error;
}
+ return 0;
+}
+
+static void __exit microcode_dev_exit (void)
+{
+ misc_deregister(&microcode_dev);
+}
+
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+#else
+#define microcode_dev_init() 0
+#define microcode_dev_exit() do { } while(0)
+#endif
+
+static long get_next_ucode_from_buffer(void **mc, void *buf,
+ unsigned long size, long offset)
+{
+ microcode_header_t *mc_header;
+ unsigned long total_size;
+
+ /* No more data */
+ if (offset >= size)
+ return 0;
+ mc_header = (microcode_header_t *)(buf + offset);
+ total_size = get_totalsize(mc_header);
+
+ if (offset + total_size > size) {
+ printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+ return -EINVAL;
+ }
+
+ *mc = vmalloc(total_size);
+ if (!*mc) {
+ printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+ return -ENOMEM;
+ }
+ memcpy(*mc, buf + offset, total_size);
+ return offset + total_size;
+}
+
+/* fake device for request_firmware */
+static struct platform_device *microcode_pdev;
+
+static int cpu_request_microcode(int cpu)
+{
+ char name[30];
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+ const struct firmware *firmware;
+ void *buf;
+ unsigned long size;
+ long offset = 0;
+ int error;
+ void *mc;
+
+ /* We should bind the task to the CPU */
+ BUG_ON(cpu != raw_smp_processor_id());
+ sprintf(name,"intel-ucode/%02x-%02x-%02x",
+ c->x86, c->x86_model, c->x86_mask);
+ error = request_firmware(&firmware, name, &microcode_pdev->dev);
+ if (error) {
+ pr_debug("ucode data file %s load failed\n", name);
+ return error;
+ }
+ buf = (void *)firmware->data;
+ size = firmware->size;
+ while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
+ > 0) {
+ error = microcode_sanity_check(mc);
+ if (error)
+ break;
+ error = get_maching_microcode(mc, cpu);
+ if (error < 0)
+ break;
+ /*
+ * It's possible the data file has multiple matching ucode,
+ * lets keep searching till the latest version
+ */
+ if (error == 1) {
+ apply_microcode(cpu);
+ error = 0;
+ }
+ vfree(mc);
+ }
+ if (offset > 0)
+ vfree(mc);
+ if (offset < 0)
+ error = offset;
+ release_firmware(firmware);
+
+ return error;
+}
+
+static void microcode_init_cpu(int cpu)
+{
+ cpumask_t old;
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+ old = current->cpus_allowed;
+
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ mutex_lock(&microcode_mutex);
+ collect_cpu_info(cpu);
+ if (uci->valid)
+ cpu_request_microcode(cpu);
+ mutex_unlock(&microcode_mutex);
+ set_cpus_allowed(current, old);
+}
+
+static void microcode_fini_cpu(int cpu)
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+ mutex_lock(&microcode_mutex);
+ uci->valid = 0;
+ vfree(uci->mc);
+ uci->mc = NULL;
+ mutex_unlock(&microcode_mutex);
+}
+
+static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+ char *end;
+ unsigned long val = simple_strtoul(buf, &end, 0);
+ int err = 0;
+ int cpu = dev->id;
+
+ if (end == buf)
+ return -EINVAL;
+ if (val == 1) {
+ cpumask_t old;
+
+ old = current->cpus_allowed;
+
+ lock_cpu_hotplug();
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+ mutex_lock(&microcode_mutex);
+ if (uci->valid)
+ err = cpu_request_microcode(cpu);
+ mutex_unlock(&microcode_mutex);
+ unlock_cpu_hotplug();
+ set_cpus_allowed(current, old);
+ }
+ if (err)
+ return err;
+ return sz;
+}
+
+static ssize_t version_show(struct sys_device *dev, char *buf)
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+ return sprintf(buf, "0x%x\n", uci->rev);
+}
+
+static ssize_t pf_show(struct sys_device *dev, char *buf)
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+ return sprintf(buf, "0x%x\n", uci->pf);
+}
+
+static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
+static SYSDEV_ATTR(version, 0400, version_show, NULL);
+static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
+
+static struct attribute *mc_default_attrs[] = {
+ &attr_reload.attr,
+ &attr_version.attr,
+ &attr_processor_flags.attr,
+ NULL
+};
+
+static struct attribute_group mc_attr_group = {
+ .attrs = mc_default_attrs,
+ .name = "microcode",
+};
+
+static int mc_sysdev_add(struct sys_device *sys_dev)
+{
+ int cpu = sys_dev->id;
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+ if (!cpu_online(cpu))
+ return 0;
+ pr_debug("Microcode:CPU %d added\n", cpu);
+ memset(uci, 0, sizeof(*uci));
+ sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+
+ microcode_init_cpu(cpu);
+ return 0;
+}
+
+static int mc_sysdev_remove(struct sys_device *sys_dev)
+{
+ int cpu = sys_dev->id;
+
+ if (!cpu_online(cpu))
+ return 0;
+ pr_debug("Microcode:CPU %d removed\n", cpu);
+ microcode_fini_cpu(cpu);
+ sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+ return 0;
+}
+
+static int mc_sysdev_resume(struct sys_device *dev)
+{
+ int cpu = dev->id;
+
+ if (!cpu_online(cpu))
+ return 0;
+ pr_debug("Microcode:CPU %d resumed\n", cpu);
+ /* only CPU 0 will apply ucode here */
+ apply_microcode(0);
+ return 0;
+}
+
+static struct sysdev_driver mc_sysdev_driver = {
+ .add = mc_sysdev_add,
+ .remove = mc_sysdev_remove,
+ .resume = mc_sysdev_resume,
+};
+
+#ifdef CONFIG_HOTPLUG_CPU
+static __cpuinit int
+mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ struct sys_device *sys_dev;
+
+ sys_dev = get_cpu_sysdev(cpu);
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_DOWN_FAILED:
+ mc_sysdev_add(sys_dev);
+ break;
+ case CPU_DOWN_PREPARE:
+ mc_sysdev_remove(sys_dev);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block mc_cpu_notifier = {
+ .notifier_call = mc_cpu_callback,
+};
+#endif
+
+static int __init microcode_init (void)
+{
+ int error;
+
+ error = microcode_dev_init();
+ if (error)
+ return error;
+ microcode_pdev = platform_device_register_simple("microcode", -1,
+ NULL, 0);
+ if (IS_ERR(microcode_pdev)) {
+ microcode_dev_exit();
+ return PTR_ERR(microcode_pdev);
+ }
+
+ lock_cpu_hotplug();
+ error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
+ unlock_cpu_hotplug();
+ if (error) {
+ microcode_dev_exit();
+ platform_device_unregister(microcode_pdev);
+ return error;
+ }
+
+ register_hotcpu_notifier(&mc_cpu_notifier);
+
printk(KERN_INFO
"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
return 0;
@@ -515,9 +756,16 @@ static int __init microcode_init (void)
static void __exit microcode_exit (void)
{
- misc_deregister(&microcode_dev);
+ microcode_dev_exit();
+
+ unregister_hotcpu_notifier(&mc_cpu_notifier);
+
+ lock_cpu_hotplug();
+ sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+ unlock_cpu_hotplug();
+
+ platform_device_unregister(microcode_pdev);
}
module_init(microcode_init)
module_exit(microcode_exit)
-MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index a70b5fa0ef0..442aaf8c77e 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -30,6 +30,7 @@
#include <asm/io_apic.h>
#include <mach_apic.h>
+#include <mach_apicdef.h>
#include <mach_mpparse.h>
#include <bios_ebda.h>
@@ -68,7 +69,7 @@ unsigned int def_to_bigsmp = 0;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
/* Internal processor count */
-static unsigned int __devinitdata num_processors;
+unsigned int __cpuinitdata num_processors;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
@@ -228,12 +229,14 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+#if MAX_MP_BUSSES < 256
if (m->mpc_busid >= MAX_MP_BUSSES) {
printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
" is too large, max. supported is %d\n",
m->mpc_busid, str, MAX_MP_BUSSES - 1);
return;
}
+#endif
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
@@ -293,19 +296,6 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
- /*
- * Well it seems all SMP boards in existence
- * use ExtINT/LVT1 == LINT0 and
- * NMI/LVT2 == LINT1 - the following check
- * will show us if this assumptions is false.
- * Until then we do not have to add baggage.
- */
- if ((m->mpc_irqtype == mp_ExtINT) &&
- (m->mpc_destapiclint != 0))
- BUG();
- if ((m->mpc_irqtype == mp_NMI) &&
- (m->mpc_destapiclint != 1))
- BUG();
}
#ifdef CONFIG_X86_NUMAQ
@@ -822,8 +812,7 @@ int es7000_plat;
#ifdef CONFIG_ACPI
-void __init mp_register_lapic_address (
- u64 address)
+void __init mp_register_lapic_address(u64 address)
{
mp_lapic_addr = (unsigned long) address;
@@ -835,13 +824,10 @@ void __init mp_register_lapic_address (
Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
}
-
-void __devinit mp_register_lapic (
- u8 id,
- u8 enabled)
+void __devinit mp_register_lapic (u8 id, u8 enabled)
{
struct mpc_config_processor processor;
- int boot_cpu = 0;
+ int boot_cpu = 0;
if (MAX_APICS - id <= 0) {
printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
@@ -878,11 +864,9 @@ static struct mp_ioapic_routing {
u32 pin_programmed[4];
} mp_ioapic_routing[MAX_IO_APICS];
-
-static int mp_find_ioapic (
- int gsi)
+static int mp_find_ioapic (int gsi)
{
- int i = 0;
+ int i = 0;
/* Find the IOAPIC that manages this GSI. */
for (i = 0; i < nr_ioapics; i++) {
@@ -895,15 +879,11 @@ static int mp_find_ioapic (
return -1;
}
-
-void __init mp_register_ioapic (
- u8 id,
- u32 address,
- u32 gsi_base)
+void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
{
- int idx = 0;
- int tmpid;
+ int idx = 0;
+ int tmpid;
if (nr_ioapics >= MAX_IO_APICS) {
printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
@@ -949,16 +929,10 @@ void __init mp_register_ioapic (
mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
mp_ioapic_routing[idx].gsi_base,
mp_ioapic_routing[idx].gsi_end);
-
- return;
}
-
-void __init mp_override_legacy_irq (
- u8 bus_irq,
- u8 polarity,
- u8 trigger,
- u32 gsi)
+void __init
+mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
{
struct mpc_config_intsrc intsrc;
int ioapic = -1;
@@ -996,15 +970,13 @@ void __init mp_override_legacy_irq (
mp_irqs[mp_irq_entries] = intsrc;
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!\n");
-
- return;
}
void __init mp_config_acpi_legacy_irqs (void)
{
struct mpc_config_intsrc intsrc;
- int i = 0;
- int ioapic = -1;
+ int i = 0;
+ int ioapic = -1;
/*
* Fabricate the legacy ISA bus (bus #31).
@@ -1073,12 +1045,12 @@ void __init mp_config_acpi_legacy_irqs (void)
#define MAX_GSI_NUM 4096
-int mp_register_gsi (u32 gsi, int triggering, int polarity)
+int mp_register_gsi(u32 gsi, int triggering, int polarity)
{
- int ioapic = -1;
- int ioapic_pin = 0;
- int idx, bit = 0;
- static int pci_irq = 16;
+ int ioapic = -1;
+ int ioapic_pin = 0;
+ int idx, bit = 0;
+ static int pci_irq = 16;
/*
* Mapping between Global System Interrups, which
* represent all possible interrupts, and IRQs
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index acb351478e4..dbda706fdd1 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -21,83 +21,174 @@
#include <linux/sysdev.h>
#include <linux/sysctl.h>
#include <linux/percpu.h>
+#include <linux/dmi.h>
+#include <linux/kprobes.h>
#include <asm/smp.h>
#include <asm/nmi.h>
+#include <asm/kdebug.h>
#include <asm/intel_arch_perfmon.h>
#include "mach_traps.h"
-unsigned int nmi_watchdog = NMI_NONE;
-extern int unknown_nmi_panic;
-static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
-extern void show_registers(struct pt_regs *regs);
+/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
+ * evtsel_nmi_owner tracks the ownership of the event selection
+ * - different performance counters/ event selection may be reserved for
+ * different subsystems this reservation system just tries to coordinate
+ * things a little
+ */
+static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner);
+static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]);
-/*
- * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
- * - it may be reserved by some other driver, or not
- * - when not reserved by some other driver, it may be used for
- * the NMI watchdog, or not
- *
- * This is maintained separately from nmi_active because the NMI
- * watchdog may also be driven from the I/O APIC timer.
+/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
+ * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now)
*/
-static DEFINE_SPINLOCK(lapic_nmi_owner_lock);
-static unsigned int lapic_nmi_owner;
-#define LAPIC_NMI_WATCHDOG (1<<0)
-#define LAPIC_NMI_RESERVED (1<<1)
+#define NMI_MAX_COUNTER_BITS 66
/* nmi_active:
- * +1: the lapic NMI watchdog is active, but can be disabled
- * 0: the lapic NMI watchdog has not been set up, and cannot
+ * >0: the lapic NMI watchdog is active, but can be disabled
+ * <0: the lapic NMI watchdog has not been set up, and cannot
* be enabled
- * -1: the lapic NMI watchdog is disabled, but can be enabled
+ * 0: the lapic NMI watchdog is disabled, but can be enabled
*/
-int nmi_active;
+atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */
-#define K7_EVNTSEL_ENABLE (1 << 22)
-#define K7_EVNTSEL_INT (1 << 20)
-#define K7_EVNTSEL_OS (1 << 17)
-#define K7_EVNTSEL_USR (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
-#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+unsigned int nmi_watchdog = NMI_DEFAULT;
+static unsigned int nmi_hz = HZ;
-#define P6_EVNTSEL0_ENABLE (1 << 22)
-#define P6_EVNTSEL_INT (1 << 20)
-#define P6_EVNTSEL_OS (1 << 17)
-#define P6_EVNTSEL_USR (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
+struct nmi_watchdog_ctlblk {
+ int enabled;
+ u64 check_bit;
+ unsigned int cccr_msr;
+ unsigned int perfctr_msr; /* the MSR to reset in NMI handler */
+ unsigned int evntsel_msr; /* the MSR to select the events to handle */
+};
+static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
-#define MSR_P4_MISC_ENABLE 0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
-#define MSR_P4_PERFCTR0 0x300
-#define MSR_P4_CCCR0 0x360
-#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
-#define P4_ESCR_OS (1<<3)
-#define P4_ESCR_USR (1<<2)
-#define P4_CCCR_OVF_PMI0 (1<<26)
-#define P4_CCCR_OVF_PMI1 (1<<27)
-#define P4_CCCR_THRESHOLD(N) ((N)<<20)
-#define P4_CCCR_COMPLEMENT (1<<19)
-#define P4_CCCR_COMPARE (1<<18)
-#define P4_CCCR_REQUIRED (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE (1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
- CRU_ESCR0 (with any non-null event selector) through a complemented
- max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0 0x30C
-#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0 \
- (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
- P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+/* local prototypes */
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
-#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+extern void show_registers(struct pt_regs *regs);
+extern int unknown_nmi_panic;
+
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+{
+ /* returns the bit offset of the performance counter register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_PERFCTR0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+
+ switch (boot_cpu_data.x86) {
+ case 6:
+ return (msr - MSR_P6_PERFCTR0);
+ case 15:
+ return (msr - MSR_P4_BPU_PERFCTR0);
+ }
+ }
+ return 0;
+}
+
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+{
+ /* returns the bit offset of the event selection register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_EVNTSEL0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+
+ switch (boot_cpu_data.x86) {
+ case 6:
+ return (msr - MSR_P6_EVNTSEL0);
+ case 15:
+ return (msr - MSR_P4_BSU_ESCR0);
+ }
+ }
+ return 0;
+}
+
+/* checks for a bit availability (hack for oprofile) */
+int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
+{
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+/* checks the an msr for availability */
+int avail_to_resrv_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+int reserve_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner)))
+ return 1;
+ return 0;
+}
+
+void release_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner));
+}
+
+int reserve_evntsel_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_evntsel_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0]))
+ return 1;
+ return 0;
+}
+
+void release_evntsel_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_evntsel_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0]);
+}
+
+static __cpuinit inline int nmi_known_cpu(void)
+{
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return 1;
+ else
+ return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
+ }
+ return 0;
+}
#ifdef CONFIG_SMP
/* The performance counters used by NMI_LOCAL_APIC don't trigger when
@@ -125,7 +216,18 @@ static int __init check_nmi_watchdog(void)
unsigned int *prev_nmi_count;
int cpu;
- if (nmi_watchdog == NMI_NONE)
+ /* Enable NMI watchdog for newer systems.
+ Actually it should be safe for most systems before 2004 too except
+ for some IBM systems that corrupt registers when NMI happens
+ during SMM. Unfortunately we don't have more exact information
+ on these and use this coarse check. */
+ if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004)
+ nmi_watchdog = NMI_LOCAL_APIC;
+
+ if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
+ return 0;
+
+ if (!atomic_read(&nmi_active))
return 0;
prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
@@ -149,25 +251,45 @@ static int __init check_nmi_watchdog(void)
if (!cpu_isset(cpu, cpu_callin_map))
continue;
#endif
+ if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+ continue;
if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
- endflag = 1;
printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
cpu,
prev_nmi_count[cpu],
nmi_count(cpu));
- nmi_active = 0;
- lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
- kfree(prev_nmi_count);
- return -1;
+ per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+ atomic_dec(&nmi_active);
}
}
+ if (!atomic_read(&nmi_active)) {
+ kfree(prev_nmi_count);
+ atomic_set(&nmi_active, -1);
+ return -1;
+ }
endflag = 1;
printk("OK.\n");
/* now that we know it works we can reduce NMI frequency to
something more reasonable; makes a difference in some configs */
- if (nmi_watchdog == NMI_LOCAL_APIC)
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
nmi_hz = 1;
+ /*
+ * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
+ * are writable, with higher bits sign extending from bit 31.
+ * So, we can only program the counter with 31 bit values and
+ * 32nd bit should be 1, for 33.. to be 1.
+ * Find the appropriate nmi_hz
+ */
+ if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
+ ((u64)cpu_khz * 1000) > 0x7fffffffULL) {
+ u64 count = (u64)cpu_khz * 1000;
+ do_div(count, 0x7fffffffUL);
+ nmi_hz = count + 1;
+ }
+ }
kfree(prev_nmi_count);
return 0;
@@ -181,124 +303,70 @@ static int __init setup_nmi_watchdog(char *str)
get_option(&str, &nmi);
- if (nmi >= NMI_INVALID)
+ if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
return 0;
- if (nmi == NMI_NONE)
- nmi_watchdog = nmi;
/*
* If any other x86 CPU has a local APIC, then
* please test the NMI stuff there and send me the
* missing bits. Right now Intel P6/P4 and AMD K7 only.
*/
- if ((nmi == NMI_LOCAL_APIC) &&
- (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
- (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
- nmi_watchdog = nmi;
- if ((nmi == NMI_LOCAL_APIC) &&
- (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
- (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
- nmi_watchdog = nmi;
- /*
- * We can enable the IO-APIC watchdog
- * unconditionally.
- */
- if (nmi == NMI_IO_APIC) {
- nmi_active = 1;
- nmi_watchdog = nmi;
- }
+ if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
+ return 0; /* no lapic support */
+ nmi_watchdog = nmi;
return 1;
}
__setup("nmi_watchdog=", setup_nmi_watchdog);
-static void disable_intel_arch_watchdog(void);
-
static void disable_lapic_nmi_watchdog(void)
{
- if (nmi_active <= 0)
+ BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+ if (atomic_read(&nmi_active) <= 0)
return;
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
- wrmsr(MSR_K7_EVNTSEL0, 0, 0);
- break;
- case X86_VENDOR_INTEL:
- if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
- disable_intel_arch_watchdog();
- break;
- }
- switch (boot_cpu_data.x86) {
- case 6:
- if (boot_cpu_data.x86_model > 0xd)
- break;
- wrmsr(MSR_P6_EVNTSEL0, 0, 0);
- break;
- case 15:
- if (boot_cpu_data.x86_model > 0x4)
- break;
+ on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
- wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
- wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
- break;
- }
- break;
- }
- nmi_active = -1;
- /* tell do_nmi() and others that we're not active any more */
- nmi_watchdog = 0;
+ BUG_ON(atomic_read(&nmi_active) != 0);
}
static void enable_lapic_nmi_watchdog(void)
{
- if (nmi_active < 0) {
- nmi_watchdog = NMI_LOCAL_APIC;
- setup_apic_nmi_watchdog();
- }
-}
+ BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-int reserve_lapic_nmi(void)
-{
- unsigned int old_owner;
-
- spin_lock(&lapic_nmi_owner_lock);
- old_owner = lapic_nmi_owner;
- lapic_nmi_owner |= LAPIC_NMI_RESERVED;
- spin_unlock(&lapic_nmi_owner_lock);
- if (old_owner & LAPIC_NMI_RESERVED)
- return -EBUSY;
- if (old_owner & LAPIC_NMI_WATCHDOG)
- disable_lapic_nmi_watchdog();
- return 0;
-}
+ /* are we already enabled */
+ if (atomic_read(&nmi_active) != 0)
+ return;
-void release_lapic_nmi(void)
-{
- unsigned int new_owner;
+ /* are we lapic aware */
+ if (nmi_known_cpu() <= 0)
+ return;
- spin_lock(&lapic_nmi_owner_lock);
- new_owner = lapic_nmi_owner & ~LAPIC_NMI_RESERVED;
- lapic_nmi_owner = new_owner;
- spin_unlock(&lapic_nmi_owner_lock);
- if (new_owner & LAPIC_NMI_WATCHDOG)
- enable_lapic_nmi_watchdog();
+ on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+ touch_nmi_watchdog();
}
void disable_timer_nmi_watchdog(void)
{
- if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+ BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+ if (atomic_read(&nmi_active) <= 0)
return;
- unset_nmi_callback();
- nmi_active = -1;
- nmi_watchdog = NMI_NONE;
+ disable_irq(0);
+ on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+ BUG_ON(atomic_read(&nmi_active) != 0);
}
void enable_timer_nmi_watchdog(void)
{
- if (nmi_active < 0) {
- nmi_watchdog = NMI_IO_APIC;
+ BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+ if (atomic_read(&nmi_active) == 0) {
touch_nmi_watchdog();
- nmi_active = 1;
+ on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+ enable_irq(0);
}
}
@@ -308,15 +376,20 @@ static int nmi_pm_active; /* nmi_active before suspend */
static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
{
- nmi_pm_active = nmi_active;
- disable_lapic_nmi_watchdog();
+ /* only CPU0 goes here, other CPUs should be offline */
+ nmi_pm_active = atomic_read(&nmi_active);
+ stop_apic_nmi_watchdog(NULL);
+ BUG_ON(atomic_read(&nmi_active) != 0);
return 0;
}
static int lapic_nmi_resume(struct sys_device *dev)
{
- if (nmi_pm_active > 0)
- enable_lapic_nmi_watchdog();
+ /* only CPU0 goes here, other CPUs should be offline */
+ if (nmi_pm_active > 0) {
+ setup_apic_nmi_watchdog(NULL);
+ touch_nmi_watchdog();
+ }
return 0;
}
@@ -336,7 +409,13 @@ static int __init init_lapic_nmi_sysfs(void)
{
int error;
- if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)
+ /* should really be a BUG_ON but b/c this is an
+ * init call, it just doesn't work. -dcz
+ */
+ if (nmi_watchdog != NMI_LOCAL_APIC)
+ return 0;
+
+ if ( atomic_read(&nmi_active) < 0 )
return 0;
error = sysdev_class_register(&nmi_sysclass);
@@ -354,138 +433,269 @@ late_initcall(init_lapic_nmi_sysfs);
* Original code written by Keith Owens.
*/
-static void clear_msr_range(unsigned int base, unsigned int n)
-{
- unsigned int i;
-
- for(i = 0; i < n; ++i)
- wrmsr(base+i, 0, 0);
-}
-
-static void write_watchdog_counter(const char *descr)
+static void write_watchdog_counter(unsigned int perfctr_msr, const char *descr)
{
u64 count = (u64)cpu_khz * 1000;
do_div(count, nmi_hz);
if(descr)
Dprintk("setting %s to -0x%08Lx\n", descr, count);
- wrmsrl(nmi_perfctr_msr, 0 - count);
+ wrmsrl(perfctr_msr, 0 - count);
}
-static void setup_k7_watchdog(void)
+/* Note that these events don't tick when the CPU idles. This means
+ the frequency varies with CPU load. */
+
+#define K7_EVNTSEL_ENABLE (1 << 22)
+#define K7_EVNTSEL_INT (1 << 20)
+#define K7_EVNTSEL_OS (1 << 17)
+#define K7_EVNTSEL_USR (1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
+#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+
+static int setup_k7_watchdog(void)
{
+ unsigned int perfctr_msr, evntsel_msr;
unsigned int evntsel;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ perfctr_msr = MSR_K7_PERFCTR0;
+ evntsel_msr = MSR_K7_EVNTSEL0;
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
- nmi_perfctr_msr = MSR_K7_PERFCTR0;
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
- clear_msr_range(MSR_K7_EVNTSEL0, 4);
- clear_msr_range(MSR_K7_PERFCTR0, 4);
+ wrmsrl(perfctr_msr, 0UL);
evntsel = K7_EVNTSEL_INT
| K7_EVNTSEL_OS
| K7_EVNTSEL_USR
| K7_NMI_EVENT;
- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- write_watchdog_counter("K7_PERFCTR0");
+ /* setup the timer */
+ wrmsr(evntsel_msr, evntsel, 0);
+ write_watchdog_counter(perfctr_msr, "K7_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+ wrmsr(evntsel_msr, evntsel, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = 0; //unused
+ wd->check_bit = 1ULL<<63;
+ return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
+}
+
+static void stop_k7_watchdog(void)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ wrmsr(wd->evntsel_msr, 0, 0);
+
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
}
-static void setup_p6_watchdog(void)
+#define P6_EVNTSEL0_ENABLE (1 << 22)
+#define P6_EVNTSEL_INT (1 << 20)
+#define P6_EVNTSEL_OS (1 << 17)
+#define P6_EVNTSEL_USR (1 << 16)
+#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
+#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
+
+static int setup_p6_watchdog(void)
{
+ unsigned int perfctr_msr, evntsel_msr;
unsigned int evntsel;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ perfctr_msr = MSR_P6_PERFCTR0;
+ evntsel_msr = MSR_P6_EVNTSEL0;
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
- nmi_perfctr_msr = MSR_P6_PERFCTR0;
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
- clear_msr_range(MSR_P6_EVNTSEL0, 2);
- clear_msr_range(MSR_P6_PERFCTR0, 2);
+ wrmsrl(perfctr_msr, 0UL);
evntsel = P6_EVNTSEL_INT
| P6_EVNTSEL_OS
| P6_EVNTSEL_USR
| P6_NMI_EVENT;
- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
- write_watchdog_counter("P6_PERFCTR0");
+ /* setup the timer */
+ wrmsr(evntsel_msr, evntsel, 0);
+ write_watchdog_counter(perfctr_msr, "P6_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= P6_EVNTSEL0_ENABLE;
- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+ wrmsr(evntsel_msr, evntsel, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = 0; //unused
+ wd->check_bit = 1ULL<<39;
+ return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
+}
+
+static void stop_p6_watchdog(void)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ wrmsr(wd->evntsel_msr, 0, 0);
+
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
}
+/* Note that these events don't tick when the CPU idles. This means
+ the frequency varies with CPU load. */
+
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
+#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
+#define P4_ESCR_OS (1<<3)
+#define P4_ESCR_USR (1<<2)
+#define P4_CCCR_OVF_PMI0 (1<<26)
+#define P4_CCCR_OVF_PMI1 (1<<27)
+#define P4_CCCR_THRESHOLD(N) ((N)<<20)
+#define P4_CCCR_COMPLEMENT (1<<19)
+#define P4_CCCR_COMPARE (1<<18)
+#define P4_CCCR_REQUIRED (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE (1<<12)
+#define P4_CCCR_OVF (1<<31)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+ CRU_ESCR0 (with any non-null event selector) through a complemented
+ max threshold. [IA32-Vol3, Section 14.9.9] */
+
static int setup_p4_watchdog(void)
{
+ unsigned int perfctr_msr, evntsel_msr, cccr_msr;
+ unsigned int evntsel, cccr_val;
unsigned int misc_enable, dummy;
+ unsigned int ht_num;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+ rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
return 0;
- nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
- nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
#ifdef CONFIG_SMP
- if (smp_num_siblings == 2)
- nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
+ /* detect which hyperthread we are on */
+ if (smp_num_siblings == 2) {
+ unsigned int ebx, apicid;
+
+ ebx = cpuid_ebx(1);
+ apicid = (ebx >> 24) & 0xff;
+ ht_num = apicid & 1;
+ } else
#endif
+ ht_num = 0;
- if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
- clear_msr_range(0x3F1, 2);
- /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
- docs doesn't fully define it, so leave it alone for now. */
- if (boot_cpu_data.x86_model >= 0x3) {
- /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
- clear_msr_range(0x3A0, 26);
- clear_msr_range(0x3BC, 3);
+ /* performance counters are shared resources
+ * assign each hyperthread its own set
+ * (re-use the ESCR0 register, seems safe
+ * and keeps the cccr_val the same)
+ */
+ if (!ht_num) {
+ /* logical cpu 0 */
+ perfctr_msr = MSR_P4_IQ_PERFCTR0;
+ evntsel_msr = MSR_P4_CRU_ESCR0;
+ cccr_msr = MSR_P4_IQ_CCCR0;
+ cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
} else {
- clear_msr_range(0x3A0, 31);
+ /* logical cpu 1 */
+ perfctr_msr = MSR_P4_IQ_PERFCTR1;
+ evntsel_msr = MSR_P4_CRU_ESCR0;
+ cccr_msr = MSR_P4_IQ_CCCR1;
+ cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
}
- clear_msr_range(0x3C0, 6);
- clear_msr_range(0x3C8, 6);
- clear_msr_range(0x3E0, 2);
- clear_msr_range(MSR_P4_CCCR0, 18);
- clear_msr_range(MSR_P4_PERFCTR0, 18);
-
- wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- write_watchdog_counter("P4_IQ_COUNTER0");
+
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
+
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
+
+ evntsel = P4_ESCR_EVENT_SELECT(0x3F)
+ | P4_ESCR_OS
+ | P4_ESCR_USR;
+
+ cccr_val |= P4_CCCR_THRESHOLD(15)
+ | P4_CCCR_COMPLEMENT
+ | P4_CCCR_COMPARE
+ | P4_CCCR_REQUIRED;
+
+ wrmsr(evntsel_msr, evntsel, 0);
+ wrmsr(cccr_msr, cccr_val, 0);
+ write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+ cccr_val |= P4_CCCR_ENABLE;
+ wrmsr(cccr_msr, cccr_val, 0);
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = cccr_msr;
+ wd->check_bit = 1ULL<<39;
return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
}
-static void disable_intel_arch_watchdog(void)
+static void stop_p4_watchdog(void)
{
- unsigned ebx;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- /*
- * Check whether the Architectural PerfMon supports
- * Unhalted Core Cycles Event or not.
- * NOTE: Corresponding bit = 0 in ebp indicates event present.
- */
- ebx = cpuid_ebx(10);
- if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+ wrmsr(wd->cccr_msr, 0, 0);
+ wrmsr(wd->evntsel_msr, 0, 0);
+
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
}
+#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
static int setup_intel_arch_watchdog(void)
{
+ unsigned int ebx;
+ union cpuid10_eax eax;
+ unsigned int unused;
+ unsigned int perfctr_msr, evntsel_msr;
unsigned int evntsel;
- unsigned ebx;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
/*
* Check whether the Architectural PerfMon supports
* Unhalted Core Cycles Event or not.
- * NOTE: Corresponding bit = 0 in ebp indicates event present.
+ * NOTE: Corresponding bit = 0 in ebx indicates event present.
*/
- ebx = cpuid_ebx(10);
- if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
- return 0;
+ cpuid(10, &(eax.full), &ebx, &unused, &unused);
+ if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+ (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+ goto fail;
+
+ perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+ evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
- nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
- clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
- clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
+
+ wrmsrl(perfctr_msr, 0UL);
evntsel = ARCH_PERFMON_EVENTSEL_INT
| ARCH_PERFMON_EVENTSEL_OS
@@ -493,51 +703,145 @@ static int setup_intel_arch_watchdog(void)
| ARCH_PERFMON_NMI_EVENT_SEL
| ARCH_PERFMON_NMI_EVENT_UMASK;
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
- write_watchdog_counter("INTEL_ARCH_PERFCTR0");
+ /* setup the timer */
+ wrmsr(evntsel_msr, evntsel, 0);
+ write_watchdog_counter(perfctr_msr, "INTEL_ARCH_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+ wrmsr(evntsel_msr, evntsel, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = 0; //unused
+ wd->check_bit = 1ULL << (eax.split.bit_width - 1);
return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
}
-void setup_apic_nmi_watchdog (void)
+static void stop_intel_arch_watchdog(void)
{
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
- return;
- setup_k7_watchdog();
- break;
- case X86_VENDOR_INTEL:
- if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
- if (!setup_intel_arch_watchdog())
+ unsigned int ebx;
+ union cpuid10_eax eax;
+ unsigned int unused;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ /*
+ * Check whether the Architectural PerfMon supports
+ * Unhalted Core Cycles Event or not.
+ * NOTE: Corresponding bit = 0 in ebx indicates event present.
+ */
+ cpuid(10, &(eax.full), &ebx, &unused, &unused);
+ if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+ (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+ return;
+
+ wrmsr(wd->evntsel_msr, 0, 0);
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
+}
+
+void setup_apic_nmi_watchdog (void *unused)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ /* only support LOCAL and IO APICs for now */
+ if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+ (nmi_watchdog != NMI_IO_APIC))
+ return;
+
+ if (wd->enabled == 1)
+ return;
+
+ /* cheap hack to support suspend/resume */
+ /* if cpu0 is not active neither should the other cpus */
+ if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
+ return;
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
return;
- break;
- }
- switch (boot_cpu_data.x86) {
- case 6:
- if (boot_cpu_data.x86_model > 0xd)
+ if (!setup_k7_watchdog())
return;
-
- setup_p6_watchdog();
break;
- case 15:
- if (boot_cpu_data.x86_model > 0x4)
- return;
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ if (!setup_intel_arch_watchdog())
+ return;
+ break;
+ }
+ switch (boot_cpu_data.x86) {
+ case 6:
+ if (boot_cpu_data.x86_model > 0xd)
+ return;
+
+ if (!setup_p6_watchdog())
+ return;
+ break;
+ case 15:
+ if (boot_cpu_data.x86_model > 0x4)
+ return;
- if (!setup_p4_watchdog())
+ if (!setup_p4_watchdog())
+ return;
+ break;
+ default:
return;
+ }
break;
default:
return;
}
- break;
- default:
+ }
+ wd->enabled = 1;
+ atomic_inc(&nmi_active);
+}
+
+void stop_apic_nmi_watchdog(void *unused)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ /* only support LOCAL and IO APICs for now */
+ if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+ (nmi_watchdog != NMI_IO_APIC))
+ return;
+
+ if (wd->enabled == 0)
return;
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ stop_k7_watchdog();
+ break;
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ stop_intel_arch_watchdog();
+ break;
+ }
+ switch (boot_cpu_data.x86) {
+ case 6:
+ if (boot_cpu_data.x86_model > 0xd)
+ break;
+ stop_p6_watchdog();
+ break;
+ case 15:
+ if (boot_cpu_data.x86_model > 0x4)
+ break;
+ stop_p4_watchdog();
+ break;
+ }
+ break;
+ default:
+ return;
+ }
}
- lapic_nmi_owner = LAPIC_NMI_WATCHDOG;
- nmi_active = 1;
+ wd->enabled = 0;
+ atomic_dec(&nmi_active);
}
/*
@@ -579,7 +883,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
extern void die_nmi(struct pt_regs *, const char *msg);
-void nmi_watchdog_tick (struct pt_regs * regs)
+__kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
{
/*
@@ -588,11 +892,23 @@ void nmi_watchdog_tick (struct pt_regs * regs)
* smp_processor_id().
*/
unsigned int sum;
+ int touched = 0;
int cpu = smp_processor_id();
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+ u64 dummy;
+ int rc=0;
+
+ /* check for other users first */
+ if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+ == NOTIFY_STOP) {
+ rc = 1;
+ touched = 1;
+ }
sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
- if (last_irq_sums[cpu] == sum) {
+ /* if the apic timer isn't firing, this cpu isn't doing much */
+ if (!touched && last_irq_sums[cpu] == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
@@ -607,27 +923,59 @@ void nmi_watchdog_tick (struct pt_regs * regs)
last_irq_sums[cpu] = sum;
alert_counter[cpu] = 0;
}
- if (nmi_perfctr_msr) {
- if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
- /*
- * P4 quirks:
- * - An overflown perfctr will assert its interrupt
- * until the OVF flag in its CCCR is cleared.
- * - LVTPC is masked on interrupt and must be
- * unmasked by the LVTPC handler.
+ /* see if the nmi watchdog went off */
+ if (wd->enabled) {
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ rdmsrl(wd->perfctr_msr, dummy);
+ if (dummy & wd->check_bit){
+ /* this wasn't a watchdog timer interrupt */
+ goto done;
+ }
+
+ /* only Intel P4 uses the cccr msr */
+ if (wd->cccr_msr != 0) {
+ /*
+ * P4 quirks:
+ * - An overflown perfctr will assert its interrupt
+ * until the OVF flag in its CCCR is cleared.
+ * - LVTPC is masked on interrupt and must be
+ * unmasked by the LVTPC handler.
+ */
+ rdmsrl(wd->cccr_msr, dummy);
+ dummy &= ~P4_CCCR_OVF;
+ wrmsrl(wd->cccr_msr, dummy);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
+ else if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
+ wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+ /* P6 based Pentium M need to re-unmask
+ * the apic vector but it doesn't hurt
+ * other P6 variant.
+ * ArchPerfom/Core Duo also needs this */
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
+ /* start the cycle over again */
+ write_watchdog_counter(wd->perfctr_msr, NULL);
+ rc = 1;
+ } else if (nmi_watchdog == NMI_IO_APIC) {
+ /* don't know how to accurately check for this.
+ * just assume it was a watchdog timer interrupt
+ * This matches the old behaviour.
*/
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
- apic_write(APIC_LVTPC, APIC_DM_NMI);
+ rc = 1;
}
- else if (nmi_perfctr_msr == MSR_P6_PERFCTR0 ||
- nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
- /* Only P6 based Pentium M need to re-unmask
- * the apic vector but it doesn't hurt
- * other P6 variant */
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- }
- write_watchdog_counter(NULL);
}
+done:
+ return rc;
+}
+
+int do_nmi_callback(struct pt_regs * regs, int cpu)
+{
+#ifdef CONFIG_SYSCTL
+ if (unknown_nmi_panic)
+ return unknown_nmi_panic_callback(regs, cpu);
+#endif
+ return 0;
}
#ifdef CONFIG_SYSCTL
@@ -637,36 +985,46 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
unsigned char reason = get_nmi_reason();
char buf[64];
- if (!(reason & 0xc0)) {
- sprintf(buf, "NMI received for unknown reason %02x\n", reason);
- die_nmi(regs, buf);
- }
+ sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+ die_nmi(regs, buf);
return 0;
}
/*
- * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ * proc handler for /proc/sys/kernel/nmi
*/
-int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
+int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
void __user *buffer, size_t *length, loff_t *ppos)
{
int old_state;
- old_state = unknown_nmi_panic;
+ nmi_watchdog_enabled = (atomic_read(&nmi_active) > 0) ? 1 : 0;
+ old_state = nmi_watchdog_enabled;
proc_dointvec(table, write, file, buffer, length, ppos);
- if (!!old_state == !!unknown_nmi_panic)
+ if (!!old_state == !!nmi_watchdog_enabled)
return 0;
- if (unknown_nmi_panic) {
- if (reserve_lapic_nmi() < 0) {
- unknown_nmi_panic = 0;
- return -EBUSY;
- } else {
- set_nmi_callback(unknown_nmi_panic_callback);
- }
+ if (atomic_read(&nmi_active) < 0) {
+ printk( KERN_WARNING "NMI watchdog is permanently disabled\n");
+ return -EIO;
+ }
+
+ if (nmi_watchdog == NMI_DEFAULT) {
+ if (nmi_known_cpu() > 0)
+ nmi_watchdog = NMI_LOCAL_APIC;
+ else
+ nmi_watchdog = NMI_IO_APIC;
+ }
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ if (nmi_watchdog_enabled)
+ enable_lapic_nmi_watchdog();
+ else
+ disable_lapic_nmi_watchdog();
} else {
- release_lapic_nmi();
- unset_nmi_callback();
+ printk( KERN_WARNING
+ "NMI watchdog doesn't know what hardware to touch\n");
+ return -EIO;
}
return 0;
}
@@ -675,7 +1033,11 @@ int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
EXPORT_SYMBOL(nmi_active);
EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(reserve_lapic_nmi);
-EXPORT_SYMBOL(release_lapic_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
+EXPORT_SYMBOL(reserve_perfctr_nmi);
+EXPORT_SYMBOL(release_perfctr_nmi);
+EXPORT_SYMBOL(reserve_evntsel_nmi);
+EXPORT_SYMBOL(release_evntsel_nmi);
EXPORT_SYMBOL(disable_timer_nmi_watchdog);
EXPORT_SYMBOL(enable_timer_nmi_watchdog);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8657c739656..8c190ca7ae4 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -37,6 +37,7 @@
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/random.h>
+#include <linux/personality.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -320,15 +321,6 @@ void show_regs(struct pt_regs * regs)
* the "args".
*/
extern void kernel_thread_helper(void);
-__asm__(".section .text\n"
- ".align 4\n"
- "kernel_thread_helper:\n\t"
- "movl %edx,%eax\n\t"
- "pushl %edx\n\t"
- "call *%ebx\n\t"
- "pushl %eax\n\t"
- "call do_exit\n"
- ".previous");
/*
* Create a kernel thread
@@ -346,7 +338,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.xes = __USER_DS;
regs.orig_eax = -1;
regs.eip = (unsigned long) kernel_thread_helper;
- regs.xcs = __KERNEL_CS;
+ regs.xcs = __KERNEL_CS | get_kernel_rpl();
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
/* Ok, create the new process.. */
@@ -905,7 +897,7 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
unsigned long arch_align_stack(unsigned long sp)
{
- if (randomize_va_space)
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index d3db03f4085..775f50e9395 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -185,17 +185,17 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
return addr;
}
-static inline int is_at_popf(struct task_struct *child, struct pt_regs *regs)
+static inline int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
{
int i, copied;
- unsigned char opcode[16];
+ unsigned char opcode[15];
unsigned long addr = convert_eip_to_linear(child, regs);
copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
for (i = 0; i < copied; i++) {
switch (opcode[i]) {
- /* popf */
- case 0x9d:
+ /* popf and iret */
+ case 0x9d: case 0xcf:
return 1;
/* opcode and address size prefixes */
case 0x66: case 0x67:
@@ -247,7 +247,7 @@ static void set_singlestep(struct task_struct *child)
* don't mark it as being "us" that set it, so that we
* won't clear it by hand later.
*/
- if (is_at_popf(child, regs))
+ if (is_setting_trap_flag(child, regs))
return;
child->ptrace |= PT_DTRACE;
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 54cfeabbc5e..84278e0093a 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -145,14 +145,10 @@ real_mode_gdt_entries [3] =
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};
-static struct
-{
- unsigned short size __attribute__ ((packed));
- unsigned long long * base __attribute__ ((packed));
-}
-real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
-real_mode_idt = { 0x3ff, NULL },
-no_idt = { 0, NULL };
+static struct Xgt_desc_struct
+real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
+real_mode_idt = { 0x3ff, 0 },
+no_idt = { 0, 0 };
/* This is 16-bit protected mode code to disable paging and the cache,
diff --git a/arch/i386/kernel/relocate_kernel.S b/arch/i386/kernel/relocate_kernel.S
index d312616effa..f151d6fae46 100644
--- a/arch/i386/kernel/relocate_kernel.S
+++ b/arch/i386/kernel/relocate_kernel.S
@@ -7,16 +7,138 @@
*/
#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/kexec.h>
+
+/*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+#define PTR(x) (x << 2)
+#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
+
+ .text
+ .align PAGE_ALIGNED
+ .globl relocate_kernel
+relocate_kernel:
+ movl 8(%esp), %ebp /* list of pages */
+
+#ifdef CONFIG_X86_PAE
+ /* map the control page at its virtual address */
+
+ movl PTR(VA_PGD)(%ebp), %edi
+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
+ andl $0xc0000000, %eax
+ shrl $27, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PMD_0)(%ebp), %edx
+ orl $PAE_PGD_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PMD_0)(%ebp), %edi
+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x3fe00000, %eax
+ shrl $18, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PTE_0)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PTE_0)(%ebp), %edi
+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x001ff000, %eax
+ shrl $9, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ /* identity map the control page at its physical address */
+
+ movl PTR(VA_PGD)(%ebp), %edi
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
+ andl $0xc0000000, %eax
+ shrl $27, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PMD_1)(%ebp), %edx
+ orl $PAE_PGD_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PMD_1)(%ebp), %edi
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x3fe00000, %eax
+ shrl $18, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PTE_1)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PTE_1)(%ebp), %edi
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x001ff000, %eax
+ shrl $9, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+#else
+ /* map the control page at its virtual address */
+
+ movl PTR(VA_PGD)(%ebp), %edi
+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
+ andl $0xffc00000, %eax
+ shrl $20, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PTE_0)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PTE_0)(%ebp), %edi
+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x003ff000, %eax
+ shrl $10, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ /* identity map the control page at its physical address */
+
+ movl PTR(VA_PGD)(%ebp), %edi
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
+ andl $0xffc00000, %eax
+ shrl $20, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_PTE_1)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+
+ movl PTR(VA_PTE_1)(%ebp), %edi
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
+ andl $0x003ff000, %eax
+ shrl $10, %eax
+ addl %edi, %eax
+
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
+ orl $PAGE_ATTR, %edx
+ movl %edx, (%eax)
+#endif
- /*
- * Must be relocatable PIC code callable as a C function, that once
- * it starts can not use the previous processes stack.
- */
- .globl relocate_new_kernel
relocate_new_kernel:
/* read the arguments and say goodbye to the stack */
movl 4(%esp), %ebx /* page_list */
- movl 8(%esp), %ebp /* reboot_code_buffer */
+ movl 8(%esp), %ebp /* list of pages */
movl 12(%esp), %edx /* start address */
movl 16(%esp), %ecx /* cpu_has_pae */
@@ -24,11 +146,26 @@ relocate_new_kernel:
pushl $0
popfl
- /* set a new stack at the bottom of our page... */
- lea 4096(%ebp), %esp
+ /* get physical address of control page now */
+ /* this is impossible after page table switch */
+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edi
- /* store the parameters back on the stack */
- pushl %edx /* store the start address */
+ /* switch to new set of page tables */
+ movl PTR(PA_PGD)(%ebp), %eax
+ movl %eax, %cr3
+
+ /* setup a new stack at the end of the physical control page */
+ lea 4096(%edi), %esp
+
+ /* jump to identity mapped page */
+ movl %edi, %eax
+ addl $(identity_mapped - relocate_kernel), %eax
+ pushl %eax
+ ret
+
+identity_mapped:
+ /* store the start address on the stack */
+ pushl %edx
/* Set cr0 to a known state:
* 31 0 == Paging disabled
@@ -113,8 +250,3 @@ relocate_new_kernel:
xorl %edi, %edi
xorl %ebp, %ebp
ret
-relocate_new_kernel_end:
-
- .globl relocate_new_kernel_size
-relocate_new_kernel_size:
- .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
deleted file mode 100644
index 98352c374c7..00000000000
--- a/arch/i386/kernel/semaphore.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * i386 semaphore implementation.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * Portions Copyright 1999 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
- */
-#include <asm/semaphore.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * %eax contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax whish is either a return
- * value or just clobbered..
- */
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed\n"
-"__down_failed:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_interruptible\n"
-"__down_failed_interruptible:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down_interruptible\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_trylock\n"
-"__down_failed_trylock:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down_trylock\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __up_wakeup\n"
-"__up_wakeup:\n\t"
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __up\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
- "ret"
-);
-
-/*
- * rw spinlock fallbacks
- */
-#if defined(CONFIG_SMP)
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __write_lock_failed\n"
-"__write_lock_failed:\n\t"
- LOCK_PREFIX "addl $" RW_LOCK_BIAS_STR ",(%eax)\n"
-"1: rep; nop\n\t"
- "cmpl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
- "jne 1b\n\t"
- LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
- "jnz __write_lock_failed\n\t"
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __read_lock_failed\n"
-"__read_lock_failed:\n\t"
- LOCK_PREFIX "incl (%eax)\n"
-"1: rep; nop\n\t"
- "cmpl $1,(%eax)\n\t"
- "js 1b\n\t"
- LOCK_PREFIX "decl (%eax)\n\t"
- "js __read_lock_failed\n\t"
- "ret"
-);
-#endif
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f1682206d30..814cdebf737 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -53,6 +53,7 @@
#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
+#include <asm/mmzone.h>
#include <asm/setup.h>
#include <asm/arch_hooks.h>
#include <asm/sections.h>
@@ -89,18 +90,6 @@ EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
-#ifdef CONFIG_ACPI
- int acpi_disabled = 0;
-#else
- int acpi_disabled = 1;
-#endif
-EXPORT_SYMBOL(acpi_disabled);
-
-#ifdef CONFIG_ACPI
-int __initdata acpi_force = 0;
-extern acpi_interrupt_flags acpi_sci_flags;
-#endif
-
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
#ifdef CONFIG_MCA
@@ -148,7 +137,6 @@ EXPORT_SYMBOL(ist_info);
struct e820map e820;
extern void early_cpu_init(void);
-extern void generic_apic_probe(char *);
extern int root_mountflags;
unsigned long saved_videomode;
@@ -700,238 +688,150 @@ static inline void copy_edd(void)
}
#endif
-static void __init parse_cmdline_early (char ** cmdline_p)
-{
- char c = ' ', *to = command_line, *from = saved_command_line;
- int len = 0;
- int userdef = 0;
+static int __initdata user_defined_memmap = 0;
- /* Save unparsed command line copy for /proc/cmdline */
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+/*
+ * "mem=nopentium" disables the 4MB page tables.
+ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+ * to <mem>, overriding the bios size.
+ * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * <start> to <start>+<mem>, overriding the bios size.
+ *
+ * HPA tells me bootloaders need to parse mem=, so no new
+ * option should be mem= [also see Documentation/i386/boot.txt]
+ */
+static int __init parse_mem(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
- for (;;) {
- if (c != ' ')
- goto next_char;
- /*
- * "mem=nopentium" disables the 4MB page tables.
- * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
- * to <mem>, overriding the bios size.
- * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
- * <start> to <start>+<mem>, overriding the bios size.
- *
- * HPA tells me bootloaders need to parse mem=, so no new
- * option should be mem= [also see Documentation/i386/boot.txt]
+ if (strcmp(arg, "nopentium") == 0) {
+ clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+ disable_pse = 1;
+ } else {
+ /* If the user specifies memory size, we
+ * limit the BIOS-provided memory map to
+ * that size. exactmap can be used to specify
+ * the exact map. mem=number can be used to
+ * trim the existing memory map.
*/
- if (!memcmp(from, "mem=", 4)) {
- if (to != command_line)
- to--;
- if (!memcmp(from+4, "nopentium", 9)) {
- from += 9+4;
- clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
- disable_pse = 1;
- } else {
- /* If the user specifies memory size, we
- * limit the BIOS-provided memory map to
- * that size. exactmap can be used to specify
- * the exact map. mem=number can be used to
- * trim the existing memory map.
- */
- unsigned long long mem_size;
-
- mem_size = memparse(from+4, &from);
- limit_regions(mem_size);
- userdef=1;
- }
- }
-
- else if (!memcmp(from, "memmap=", 7)) {
- if (to != command_line)
- to--;
- if (!memcmp(from+7, "exactmap", 8)) {
-#ifdef CONFIG_CRASH_DUMP
- /* If we are doing a crash dump, we
- * still need to know the real mem
- * size before original memory map is
- * reset.
- */
- find_max_pfn();
- saved_max_pfn = max_pfn;
-#endif
- from += 8+7;
- e820.nr_map = 0;
- userdef = 1;
- } else {
- /* If the user specifies memory size, we
- * limit the BIOS-provided memory map to
- * that size. exactmap can be used to specify
- * the exact map. mem=number can be used to
- * trim the existing memory map.
- */
- unsigned long long start_at, mem_size;
+ unsigned long long mem_size;
- mem_size = memparse(from+7, &from);
- if (*from == '@') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_RAM);
- } else if (*from == '#') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_ACPI);
- } else if (*from == '$') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_RESERVED);
- } else {
- limit_regions(mem_size);
- userdef=1;
- }
- }
- }
-
- else if (!memcmp(from, "noexec=", 7))
- noexec_setup(from + 7);
+ mem_size = memparse(arg, &arg);
+ limit_regions(mem_size);
+ user_defined_memmap = 1;
+ }
+ return 0;
+}
+early_param("mem", parse_mem);
+static int __init parse_memmap(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
-#ifdef CONFIG_X86_SMP
- /*
- * If the BIOS enumerates physical processors before logical,
- * maxcpus=N at enumeration-time can be used to disable HT.
+ if (strcmp(arg, "exactmap") == 0) {
+#ifdef CONFIG_CRASH_DUMP
+ /* If we are doing a crash dump, we
+ * still need to know the real mem
+ * size before original memory map is
+ * reset.
*/
- else if (!memcmp(from, "maxcpus=", 8)) {
- extern unsigned int maxcpus;
-
- maxcpus = simple_strtoul(from + 8, NULL, 0);
- }
+ find_max_pfn();
+ saved_max_pfn = max_pfn;
#endif
-
-#ifdef CONFIG_ACPI
- /* "acpi=off" disables both ACPI table parsing and interpreter */
- else if (!memcmp(from, "acpi=off", 8)) {
- disable_acpi();
- }
-
- /* acpi=force to over-ride black-list */
- else if (!memcmp(from, "acpi=force", 10)) {
- acpi_force = 1;
- acpi_ht = 1;
- acpi_disabled = 0;
- }
-
- /* acpi=strict disables out-of-spec workarounds */
- else if (!memcmp(from, "acpi=strict", 11)) {
- acpi_strict = 1;
- }
-
- /* Limit ACPI just to boot-time to enable HT */
- else if (!memcmp(from, "acpi=ht", 7)) {
- if (!acpi_force)
- disable_acpi();
- acpi_ht = 1;
- }
-
- /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
- else if (!memcmp(from, "pci=noacpi", 10)) {
- acpi_disable_pci();
- }
- /* "acpi=noirq" disables ACPI interrupt routing */
- else if (!memcmp(from, "acpi=noirq", 10)) {
- acpi_noirq_set();
+ e820.nr_map = 0;
+ user_defined_memmap = 1;
+ } else {
+ /* If the user specifies memory size, we
+ * limit the BIOS-provided memory map to
+ * that size. exactmap can be used to specify
+ * the exact map. mem=number can be used to
+ * trim the existing memory map.
+ */
+ unsigned long long start_at, mem_size;
+
+ mem_size = memparse(arg, &arg);
+ if (*arg == '@') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, E820_RAM);
+ } else if (*arg == '#') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, E820_ACPI);
+ } else if (*arg == '$') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, E820_RESERVED);
+ } else {
+ limit_regions(mem_size);
+ user_defined_memmap = 1;
}
+ }
+ return 0;
+}
+early_param("memmap", parse_memmap);
- else if (!memcmp(from, "acpi_sci=edge", 13))
- acpi_sci_flags.trigger = 1;
-
- else if (!memcmp(from, "acpi_sci=level", 14))
- acpi_sci_flags.trigger = 3;
-
- else if (!memcmp(from, "acpi_sci=high", 13))
- acpi_sci_flags.polarity = 1;
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel.
+ */
+static int __init parse_elfcorehdr(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
- else if (!memcmp(from, "acpi_sci=low", 12))
- acpi_sci_flags.polarity = 3;
+ elfcorehdr_addr = memparse(arg, &arg);
+ return 0;
+}
+early_param("elfcorehdr", parse_elfcorehdr);
+#endif /* CONFIG_PROC_VMCORE */
-#ifdef CONFIG_X86_IO_APIC
- else if (!memcmp(from, "acpi_skip_timer_override", 24))
- acpi_skip_timer_override = 1;
+/*
+ * highmem=size forces highmem to be exactly 'size' bytes.
+ * This works even on boxes that have no highmem otherwise.
+ * This also works to reduce highmem size on bigger boxes.
+ */
+static int __init parse_highmem(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
- if (!memcmp(from, "disable_timer_pin_1", 19))
- disable_timer_pin_1 = 1;
- if (!memcmp(from, "enable_timer_pin_1", 18))
- disable_timer_pin_1 = -1;
+ highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
+ return 0;
+}
+early_param("highmem", parse_highmem);
- /* disable IO-APIC */
- else if (!memcmp(from, "noapic", 6))
- disable_ioapic_setup();
-#endif /* CONFIG_X86_IO_APIC */
-#endif /* CONFIG_ACPI */
+/*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the
+ * vmalloc area - the default is 128m.
+ */
+static int __init parse_vmalloc(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
-#ifdef CONFIG_X86_LOCAL_APIC
- /* enable local APIC */
- else if (!memcmp(from, "lapic", 5))
- lapic_enable();
+ __VMALLOC_RESERVE = memparse(arg, &arg);
+ return 0;
+}
+early_param("vmalloc", parse_vmalloc);
- /* disable local APIC */
- else if (!memcmp(from, "nolapic", 6))
- lapic_disable();
-#endif /* CONFIG_X86_LOCAL_APIC */
+/*
+ * reservetop=size reserves a hole at the top of the kernel address space which
+ * a hypervisor can load into later. Needed for dynamically loaded hypervisors,
+ * so relocating the fixmap can be done before paging initialization.
+ */
+static int __init parse_reservetop(char *arg)
+{
+ unsigned long address;
-#ifdef CONFIG_KEXEC
- /* crashkernel=size@addr specifies the location to reserve for
- * a crash kernel. By reserving this memory we guarantee
- * that linux never set's it up as a DMA target.
- * Useful for holding code to do something appropriate
- * after a kernel panic.
- */
- else if (!memcmp(from, "crashkernel=", 12)) {
- unsigned long size, base;
- size = memparse(from+12, &from);
- if (*from == '@') {
- base = memparse(from+1, &from);
- /* FIXME: Do I want a sanity check
- * to validate the memory range?
- */
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- }
-#endif
-#ifdef CONFIG_PROC_VMCORE
- /* elfcorehdr= specifies the location of elf core header
- * stored by the crashed kernel.
- */
- else if (!memcmp(from, "elfcorehdr=", 11))
- elfcorehdr_addr = memparse(from+11, &from);
-#endif
+ if (!arg)
+ return -EINVAL;
- /*
- * highmem=size forces highmem to be exactly 'size' bytes.
- * This works even on boxes that have no highmem otherwise.
- * This also works to reduce highmem size on bigger boxes.
- */
- else if (!memcmp(from, "highmem=", 8))
- highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
-
- /*
- * vmalloc=size forces the vmalloc area to be exactly 'size'
- * bytes. This can be used to increase (or decrease) the
- * vmalloc area - the default is 128m.
- */
- else if (!memcmp(from, "vmalloc=", 8))
- __VMALLOC_RESERVE = memparse(from+8, &from);
-
- next_char:
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
- *cmdline_p = command_line;
- if (userdef) {
- printk(KERN_INFO "user-defined physical RAM map:\n");
- print_memory_map("user");
- }
+ address = memparse(arg, &arg);
+ reserve_top_address(address);
+ return 0;
}
+early_param("reservetop", parse_reservetop);
/*
* Callback for efi_memory_walk.
@@ -1170,6 +1070,14 @@ static unsigned long __init setup_memory(void)
}
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
pages_to_mb(highend_pfn - highstart_pfn));
+ num_physpages = highend_pfn;
+ high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+ num_physpages = max_low_pfn;
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+#endif
+#ifdef CONFIG_FLATMEM
+ max_mapnr = num_physpages;
#endif
printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
pages_to_mb(max_low_pfn));
@@ -1181,22 +1089,20 @@ static unsigned long __init setup_memory(void)
void __init zone_sizes_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
- unsigned int max_dma, low;
-
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- low = max_low_pfn;
-
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+ virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+ max_low_pfn,
+ highend_pfn};
+ add_active_range(0, 0, highend_pfn);
+#else
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+ virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+ max_low_pfn};
+ add_active_range(0, 0, max_low_pfn);
#endif
- }
- free_area_init(zones_size);
+
+ free_area_init_nodes(max_zone_pfns);
}
#else
extern unsigned long __init setup_memory(void);
@@ -1258,7 +1164,7 @@ void __init setup_bootmem_allocator(void)
*/
find_smp_config();
#endif
-
+ numa_kva_reserve();
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
@@ -1499,17 +1405,15 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
- parse_cmdline_early(cmdline_p);
+ parse_early_param();
-#ifdef CONFIG_EARLY_PRINTK
- {
- char *s = strstr(*cmdline_p, "earlyprintk=");
- if (s) {
- setup_early_printk(strchr(s, '=') + 1);
- printk("early console enabled\n");
- }
+ if (user_defined_memmap) {
+ printk(KERN_INFO "user-defined physical RAM map:\n");
+ print_memory_map("user");
}
-#endif
+
+ strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
max_low_pfn = setup_memory();
@@ -1538,7 +1442,7 @@ void __init setup_arch(char **cmdline_p)
dmi_scan_machine();
#ifdef CONFIG_X86_GENERICARCH
- generic_apic_probe(*cmdline_p);
+ generic_apic_probe();
#endif
if (efi_enabled)
efi_map_memmap();
@@ -1550,9 +1454,11 @@ void __init setup_arch(char **cmdline_p)
acpi_boot_table_init();
#endif
+#ifdef CONFIG_PCI
#ifdef CONFIG_X86_IO_APIC
check_acpi_pci(); /* Checks more than just ACPI actually */
#endif
+#endif
#ifdef CONFIG_ACPI
acpi_boot_init();
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index c10789d7a9d..465188e2d70 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -634,3 +634,69 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
}
}
+/*
+ * this function sends a 'generic call function' IPI to one other CPU
+ * in the system.
+ *
+ * cpu is a standard Linux logical CPU number.
+ */
+static void
+__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+ int nonatomic, int wait)
+{
+ struct call_data_struct data;
+ int cpus = 1;
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ call_data = &data;
+ wmb();
+ /* Send a message to all other CPUs and wait for them to respond */
+ send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
+
+ /* Wait for response */
+ while (atomic_read(&data.started) != cpus)
+ cpu_relax();
+
+ if (!wait)
+ return;
+
+ while (atomic_read(&data.finished) != cpus)
+ cpu_relax();
+}
+
+/*
+ * smp_call_function_single - Run a function on another CPU
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: Currently unused.
+ * @wait: If true, wait until function has completed on other CPUs.
+ *
+ * Retrurns 0 on success, else a negative status code.
+ *
+ * Does not return until the remote CPU is nearly ready to execute <func>
+ * or is or has executed.
+ */
+
+int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+ int nonatomic, int wait)
+{
+ /* prevent preemption and reschedule on another processor */
+ int me = get_cpu();
+ if (cpu == me) {
+ WARN_ON(1);
+ put_cpu();
+ return -EBUSY;
+ }
+ spin_lock_bh(&call_lock);
+ __smp_call_function_single(cpu, func, info, nonatomic, wait);
+ spin_unlock_bh(&call_lock);
+ put_cpu();
+ return 0;
+}
+EXPORT_SYMBOL(smp_call_function_single);
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index f948419c888..020d873b7d2 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -177,6 +177,9 @@ static void __devinit smp_store_cpu_info(int id)
*/
if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+ if (num_possible_cpus() == 1)
+ goto valid_k7;
+
/* Athlon 660/661 is valid. */
if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
goto valid_k7;
@@ -642,9 +645,13 @@ static void map_cpu_to_logical_apicid(void)
{
int cpu = smp_processor_id();
int apicid = logical_smp_processor_id();
+ int node = apicid_to_node(apicid);
+
+ if (!node_online(node))
+ node = first_online_node;
cpu_2_logical_apicid[cpu] = apicid;
- map_cpu_to_node(cpu, apicid_to_node(apicid));
+ map_cpu_to_node(cpu, node);
}
static void unmap_cpu_to_logical_apicid(int cpu)
@@ -1372,7 +1379,8 @@ int __cpu_disable(void)
*/
if (cpu == 0)
return -EBUSY;
-
+ if (nmi_watchdog == NMI_LOCAL_APIC)
+ stop_apic_nmi_watchdog(NULL);
clear_local_APIC();
/* Allow any queued timer interrupts to get serviced */
local_irq_enable();
@@ -1486,3 +1494,16 @@ void __init smp_intr_init(void)
/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
}
+
+/*
+ * If the BIOS enumerates physical processors before logical,
+ * maxcpus=N at enumeration-time can be used to disable HT.
+ */
+static int __init parse_maxcpus(char *arg)
+{
+ extern unsigned int maxcpus;
+
+ maxcpus = simple_strtoul(arg, NULL, 0);
+ return 0;
+}
+early_param("maxcpus", parse_maxcpus);
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index b1809c9a089..32413122c4c 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -42,7 +42,7 @@
#define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8)
static u8 pxm_bitmap[PXM_BITMAP_LEN]; /* bitmap of proximity domains */
-#define MAX_CHUNKS_PER_NODE 4
+#define MAX_CHUNKS_PER_NODE 3
#define MAXCHUNKS (MAX_CHUNKS_PER_NODE * MAX_NUMNODES)
struct node_memory_chunk_s {
unsigned long start_pfn;
@@ -54,8 +54,6 @@ struct node_memory_chunk_s {
static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
static int num_memory_chunks; /* total number of memory chunks */
-static int zholes_size_init;
-static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
extern void * boot_ioremap(unsigned long, unsigned long);
@@ -135,50 +133,6 @@ static void __init parse_memory_affinity_structure (char *sratp)
"enabled and removable" : "enabled" ) );
}
-#if MAX_NR_ZONES != 4
-#error "MAX_NR_ZONES != 4, chunk_to_zone requires review"
-#endif
-/* Take a chunk of pages from page frame cstart to cend and count the number
- * of pages in each zone, returned via zones[].
- */
-static __init void chunk_to_zones(unsigned long cstart, unsigned long cend,
- unsigned long *zones)
-{
- unsigned long max_dma;
- extern unsigned long max_low_pfn;
-
- int z;
- unsigned long rend;
-
- /* FIXME: MAX_DMA_ADDRESS and max_low_pfn are trying to provide
- * similarly scoped information and should be handled in a consistant
- * manner.
- */
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
- /* Split the hole into the zones in which it falls. Repeatedly
- * take the segment in which the remaining hole starts, round it
- * to the end of that zone.
- */
- memset(zones, 0, MAX_NR_ZONES * sizeof(long));
- while (cstart < cend) {
- if (cstart < max_dma) {
- z = ZONE_DMA;
- rend = (cend < max_dma)? cend : max_dma;
-
- } else if (cstart < max_low_pfn) {
- z = ZONE_NORMAL;
- rend = (cend < max_low_pfn)? cend : max_low_pfn;
-
- } else {
- z = ZONE_HIGHMEM;
- rend = cend;
- }
- zones[z] += rend - cstart;
- cstart = rend;
- }
-}
-
/*
* The SRAT table always lists ascending addresses, so can always
* assume that the first "start" address that you see is the real
@@ -223,7 +177,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
memset(pxm_bitmap, 0, sizeof(pxm_bitmap)); /* init proximity domain bitmap */
memset(node_memory_chunk, 0, sizeof(node_memory_chunk));
- memset(zholes_size, 0, sizeof(zholes_size));
num_memory_chunks = 0;
while (p < end) {
@@ -287,6 +240,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
node_read_chunk(chunk->nid, chunk);
+ add_active_range(chunk->nid, chunk->start_pfn, chunk->end_pfn);
}
for_each_online_node(nid) {
@@ -395,57 +349,7 @@ int __init get_memcfg_from_srat(void)
return acpi20_parse_srat((struct acpi_table_srat *)header);
}
out_err:
+ remove_all_active_ranges();
printk("failed to get NUMA memory information from SRAT table\n");
return 0;
}
-
-/* For each node run the memory list to determine whether there are
- * any memory holes. For each hole determine which ZONE they fall
- * into.
- *
- * NOTE#1: this requires knowledge of the zone boundries and so
- * _cannot_ be performed before those are calculated in setup_memory.
- *
- * NOTE#2: we rely on the fact that the memory chunks are ordered by
- * start pfn number during setup.
- */
-static void __init get_zholes_init(void)
-{
- int nid;
- int c;
- int first;
- unsigned long end = 0;
-
- for_each_online_node(nid) {
- first = 1;
- for (c = 0; c < num_memory_chunks; c++){
- if (node_memory_chunk[c].nid == nid) {
- if (first) {
- end = node_memory_chunk[c].end_pfn;
- first = 0;
-
- } else {
- /* Record any gap between this chunk
- * and the previous chunk on this node
- * against the zones it spans.
- */
- chunk_to_zones(end,
- node_memory_chunk[c].start_pfn,
- &zholes_size[nid * MAX_NR_ZONES]);
- }
- }
- }
- }
-}
-
-unsigned long * __init get_zholes_size(int nid)
-{
- if (!zholes_size_init) {
- zholes_size_init++;
- get_zholes_init();
- }
- if (nid >= MAX_NUMNODES || !node_online(nid))
- printk("%s: nid = %d is invalid/offline. num_online_nodes = %d",
- __FUNCTION__, nid, num_online_nodes());
- return &zholes_size[nid * MAX_NR_ZONES];
-}
diff --git a/arch/i386/kernel/stacktrace.c b/arch/i386/kernel/stacktrace.c
deleted file mode 100644
index e62a037ab39..00000000000
--- a/arch/i386/kernel/stacktrace.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/i386/kernel/stacktrace.c
- *
- * Stack trace management functions
- *
- * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#include <linux/sched.h>
-#include <linux/stacktrace.h>
-
-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
-{
- return p > (void *)tinfo &&
- p < (void *)tinfo + THREAD_SIZE - 3;
-}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer:
- */
-static inline unsigned long
-save_context_stack(struct stack_trace *trace, unsigned int skip,
- struct thread_info *tinfo, unsigned long *stack,
- unsigned long ebp)
-{
- unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
- while (valid_stack_ptr(tinfo, (void *)ebp)) {
- addr = *(unsigned long *)(ebp + 4);
- if (!skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- skip--;
- if (trace->nr_entries >= trace->max_entries)
- break;
- /*
- * break out of recursive entries (such as
- * end_of_stack_stop_unwind_function):
- */
- if (ebp == *(unsigned long *)ebp)
- break;
-
- ebp = *(unsigned long *)ebp;
- }
-#else
- while (valid_stack_ptr(tinfo, stack)) {
- addr = *stack++;
- if (__kernel_text_address(addr)) {
- if (!skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- skip--;
- if (trace->nr_entries >= trace->max_entries)
- break;
- }
- }
-#endif
-
- return ebp;
-}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer.
- * If all_contexts is set, all contexts (hardirq, softirq and process)
- * are saved. If not set then only the current context is saved.
- */
-void save_stack_trace(struct stack_trace *trace,
- struct task_struct *task, int all_contexts,
- unsigned int skip)
-{
- unsigned long ebp;
- unsigned long *stack = &ebp;
-
- WARN_ON(trace->nr_entries || !trace->max_entries);
-
- if (!task || task == current) {
- /* Grab ebp right from our regs: */
- asm ("movl %%ebp, %0" : "=r" (ebp));
- } else {
- /* ebp is the last reg pushed by switch_to(): */
- ebp = *(unsigned long *) task->thread.esp;
- }
-
- while (1) {
- struct thread_info *context = (struct thread_info *)
- ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-
- ebp = save_context_stack(trace, skip, context, stack, ebp);
- stack = (unsigned long *)context->previous_esp;
- if (!all_contexts || !stack ||
- trace->nr_entries >= trace->max_entries)
- break;
- trace->entries[trace->nr_entries++] = ULONG_MAX;
- if (trace->nr_entries >= trace->max_entries)
- break;
- }
-}
-
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index dd63d477539..7e639f78b0b 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -317,3 +317,4 @@ ENTRY(sys_call_table)
.long sys_tee /* 315 */
.long sys_vmsplice
.long sys_move_pages
+ .long sys_getcpu
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index edd00f6cee3..86944acfb64 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -130,18 +130,33 @@ static int set_rtc_mmss(unsigned long nowtime)
int timer_ack;
-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
- if (!user_mode_vm(regs) && in_lock_functions(pc))
+#ifdef CONFIG_SMP
+ if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
return *(unsigned long *)(regs->ebp + 4);
-
+#else
+ unsigned long *sp;
+ if ((regs->xcs & 3) == 0)
+ sp = (unsigned long *)&regs->esp;
+ else
+ sp = (unsigned long *)regs->esp;
+ /* Return address is either directly at stack pointer
+ or above a saved eflags. Eflags has bits 22-31 zero,
+ kernel addresses don't. */
+ if (sp[0] >> 22)
+ return sp[0];
+ if (sp[1] >> 22)
+ return sp[1];
+#endif
+ }
+#endif
return pc;
}
EXPORT_SYMBOL(profile_pc);
-#endif
/*
* This is the same as the above, except we _also_ save the current
@@ -270,16 +285,19 @@ void notify_arch_cmos_timer(void)
mod_timer(&sync_cmos_timer, jiffies + 1);
}
-static long clock_cmos_diff, sleep_start;
+static long clock_cmos_diff;
+static unsigned long sleep_start;
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
/*
* Estimate time zone so that set_time can update the clock
*/
- clock_cmos_diff = -get_cmos_time();
+ unsigned long ctime = get_cmos_time();
+
+ clock_cmos_diff = -ctime;
clock_cmos_diff += get_seconds();
- sleep_start = get_cmos_time();
+ sleep_start = ctime;
return 0;
}
@@ -287,18 +305,29 @@ static int timer_resume(struct sys_device *dev)
{
unsigned long flags;
unsigned long sec;
- unsigned long sleep_length;
-
+ unsigned long ctime = get_cmos_time();
+ long sleep_length = (ctime - sleep_start) * HZ;
+ struct timespec ts;
+
+ if (sleep_length < 0) {
+ printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
+ /* The time after the resume must not be earlier than the time
+ * before the suspend or some nasty things will happen
+ */
+ sleep_length = 0;
+ ctime = sleep_start;
+ }
#ifdef CONFIG_HPET_TIMER
if (is_hpet_enabled())
hpet_reenable();
#endif
setup_pit_timer();
- sec = get_cmos_time() + clock_cmos_diff;
- sleep_length = (get_cmos_time() - sleep_start) * HZ;
+
+ sec = ctime + clock_cmos_diff;
+ ts.tv_sec = sec;
+ ts.tv_nsec = 0;
+ do_settimeofday(&ts);
write_seqlock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = sec;
- xtime.tv_nsec = 0;
jiffies_64 += sleep_length;
wall_jiffies += sleep_length;
write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -334,10 +363,11 @@ extern void (*late_time_init)(void);
/* Duplicate of time_init() below, with hpet_enable part added */
static void __init hpet_time_init(void)
{
- xtime.tv_sec = get_cmos_time();
- xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
+ struct timespec ts;
+ ts.tv_sec = get_cmos_time();
+ ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+
+ do_settimeofday(&ts);
if ((hpet_enable() >= 0) && hpet_use_timer) {
printk("Using HPET for base-timer\n");
@@ -349,6 +379,7 @@ static void __init hpet_time_init(void)
void __init time_init(void)
{
+ struct timespec ts;
#ifdef CONFIG_HPET_TIMER
if (is_hpet_capable()) {
/*
@@ -359,10 +390,10 @@ void __init time_init(void)
return;
}
#endif
- xtime.tv_sec = get_cmos_time();
- xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
+ ts.tv_sec = get_cmos_time();
+ ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+
+ do_settimeofday(&ts);
time_init_hook();
}
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 14a1376fedd..6bf14a4e995 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -301,23 +301,25 @@ int hpet_rtc_timer_init(void)
hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
local_irq_save(flags);
+
cnt = hpet_readl(HPET_COUNTER);
cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
hpet_writel(cnt, HPET_T1_CMP);
hpet_t1_cmp = cnt;
- local_irq_restore(flags);
cfg = hpet_readl(HPET_T1_CFG);
cfg &= ~HPET_TN_PERIODIC;
cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
hpet_writel(cfg, HPET_T1_CFG);
+ local_irq_restore(flags);
+
return 1;
}
static void hpet_rtc_timer_reinit(void)
{
- unsigned int cfg, cnt;
+ unsigned int cfg, cnt, ticks_per_int, lost_ints;
if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
cfg = hpet_readl(HPET_T1_CFG);
@@ -332,10 +334,33 @@ static void hpet_rtc_timer_reinit(void)
hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
/* It is more accurate to use the comparator value than current count.*/
- cnt = hpet_t1_cmp;
- cnt += hpet_tick*HZ/hpet_rtc_int_freq;
- hpet_writel(cnt, HPET_T1_CMP);
- hpet_t1_cmp = cnt;
+ ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
+ hpet_t1_cmp += ticks_per_int;
+ hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+ /*
+ * If the interrupt handler was delayed too long, the write above tries
+ * to schedule the next interrupt in the past and the hardware would
+ * not interrupt until the counter had wrapped around.
+ * So we have to check that the comparator wasn't set to a past time.
+ */
+ cnt = hpet_readl(HPET_COUNTER);
+ if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
+ lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
+ /* Make sure that, even with the time needed to execute
+ * this code, the next scheduled interrupt has been moved
+ * back to the future: */
+ lost_ints++;
+
+ hpet_t1_cmp += lost_ints * ticks_per_int;
+ hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+ if (PIE_on)
+ PIE_count += lost_ints;
+
+ printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+ hpet_rtc_int_freq);
+ }
}
/*
diff --git a/arch/i386/kernel/topology.c b/arch/i386/kernel/topology.c
index e2e281d4bcc..07d6da36a82 100644
--- a/arch/i386/kernel/topology.c
+++ b/arch/i386/kernel/topology.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/nodemask.h>
+#include <linux/mmzone.h>
#include <asm/cpu.h>
static struct i386_cpu cpu_devices[NR_CPUS];
@@ -55,34 +56,18 @@ EXPORT_SYMBOL(arch_register_cpu);
EXPORT_SYMBOL(arch_unregister_cpu);
#endif /*CONFIG_HOTPLUG_CPU*/
-
-
-#ifdef CONFIG_NUMA
-#include <linux/mmzone.h>
-
static int __init topology_init(void)
{
int i;
+#ifdef CONFIG_NUMA
for_each_online_node(i)
register_one_node(i);
+#endif /* CONFIG_NUMA */
for_each_present_cpu(i)
arch_register_cpu(i);
return 0;
}
-#else /* !CONFIG_NUMA */
-
-static int __init topology_init(void)
-{
- int i;
-
- for_each_present_cpu(i)
- arch_register_cpu(i);
- return 0;
-}
-
-#endif /* CONFIG_NUMA */
-
subsys_initcall(topology_init);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7e9edafffd8..a13037fe0ee 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -28,6 +28,7 @@
#include <linux/kprobes.h>
#include <linux/kexec.h>
#include <linux/unwind.h>
+#include <linux/uaccess.h>
#ifdef CONFIG_EISA
#include <linux/ioport.h>
@@ -40,7 +41,6 @@
#include <asm/processor.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/debugreg.h>
@@ -51,6 +51,7 @@
#include <asm/smp.h>
#include <asm/arch_hooks.h>
#include <asm/kdebug.h>
+#include <asm/stacktrace.h>
#include <linux/module.h>
@@ -118,26 +119,16 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
p < (void *)tinfo + THREAD_SIZE - 3;
}
-/*
- * Print one address/symbol entries per line.
- */
-static inline void print_addr_and_symbol(unsigned long addr, char *log_lvl)
-{
- printk(" [<%08lx>] ", addr);
-
- print_symbol("%s\n", addr);
-}
-
static inline unsigned long print_context_stack(struct thread_info *tinfo,
unsigned long *stack, unsigned long ebp,
- char *log_lvl)
+ struct stacktrace_ops *ops, void *data)
{
unsigned long addr;
#ifdef CONFIG_FRAME_POINTER
while (valid_stack_ptr(tinfo, (void *)ebp)) {
addr = *(unsigned long *)(ebp + 4);
- print_addr_and_symbol(addr, log_lvl);
+ ops->address(data, addr);
/*
* break out of recursive entries (such as
* end_of_stack_stop_unwind_function):
@@ -150,30 +141,37 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
while (valid_stack_ptr(tinfo, stack)) {
addr = *stack++;
if (__kernel_text_address(addr))
- print_addr_and_symbol(addr, log_lvl);
+ ops->address(data, addr);
}
#endif
return ebp;
}
+struct ops_and_data {
+ struct stacktrace_ops *ops;
+ void *data;
+};
+
static asmlinkage int
-show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
+dump_trace_unwind(struct unwind_frame_info *info, void *data)
{
+ struct ops_and_data *oad = (struct ops_and_data *)data;
int n = 0;
while (unwind(info) == 0 && UNW_PC(info)) {
n++;
- print_addr_and_symbol(UNW_PC(info), log_lvl);
+ oad->ops->address(oad->data, UNW_PC(info));
if (arch_unw_user_mode(info))
break;
}
return n;
}
-static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *stack, char *log_lvl)
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack,
+ struct stacktrace_ops *ops, void *data)
{
- unsigned long ebp;
+ unsigned long ebp = 0;
if (!task)
task = current;
@@ -181,54 +179,116 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (call_trace >= 0) {
int unw_ret = 0;
struct unwind_frame_info info;
+ struct ops_and_data oad = { .ops = ops, .data = data };
if (regs) {
if (unwind_init_frame_info(&info, task, regs) == 0)
- unw_ret = show_trace_unwind(&info, log_lvl);
+ unw_ret = dump_trace_unwind(&info, &oad);
} else if (task == current)
- unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
+ unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
else {
if (unwind_init_blocked(&info, task) == 0)
- unw_ret = show_trace_unwind(&info, log_lvl);
+ unw_ret = dump_trace_unwind(&info, &oad);
}
if (unw_ret > 0) {
if (call_trace == 1 && !arch_unw_user_mode(&info)) {
- print_symbol("DWARF2 unwinder stuck at %s\n",
+ ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
UNW_PC(&info));
if (UNW_SP(&info) >= PAGE_OFFSET) {
- printk("Leftover inexact backtrace:\n");
+ ops->warning(data, "Leftover inexact backtrace:\n");
stack = (void *)UNW_SP(&info);
+ if (!stack)
+ return;
+ ebp = UNW_FP(&info);
} else
- printk("Full inexact backtrace again:\n");
+ ops->warning(data, "Full inexact backtrace again:\n");
} else if (call_trace >= 1)
return;
else
- printk("Full inexact backtrace again:\n");
+ ops->warning(data, "Full inexact backtrace again:\n");
} else
- printk("Inexact backtrace:\n");
+ ops->warning(data, "Inexact backtrace:\n");
+ }
+ if (!stack) {
+ unsigned long dummy;
+ stack = &dummy;
+ if (task && task != current)
+ stack = (unsigned long *)task->thread.esp;
}
- if (task == current) {
- /* Grab ebp right from our regs */
- asm ("movl %%ebp, %0" : "=r" (ebp) : );
- } else {
- /* ebp is the last reg pushed by switch_to */
- ebp = *(unsigned long *) task->thread.esp;
+#ifdef CONFIG_FRAME_POINTER
+ if (!ebp) {
+ if (task == current) {
+ /* Grab ebp right from our regs */
+ asm ("movl %%ebp, %0" : "=r" (ebp) : );
+ } else {
+ /* ebp is the last reg pushed by switch_to */
+ ebp = *(unsigned long *) task->thread.esp;
+ }
}
+#endif
while (1) {
struct thread_info *context;
context = (struct thread_info *)
((unsigned long)stack & (~(THREAD_SIZE - 1)));
- ebp = print_context_stack(context, stack, ebp, log_lvl);
+ ebp = print_context_stack(context, stack, ebp, ops, data);
+ /* Should be after the line below, but somewhere
+ in early boot context comes out corrupted and we
+ can't reference it -AK */
+ if (ops->stack(data, "IRQ") < 0)
+ break;
stack = (unsigned long*)context->previous_esp;
if (!stack)
break;
- printk("%s =======================\n", log_lvl);
}
}
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+ printk(data);
+ print_symbol(msg, symbol);
+ printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+ printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+ return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr)
+{
+ printk("%s [<%08lx>] ", (char *)data, addr);
+ print_symbol("%s\n", addr);
+}
+
+static struct stacktrace_ops print_trace_ops = {
+ .warning = print_trace_warning,
+ .warning_symbol = print_trace_warning_symbol,
+ .stack = print_trace_stack,
+ .address = print_trace_address,
+};
+
+static void
+show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ unsigned long * stack, char *log_lvl)
+{
+ dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
+ printk("%s =======================\n", log_lvl);
+}
-void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack)
+void show_trace(struct task_struct *task, struct pt_regs *regs,
+ unsigned long * stack)
{
show_trace_log_lvl(task, regs, stack, "");
}
@@ -291,8 +351,9 @@ void show_registers(struct pt_regs *regs)
ss = regs->xss & 0xffff;
}
print_modules();
- printk(KERN_EMERG "CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\n"
- "EFLAGS: %08lx (%s %.*s) \n",
+ printk(KERN_EMERG "CPU: %d\n"
+ KERN_EMERG "EIP: %04x:[<%08lx>] %s VLI\n"
+ KERN_EMERG "EFLAGS: %08lx (%s %.*s)\n",
smp_processor_id(), 0xffff & regs->xcs, regs->eip,
print_tainted(), regs->eflags, system_utsname.release,
(int)strcspn(system_utsname.version, " "),
@@ -313,6 +374,8 @@ void show_registers(struct pt_regs *regs)
*/
if (in_kernel) {
u8 __user *eip;
+ int code_bytes = 64;
+ unsigned char c;
printk("\n" KERN_EMERG "Stack: ");
show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
@@ -320,9 +383,12 @@ void show_registers(struct pt_regs *regs)
printk(KERN_EMERG "Code: ");
eip = (u8 __user *)regs->eip - 43;
- for (i = 0; i < 64; i++, eip++) {
- unsigned char c;
-
+ if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
+ /* try starting at EIP */
+ eip = (u8 __user *)regs->eip;
+ code_bytes = 32;
+ }
+ for (i = 0; i < code_bytes; i++, eip++) {
if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
printk(" Bad EIP value.");
break;
@@ -343,7 +409,7 @@ static void handle_BUG(struct pt_regs *regs)
if (eip < PAGE_OFFSET)
return;
- if (__get_user(ud2, (unsigned short __user *)eip))
+ if (probe_kernel_address((unsigned short __user *)eip, ud2))
return;
if (ud2 != 0x0b0f)
return;
@@ -356,7 +422,8 @@ static void handle_BUG(struct pt_regs *regs)
char *file;
char c;
- if (__get_user(line, (unsigned short __user *)(eip + 2)))
+ if (probe_kernel_address((unsigned short __user *)(eip + 2),
+ line))
break;
if (__get_user(file, (char * __user *)(eip + 4)) ||
(unsigned long)file < PAGE_OFFSET || __get_user(c, file))
@@ -629,18 +696,24 @@ gp_in_kernel:
}
}
-static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+mem_parity_error(unsigned char reason, struct pt_regs * regs)
{
- printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
- "to continue\n");
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+ "CPU %d.\n", reason, smp_processor_id());
printk(KERN_EMERG "You probably have a hardware problem with your RAM "
"chips\n");
+ if (panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
/* Clear and disable the memory parity error line. */
clear_mem_error(reason);
}
-static void io_check_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+io_check_error(unsigned char reason, struct pt_regs * regs)
{
unsigned long i;
@@ -656,7 +729,8 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs)
outb(reason, 0x61);
}
-static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
{
#ifdef CONFIG_MCA
/* Might actually be able to figure out what the guilty party
@@ -666,15 +740,18 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
return;
}
#endif
- printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
- reason, smp_processor_id());
- printk("Dazed and confused, but trying to continue\n");
- printk("Do you have a strange power saving mode enabled?\n");
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+ "CPU %d.\n", reason, smp_processor_id());
+ printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+ if (panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
}
static DEFINE_SPINLOCK(nmi_print_lock);
-void die_nmi (struct pt_regs *regs, const char *msg)
+void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
{
if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
NOTIFY_STOP)
@@ -706,7 +783,7 @@ void die_nmi (struct pt_regs *regs, const char *msg)
do_exit(SIGSEGV);
}
-static void default_do_nmi(struct pt_regs * regs)
+static __kprobes void default_do_nmi(struct pt_regs * regs)
{
unsigned char reason = 0;
@@ -723,12 +800,12 @@ static void default_do_nmi(struct pt_regs * regs)
* Ok, so this is none of the documented NMI sources,
* so it must be the NMI watchdog.
*/
- if (nmi_watchdog) {
- nmi_watchdog_tick(regs);
+ if (nmi_watchdog_tick(regs, reason))
return;
- }
+ if (!do_nmi_callback(regs, smp_processor_id()))
#endif
- unknown_nmi_error(reason, regs);
+ unknown_nmi_error(reason, regs);
+
return;
}
if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
@@ -744,14 +821,7 @@ static void default_do_nmi(struct pt_regs * regs)
reassert_nmi();
}
-static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
-{
- return 0;
-}
-
-static nmi_callback_t nmi_callback = dummy_nmi_callback;
-
-fastcall void do_nmi(struct pt_regs * regs, long error_code)
+fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code)
{
int cpu;
@@ -761,25 +831,11 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
++nmi_count(cpu);
- if (!rcu_dereference(nmi_callback)(regs, cpu))
- default_do_nmi(regs);
+ default_do_nmi(regs);
nmi_exit();
}
-void set_nmi_callback(nmi_callback_t callback)
-{
- vmalloc_sync_all();
- rcu_assign_pointer(nmi_callback, callback);
-}
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-
-void unset_nmi_callback(void)
-{
- nmi_callback = dummy_nmi_callback;
-}
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
-
#ifdef CONFIG_KPROBES
fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
@@ -1119,20 +1175,6 @@ void __init trap_init_f00f_bug(void)
}
#endif
-#define _set_gate(gate_addr,type,dpl,addr,seg) \
-do { \
- int __d0, __d1; \
- __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
- "movw %4,%%dx\n\t" \
- "movl %%eax,%0\n\t" \
- "movl %%edx,%1" \
- :"=m" (*((long *) (gate_addr))), \
- "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
- :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
- "3" ((char *) (addr)),"2" ((seg) << 16)); \
-} while (0)
-
-
/*
* This needs to use 'idt_table' rather than 'idt', and
* thus use the _nonmapped_ version of the IDT, as the
@@ -1141,7 +1183,7 @@ do { \
*/
void set_intr_gate(unsigned int n, void *addr)
{
- _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
+ _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
}
/*
@@ -1149,22 +1191,22 @@ void set_intr_gate(unsigned int n, void *addr)
*/
static inline void set_system_intr_gate(unsigned int n, void *addr)
{
- _set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS);
+ _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
}
static void __init set_trap_gate(unsigned int n, void *addr)
{
- _set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
+ _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
}
static void __init set_system_gate(unsigned int n, void *addr)
{
- _set_gate(idt_table+n,15,3,addr,__KERNEL_CS);
+ _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
}
static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
{
- _set_gate(idt_table+n,5,0,0,(gdt_entry<<3));
+ _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
}
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index 7e0d8dab207..b8fa0a8b2e4 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -192,7 +192,7 @@ int recalibrate_cpu_khz(void)
EXPORT_SYMBOL(recalibrate_cpu_khz);
-void tsc_init(void)
+void __init tsc_init(void)
{
if (!cpu_has_tsc || tsc_disable)
return;
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 2d4f1386e2b..1e7ac1c44dd 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(phys_startup_32)
jiffies = jiffies_64;
+
+PHDRS {
+ text PT_LOAD FLAGS(5); /* R_E */
+ data PT_LOAD FLAGS(7); /* RWE */
+ note PT_NOTE FLAGS(4); /* R__ */
+}
SECTIONS
{
. = __KERNEL_START;
@@ -26,7 +32,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x9090
+ } :text = 0x9090
_etext = .; /* End of text section */
@@ -48,7 +54,7 @@ SECTIONS
.data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
*(.data)
CONSTRUCTORS
- }
+ } :data
. = ALIGN(4096);
__nosave_begin = .;
@@ -184,4 +190,6 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
+
+ NOTES
}
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
index 914933e9ec3..d86a548b8d5 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -4,6 +4,6 @@
lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
- bitops.o
+ bitops.o semaphore.o
lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S
new file mode 100644
index 00000000000..01f80b5c45d
--- /dev/null
+++ b/arch/i386/lib/semaphore.S
@@ -0,0 +1,217 @@
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.i>
+#include <asm/frame.i>
+#include <asm/dwarf2.h>
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %eax contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax whish is either a return
+ * value or just clobbered..
+ */
+ .section .sched.text
+ENTRY(__down_failed)
+ CFI_STARTPROC
+ FRAME
+ pushl %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ pushl %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ call __down
+ popl %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE ecx
+ popl %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE edx
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__down_failed)
+
+ENTRY(__down_failed_interruptible)
+ CFI_STARTPROC
+ FRAME
+ pushl %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ pushl %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ call __down_interruptible
+ popl %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE ecx
+ popl %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE edx
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__down_failed_interruptible)
+
+ENTRY(__down_failed_trylock)
+ CFI_STARTPROC
+ FRAME
+ pushl %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ pushl %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ call __down_trylock
+ popl %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE ecx
+ popl %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE edx
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__down_failed_trylock)
+
+ENTRY(__up_wakeup)
+ CFI_STARTPROC
+ FRAME
+ pushl %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ pushl %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ call __up
+ popl %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE ecx
+ popl %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE edx
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__up_wakeup)
+
+/*
+ * rw spinlock fallbacks
+ */
+#ifdef CONFIG_SMP
+ENTRY(__write_lock_failed)
+ CFI_STARTPROC simple
+ FRAME
+2: LOCK_PREFIX
+ addl $ RW_LOCK_BIAS,(%eax)
+1: rep; nop
+ cmpl $ RW_LOCK_BIAS,(%eax)
+ jne 1b
+ LOCK_PREFIX
+ subl $ RW_LOCK_BIAS,(%eax)
+ jnz 2b
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__write_lock_failed)
+
+ENTRY(__read_lock_failed)
+ CFI_STARTPROC
+ FRAME
+2: LOCK_PREFIX
+ incl (%eax)
+1: rep; nop
+ cmpl $1,(%eax)
+ js 1b
+ LOCK_PREFIX
+ decl (%eax)
+ js 2b
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+ END(__read_lock_failed)
+
+#endif
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_down_read_failed)
+ CFI_STARTPROC
+ push %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ push %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ call rwsem_down_read_failed
+ pop %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ pop %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ ret
+ CFI_ENDPROC
+ END(call_rwsem_down_read_failed)
+
+ENTRY(call_rwsem_down_write_failed)
+ CFI_STARTPROC
+ push %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ calll rwsem_down_write_failed
+ pop %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ ret
+ CFI_ENDPROC
+ END(call_rwsem_down_write_failed)
+
+ENTRY(call_rwsem_wake)
+ CFI_STARTPROC
+ decw %dx /* do nothing if still outstanding active readers */
+ jnz 1f
+ push %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ call rwsem_wake
+ pop %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+1: ret
+ CFI_ENDPROC
+ END(call_rwsem_wake)
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_downgrade_wake)
+ CFI_STARTPROC
+ push %ecx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ecx,0
+ push %edx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET edx,0
+ call rwsem_downgrade_wake
+ pop %edx
+ CFI_ADJUST_CFA_OFFSET -4
+ pop %ecx
+ CFI_ADJUST_CFA_OFFSET -4
+ ret
+ CFI_ENDPROC
+ END(call_rwsem_downgrade_wake)
+
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index ef7a6e6fcb9..33d9f93557b 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -5,6 +5,7 @@
#define APIC_DEFINITION 1
#include <linux/threads.h>
#include <linux/cpumask.h>
+#include <asm/smp.h>
#include <asm/mpspec.h>
#include <asm/genapic.h>
#include <asm/fixmap.h>
diff --git a/arch/i386/mach-generic/es7000.c b/arch/i386/mach-generic/es7000.c
index 845cdd0b359..aa144d82334 100644
--- a/arch/i386/mach-generic/es7000.c
+++ b/arch/i386/mach-generic/es7000.c
@@ -4,6 +4,7 @@
#define APIC_DEFINITION 1
#include <linux/threads.h>
#include <linux/cpumask.h>
+#include <asm/smp.h>
#include <asm/mpspec.h>
#include <asm/genapic.h>
#include <asm/fixmap.h>
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c
index bcd1bcfaa72..94b1fd9cbe3 100644
--- a/arch/i386/mach-generic/probe.c
+++ b/arch/i386/mach-generic/probe.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/init.h>
+#include <linux/errno.h>
#include <asm/fixmap.h>
#include <asm/mpspec.h>
#include <asm/apicdef.h>
@@ -29,7 +30,24 @@ struct genapic *apic_probe[] __initdata = {
NULL,
};
-static int cmdline_apic;
+static int cmdline_apic __initdata;
+static int __init parse_apic(char *arg)
+{
+ int i;
+
+ if (!arg)
+ return -EINVAL;
+
+ for (i = 0; apic_probe[i]; i++) {
+ if (!strcmp(apic_probe[i]->name, arg)) {
+ genapic = apic_probe[i];
+ cmdline_apic = 1;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+early_param("apic", parse_apic);
void __init generic_bigsmp_probe(void)
{
@@ -48,40 +66,20 @@ void __init generic_bigsmp_probe(void)
}
}
-void __init generic_apic_probe(char *command_line)
+void __init generic_apic_probe(void)
{
- char *s;
- int i;
- int changed = 0;
-
- s = strstr(command_line, "apic=");
- if (s && (s == command_line || isspace(s[-1]))) {
- char *p = strchr(s, ' '), old;
- if (!p)
- p = strchr(s, '\0');
- old = *p;
- *p = 0;
- for (i = 0; !changed && apic_probe[i]; i++) {
- if (!strcmp(apic_probe[i]->name, s+5)) {
- changed = 1;
+ if (!cmdline_apic) {
+ int i;
+ for (i = 0; apic_probe[i]; i++) {
+ if (apic_probe[i]->probe()) {
genapic = apic_probe[i];
+ break;
}
}
- if (!changed)
- printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
- *p = old;
- cmdline_apic = changed;
- }
- for (i = 0; !changed && apic_probe[i]; i++) {
- if (apic_probe[i]->probe()) {
- changed = 1;
- genapic = apic_probe[i];
- }
+ /* Not visible without early console */
+ if (!apic_probe[i])
+ panic("Didn't find an APIC driver");
}
- /* Not visible without early console */
- if (!changed)
- panic("Didn't find an APIC driver");
-
printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
}
@@ -119,7 +117,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 0;
}
+#ifdef CONFIG_SMP
int hard_smp_processor_id(void)
{
return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
}
+#endif
diff --git a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c
index b73501ddd65..f7e5d66648d 100644
--- a/arch/i386/mach-generic/summit.c
+++ b/arch/i386/mach-generic/summit.c
@@ -4,6 +4,7 @@
#define APIC_DEFINITION 1
#include <linux/threads.h>
#include <linux/cpumask.h>
+#include <asm/smp.h>
#include <asm/mpspec.h>
#include <asm/genapic.h>
#include <asm/fixmap.h>
diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
index 50f6de6ff64..f39887359e8 100644
--- a/arch/i386/mach-voyager/voyager_thread.c
+++ b/arch/i386/mach-voyager/voyager_thread.c
@@ -130,7 +130,6 @@ thread(void *unused)
init_timer(&wakeup_timer);
sigfillset(&current->blocked);
- current->signal->tty = NULL;
printk(KERN_NOTICE "Voyager starting monitor thread\n");
diff --git a/arch/i386/mm/boot_ioremap.c b/arch/i386/mm/boot_ioremap.c
index 5d44f4f5ff5..4de11f508c3 100644
--- a/arch/i386/mm/boot_ioremap.c
+++ b/arch/i386/mm/boot_ioremap.c
@@ -29,8 +29,11 @@
*/
#define BOOT_PTE_PTRS (PTRS_PER_PTE*2)
-#define boot_pte_index(address) \
- (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1))
+
+static unsigned long boot_pte_index(unsigned long vaddr)
+{
+ return __pa(vaddr) >> PAGE_SHIFT;
+}
static inline boot_pte_t* boot_vaddr_to_pte(void *address)
{
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 7c392dc553b..51e3739dd22 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -117,7 +117,8 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
void *node_remap_end_vaddr[MAX_NUMNODES];
void *node_remap_alloc_vaddr[MAX_NUMNODES];
-
+static unsigned long kva_start_pfn;
+static unsigned long kva_pages;
/*
* FLAT - support for basic PC memory model with discontig enabled, essentially
* a single node with all available processors in it with a flat
@@ -156,21 +157,6 @@ static void __init find_max_pfn_node(int nid)
BUG();
}
-/* Find the owning node for a pfn. */
-int early_pfn_to_nid(unsigned long pfn)
-{
- int nid;
-
- for_each_node(nid) {
- if (node_end_pfn[nid] == 0)
- break;
- if (node_start_pfn[nid] <= pfn && node_end_pfn[nid] >= pfn)
- return nid;
- }
-
- return 0;
-}
-
/*
* Allocate memory for the pg_data_t for this node via a crude pre-bootmem
* method. For node zero take this from the bottom of memory, for
@@ -226,6 +212,8 @@ static unsigned long calculate_numa_remap_pages(void)
unsigned long pfn;
for_each_online_node(nid) {
+ unsigned old_end_pfn = node_end_pfn[nid];
+
/*
* The acpi/srat node info can show hot-add memroy zones
* where memory could be added but not currently present.
@@ -275,6 +263,7 @@ static unsigned long calculate_numa_remap_pages(void)
node_end_pfn[nid] -= size;
node_remap_start_pfn[nid] = node_end_pfn[nid];
+ shrink_active_range(nid, old_end_pfn, node_end_pfn[nid]);
}
printk("Reserving total of %ld pages for numa KVA remap\n",
reserve_pages);
@@ -286,7 +275,6 @@ unsigned long __init setup_memory(void)
{
int nid;
unsigned long system_start_pfn, system_max_low_pfn;
- unsigned long reserve_pages;
/*
* When mapping a NUMA machine we allocate the node_mem_map arrays
@@ -298,14 +286,23 @@ unsigned long __init setup_memory(void)
find_max_pfn();
get_memcfg_numa();
- reserve_pages = calculate_numa_remap_pages();
+ kva_pages = calculate_numa_remap_pages();
/* partially used pages are not usable - thus round upwards */
system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end);
- system_max_low_pfn = max_low_pfn = find_max_low_pfn() - reserve_pages;
- printk("reserve_pages = %ld find_max_low_pfn() ~ %ld\n",
- reserve_pages, max_low_pfn + reserve_pages);
+ kva_start_pfn = find_max_low_pfn() - kva_pages;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Numa kva area is below the initrd */
+ if (LOADER_TYPE && INITRD_START)
+ kva_start_pfn = PFN_DOWN(INITRD_START) - kva_pages;
+#endif
+ kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1);
+
+ system_max_low_pfn = max_low_pfn = find_max_low_pfn();
+ printk("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n",
+ kva_start_pfn, max_low_pfn);
printk("max_pfn = %ld\n", max_pfn);
#ifdef CONFIG_HIGHMEM
highstart_pfn = highend_pfn = max_pfn;
@@ -313,6 +310,11 @@ unsigned long __init setup_memory(void)
highstart_pfn = system_max_low_pfn;
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
pages_to_mb(highend_pfn - highstart_pfn));
+ num_physpages = highend_pfn;
+ high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+ num_physpages = system_max_low_pfn;
+ high_memory = (void *) __va(system_max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
pages_to_mb(system_max_low_pfn));
@@ -323,7 +325,7 @@ unsigned long __init setup_memory(void)
(ulong) pfn_to_kaddr(max_low_pfn));
for_each_online_node(nid) {
node_remap_start_vaddr[nid] = pfn_to_kaddr(
- highstart_pfn + node_remap_offset[nid]);
+ kva_start_pfn + node_remap_offset[nid]);
/* Init the node remap allocator */
node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
(node_remap_size[nid] * PAGE_SIZE);
@@ -338,7 +340,6 @@ unsigned long __init setup_memory(void)
}
printk("High memory starts at vaddr %08lx\n",
(ulong) pfn_to_kaddr(highstart_pfn));
- vmalloc_earlyreserve = reserve_pages * PAGE_SIZE;
for_each_online_node(nid)
find_max_pfn_node(nid);
@@ -348,48 +349,30 @@ unsigned long __init setup_memory(void)
return max_low_pfn;
}
+void __init numa_kva_reserve(void)
+{
+ reserve_bootmem(PFN_PHYS(kva_start_pfn),PFN_PHYS(kva_pages));
+}
+
void __init zone_sizes_init(void)
{
int nid;
-
-
- for_each_online_node(nid) {
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
- unsigned long *zholes_size;
- unsigned int max_dma;
-
- unsigned long low = max_low_pfn;
- unsigned long start = node_start_pfn[nid];
- unsigned long high = node_end_pfn[nid];
-
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
- if (node_has_online_mem(nid)){
- if (start > low) {
-#ifdef CONFIG_HIGHMEM
- BUG_ON(start > high);
- zones_size[ZONE_HIGHMEM] = high - start;
-#endif
- } else {
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- BUG_ON(max_dma > low);
- BUG_ON(low > high);
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = high - low;
-#endif
- }
- }
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+ virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+ max_low_pfn,
+ highend_pfn
+ };
+
+ /* If SRAT has not registered memory, register it now */
+ if (find_max_pfn_with_active_regions() == 0) {
+ for_each_online_node(nid) {
+ if (node_has_online_mem(nid))
+ add_active_range(nid, node_start_pfn[nid],
+ node_end_pfn[nid]);
}
-
- zholes_size = get_zholes_size(nid);
-
- free_area_init_node(nid, NODE_DATA(nid), zones_size, start,
- zholes_size);
}
+
+ free_area_init_nodes(max_zone_pfns);
return;
}
@@ -409,7 +392,7 @@ void __init set_highmem_pages_init(int bad_ppro)
zone_end_pfn = zone_start_pfn + zone->spanned_pages;
printk("Initializing %s for node %d (%08lx:%08lx)\n",
- zone->name, zone->zone_pgdat->node_id,
+ zone->name, zone_to_nid(zone),
zone_start_pfn, zone_end_pfn);
for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c
index de03c5430ab..0ce4f22a263 100644
--- a/arch/i386/mm/extable.c
+++ b/arch/i386/mm/extable.c
@@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)
const struct exception_table_entry *fixup;
#ifdef CONFIG_PNPBIOS
- if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
+ if (unlikely(SEGMENT_IS_PNP_CODE(regs->xcs)))
{
extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
extern u32 pnp_bios_is_utter_crap;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index f7279468323..5e17a3f43b4 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -27,21 +27,24 @@
#include <asm/uaccess.h>
#include <asm/desc.h>
#include <asm/kdebug.h>
+#include <asm/segment.h>
extern void die(const char *,struct pt_regs *,long);
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
int register_page_fault_notifier(struct notifier_block *nb)
{
vmalloc_sync_all();
return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}
+EXPORT_SYMBOL_GPL(register_page_fault_notifier);
int unregister_page_fault_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
}
+EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
static inline int notify_page_fault(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
@@ -55,14 +58,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
};
return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
}
-#else
-static inline int notify_page_fault(enum die_val val, const char *str,
- struct pt_regs *regs, long err, int trap, int sig)
-{
- return NOTIFY_DONE;
-}
-#endif
-
/*
* Unlock any spinlocks which will prevent us from getting the
@@ -119,10 +114,10 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
}
/* The standard kernel/user address space limit. */
- *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
+ *eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;
/* By far the most common cases. */
- if (likely(seg == __USER_CS || seg == __KERNEL_CS))
+ if (likely(SEGMENT_IS_FLAT_CODE(seg)))
return eip;
/* Check the segment exists, is within the current LDT/GDT size,
@@ -436,11 +431,7 @@ good_area:
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
-#ifdef TEST_VERIFY_AREA
- if (regs->cs == KERNEL_CS)
- printk("WP fault at %08lx\n", regs->eip);
-#endif
- /* fall through */
+ /* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
index b6eb4dcb877..ba44000b906 100644
--- a/arch/i386/mm/highmem.c
+++ b/arch/i386/mm/highmem.c
@@ -54,7 +54,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
- if (vaddr < FIXADDR_START) { // FIXME
+ if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
dec_preempt_count();
preempt_check_resched();
return;
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 89e8486aac3..4a5a914b343 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -435,16 +435,22 @@ u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
* on Enable
* off Disable
*/
-void __init noexec_setup(const char *str)
+static int __init noexec_setup(char *str)
{
- if (!strncmp(str, "on",2) && cpu_has_nx) {
- __supported_pte_mask |= _PAGE_NX;
- disable_nx = 0;
- } else if (!strncmp(str,"off",3)) {
+ if (!str || !strcmp(str, "on")) {
+ if (cpu_has_nx) {
+ __supported_pte_mask |= _PAGE_NX;
+ disable_nx = 0;
+ }
+ } else if (!strcmp(str,"off")) {
disable_nx = 1;
__supported_pte_mask &= ~_PAGE_NX;
- }
+ } else
+ return -EINVAL;
+
+ return 0;
}
+early_param("noexec", noexec_setup);
int nx_enabled = 0;
#ifdef CONFIG_X86_PAE
@@ -552,18 +558,6 @@ static void __init test_wp_bit(void)
}
}
-static void __init set_max_mapnr_init(void)
-{
-#ifdef CONFIG_HIGHMEM
- num_physpages = highend_pfn;
-#else
- num_physpages = max_low_pfn;
-#endif
-#ifdef CONFIG_FLATMEM
- max_mapnr = num_physpages;
-#endif
-}
-
static struct kcore_list kcore_mem, kcore_vmalloc;
void __init mem_init(void)
@@ -590,14 +584,6 @@ void __init mem_init(void)
}
#endif
- set_max_mapnr_init();
-
-#ifdef CONFIG_HIGHMEM
- high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
-#else
- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
-#endif
-
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();
@@ -629,6 +615,48 @@ void __init mem_init(void)
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
);
+#if 1 /* double-sanity-check paranoia */
+ printk("virtual kernel memory layout:\n"
+ " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
+#ifdef CONFIG_HIGHMEM
+ " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
+#endif
+ " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
+ " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
+ " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
+ FIXADDR_START, FIXADDR_TOP,
+ (FIXADDR_TOP - FIXADDR_START) >> 10,
+
+#ifdef CONFIG_HIGHMEM
+ PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
+ (LAST_PKMAP*PAGE_SIZE) >> 10,
+#endif
+
+ VMALLOC_START, VMALLOC_END,
+ (VMALLOC_END - VMALLOC_START) >> 20,
+
+ (unsigned long)__va(0), (unsigned long)high_memory,
+ ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+
+ (unsigned long)&__init_begin, (unsigned long)&__init_end,
+ ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10,
+
+ (unsigned long)&_etext, (unsigned long)&_edata,
+ ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+
+ (unsigned long)&_text, (unsigned long)&_etext,
+ ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+
+#ifdef CONFIG_HIGHMEM
+ BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE > FIXADDR_START);
+ BUG_ON(VMALLOC_END > PKMAP_BASE);
+#endif
+ BUG_ON(VMALLOC_START > VMALLOC_END);
+ BUG_ON((unsigned long)high_memory > VMALLOC_START);
+#endif /* double-sanity-check paranoia */
+
#ifdef CONFIG_X86_PAE
if (!cpu_has_pae)
panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
@@ -657,7 +685,7 @@ void __init mem_init(void)
int arch_add_memory(int nid, u64 start, u64 size)
{
struct pglist_data *pgdata = &contig_page_data;
- struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
+ struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index bd98768d876..10126e3f817 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -60,7 +61,9 @@ void show_mem(void)
printk(KERN_INFO "%lu pages writeback\n",
global_page_state(NR_WRITEBACK));
printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
- printk(KERN_INFO "%lu pages slab\n", global_page_state(NR_SLAB));
+ printk(KERN_INFO "%lu pages slab\n",
+ global_page_state(NR_SLAB_RECLAIMABLE) +
+ global_page_state(NR_SLAB_UNRECLAIMABLE));
printk(KERN_INFO "%lu pages pagetables\n",
global_page_state(NR_PAGETABLE));
}
@@ -137,6 +140,12 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
__flush_tlb_one(vaddr);
}
+static int fixmaps;
+#ifndef CONFIG_COMPAT_VDSO
+unsigned long __FIXADDR_TOP = 0xfffff000;
+EXPORT_SYMBOL(__FIXADDR_TOP);
+#endif
+
void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
{
unsigned long address = __fix_to_virt(idx);
@@ -146,6 +155,25 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
return;
}
set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
+ fixmaps++;
+}
+
+/**
+ * reserve_top_address - reserves a hole in the top of kernel address space
+ * @reserve - size of hole to reserve
+ *
+ * Can be used to relocate the fixmap area and poke a hole in the top
+ * of kernel address space to make room for a hypervisor.
+ */
+void reserve_top_address(unsigned long reserve)
+{
+ BUG_ON(fixmaps > 0);
+#ifdef CONFIG_COMPAT_VDSO
+ BUG_ON(reserve != 0);
+#else
+ __FIXADDR_TOP = -reserve - PAGE_SIZE;
+ __VMALLOC_RESERVE += reserve;
+#endif
}
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 5f8dc8a21bd..3700eef7874 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -17,14 +17,15 @@
#include <asm/nmi.h>
#include <asm/msr.h>
#include <asm/apic.h>
+#include <asm/kdebug.h>
#include "op_counter.h"
#include "op_x86_model.h"
-
+
static struct op_x86_model_spec const * model;
static struct op_msrs cpu_msrs[NR_CPUS];
static unsigned long saved_lvtpc[NR_CPUS];
-
+
static int nmi_start(void);
static void nmi_stop(void);
@@ -82,13 +83,24 @@ static void exit_driverfs(void)
#define exit_driverfs() do { } while (0)
#endif /* CONFIG_PM */
-
-static int nmi_callback(struct pt_regs * regs, int cpu)
+static int profile_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
- return model->check_ctrs(regs, &cpu_msrs[cpu]);
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+ int cpu = smp_processor_id();
+
+ switch(val) {
+ case DIE_NMI:
+ if (model->check_ctrs(args->regs, &cpu_msrs[cpu]))
+ ret = NOTIFY_STOP;
+ break;
+ default:
+ break;
+ }
+ return ret;
}
-
-
+
static void nmi_cpu_save_registers(struct op_msrs * msrs)
{
unsigned int const nr_ctrs = model->num_counters;
@@ -98,15 +110,19 @@ static void nmi_cpu_save_registers(struct op_msrs * msrs)
unsigned int i;
for (i = 0; i < nr_ctrs; ++i) {
- rdmsr(counters[i].addr,
- counters[i].saved.low,
- counters[i].saved.high);
+ if (counters[i].addr){
+ rdmsr(counters[i].addr,
+ counters[i].saved.low,
+ counters[i].saved.high);
+ }
}
for (i = 0; i < nr_ctrls; ++i) {
- rdmsr(controls[i].addr,
- controls[i].saved.low,
- controls[i].saved.high);
+ if (controls[i].addr){
+ rdmsr(controls[i].addr,
+ controls[i].saved.low,
+ controls[i].saved.high);
+ }
}
}
@@ -170,27 +186,29 @@ static void nmi_cpu_setup(void * dummy)
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
+static struct notifier_block profile_exceptions_nb = {
+ .notifier_call = profile_exceptions_notify,
+ .next = NULL,
+ .priority = 0
+};
static int nmi_setup(void)
{
+ int err=0;
+
if (!allocate_msrs())
return -ENOMEM;
- /* We walk a thin line between law and rape here.
- * We need to be careful to install our NMI handler
- * without actually triggering any NMIs as this will
- * break the core code horrifically.
- */
- if (reserve_lapic_nmi() < 0) {
+ if ((err = register_die_notifier(&profile_exceptions_nb))){
free_msrs();
- return -EBUSY;
+ return err;
}
+
/* We need to serialize save and setup for HT because the subset
* of msrs are distinct for save and setup operations
*/
on_each_cpu(nmi_save_registers, NULL, 0, 1);
on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
- set_nmi_callback(nmi_callback);
nmi_enabled = 1;
return 0;
}
@@ -205,15 +223,19 @@ static void nmi_restore_registers(struct op_msrs * msrs)
unsigned int i;
for (i = 0; i < nr_ctrls; ++i) {
- wrmsr(controls[i].addr,
- controls[i].saved.low,
- controls[i].saved.high);
+ if (controls[i].addr){
+ wrmsr(controls[i].addr,
+ controls[i].saved.low,
+ controls[i].saved.high);
+ }
}
for (i = 0; i < nr_ctrs; ++i) {
- wrmsr(counters[i].addr,
- counters[i].saved.low,
- counters[i].saved.high);
+ if (counters[i].addr){
+ wrmsr(counters[i].addr,
+ counters[i].saved.low,
+ counters[i].saved.high);
+ }
}
}
@@ -234,6 +256,7 @@ static void nmi_cpu_shutdown(void * dummy)
apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
apic_write(APIC_LVTERR, v);
nmi_restore_registers(msrs);
+ model->shutdown(msrs);
}
@@ -241,8 +264,7 @@ static void nmi_shutdown(void)
{
nmi_enabled = 0;
on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
- unset_nmi_callback();
- release_lapic_nmi();
+ unregister_die_notifier(&profile_exceptions_nb);
free_msrs();
}
@@ -284,6 +306,14 @@ static int nmi_create_files(struct super_block * sb, struct dentry * root)
struct dentry * dir;
char buf[4];
+ /* quick little hack to _not_ expose a counter if it is not
+ * available for use. This should protect userspace app.
+ * NOTE: assumes 1:1 mapping here (that counters are organized
+ * sequentially in their struct assignment).
+ */
+ if (unlikely(!avail_to_resrv_perfctr_nmi_bit(i)))
+ continue;
+
snprintf(buf, sizeof(buf), "%d", i);
dir = oprofilefs_mkdir(sb, root, buf);
oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
diff --git a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c
index 930a1127bb3..abf0ba52a63 100644
--- a/arch/i386/oprofile/nmi_timer_int.c
+++ b/arch/i386/oprofile/nmi_timer_int.c
@@ -17,34 +17,49 @@
#include <asm/nmi.h>
#include <asm/apic.h>
#include <asm/ptrace.h>
+#include <asm/kdebug.h>
-static int nmi_timer_callback(struct pt_regs * regs, int cpu)
+static int profile_timer_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
- oprofile_add_sample(regs, 0);
- return 1;
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ switch(val) {
+ case DIE_NMI:
+ oprofile_add_sample(args->regs, 0);
+ ret = NOTIFY_STOP;
+ break;
+ default:
+ break;
+ }
+ return ret;
}
+static struct notifier_block profile_timer_exceptions_nb = {
+ .notifier_call = profile_timer_exceptions_notify,
+ .next = NULL,
+ .priority = 0
+};
+
static int timer_start(void)
{
- disable_timer_nmi_watchdog();
- set_nmi_callback(nmi_timer_callback);
+ if (register_die_notifier(&profile_timer_exceptions_nb))
+ return 1;
return 0;
}
static void timer_stop(void)
{
- enable_timer_nmi_watchdog();
- unset_nmi_callback();
+ unregister_die_notifier(&profile_timer_exceptions_nb);
synchronize_sched(); /* Allow already-started NMIs to complete. */
}
int __init op_nmi_timer_init(struct oprofile_operations * ops)
{
- extern int nmi_active;
-
- if (nmi_active <= 0)
+ if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
return -ENODEV;
ops->start = timer_start;
diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
index 693bdea4a52..3057a19e464 100644
--- a/arch/i386/oprofile/op_model_athlon.c
+++ b/arch/i386/oprofile/op_model_athlon.c
@@ -21,10 +21,12 @@
#define NUM_COUNTERS 4
#define NUM_CONTROLS 4
+#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1);} while (0)
#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
@@ -40,15 +42,21 @@ static unsigned long reset_value[NUM_COUNTERS];
static void athlon_fill_in_addresses(struct op_msrs * const msrs)
{
- msrs->counters[0].addr = MSR_K7_PERFCTR0;
- msrs->counters[1].addr = MSR_K7_PERFCTR1;
- msrs->counters[2].addr = MSR_K7_PERFCTR2;
- msrs->counters[3].addr = MSR_K7_PERFCTR3;
-
- msrs->controls[0].addr = MSR_K7_EVNTSEL0;
- msrs->controls[1].addr = MSR_K7_EVNTSEL1;
- msrs->controls[2].addr = MSR_K7_EVNTSEL2;
- msrs->controls[3].addr = MSR_K7_EVNTSEL3;
+ int i;
+
+ for (i=0; i < NUM_COUNTERS; i++) {
+ if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+ msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+ else
+ msrs->counters[i].addr = 0;
+ }
+
+ for (i=0; i < NUM_CONTROLS; i++) {
+ if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+ msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+ else
+ msrs->controls[i].addr = 0;
+ }
}
@@ -59,19 +67,23 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
/* clear all counters */
for (i = 0 ; i < NUM_CONTROLS; ++i) {
+ if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+ continue;
CTRL_READ(low, high, msrs, i);
CTRL_CLEAR(low);
CTRL_WRITE(low, high, msrs, i);
}
-
+
/* avoid a false detection of ctr overflows in NMI handler */
for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (unlikely(!CTR_IS_RESERVED(msrs,i)))
+ continue;
CTR_WRITE(1, msrs, i);
}
/* enable active counters */
for (i = 0; i < NUM_COUNTERS; ++i) {
- if (counter_config[i].enabled) {
+ if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
reset_value[i] = counter_config[i].count;
CTR_WRITE(counter_config[i].count, msrs, i);
@@ -98,6 +110,8 @@ static int athlon_check_ctrs(struct pt_regs * const regs,
int i;
for (i = 0 ; i < NUM_COUNTERS; ++i) {
+ if (!reset_value[i])
+ continue;
CTR_READ(low, high, msrs, i);
if (CTR_OVERFLOWED(low)) {
oprofile_add_sample(regs, i);
@@ -132,12 +146,27 @@ static void athlon_stop(struct op_msrs const * const msrs)
/* Subtle: stop on all counters to avoid race with
* setting our pm callback */
for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+ if (!reset_value[i])
+ continue;
CTRL_READ(low, high, msrs, i);
CTRL_SET_INACTIVE(low);
CTRL_WRITE(low, high, msrs, i);
}
}
+static void athlon_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
+
+ for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+ if (CTR_IS_RESERVED(msrs,i))
+ release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+ }
+ for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+ if (CTRL_IS_RESERVED(msrs,i))
+ release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+ }
+}
struct op_x86_model_spec const op_athlon_spec = {
.num_counters = NUM_COUNTERS,
@@ -146,5 +175,6 @@ struct op_x86_model_spec const op_athlon_spec = {
.setup_ctrs = &athlon_setup_ctrs,
.check_ctrs = &athlon_check_ctrs,
.start = &athlon_start,
- .stop = &athlon_stop
+ .stop = &athlon_stop,
+ .shutdown = &athlon_shutdown
};
diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
index 7c61d357b82..47925927b12 100644
--- a/arch/i386/oprofile/op_model_p4.c
+++ b/arch/i386/oprofile/op_model_p4.c
@@ -32,7 +32,7 @@
#define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2)
static unsigned int num_counters = NUM_COUNTERS_NON_HT;
-
+static unsigned int num_controls = NUM_CONTROLS_NON_HT;
/* this has to be checked dynamically since the
hyper-threadedness of a chip is discovered at
@@ -40,8 +40,10 @@ static unsigned int num_counters = NUM_COUNTERS_NON_HT;
static inline void setup_num_counters(void)
{
#ifdef CONFIG_SMP
- if (smp_num_siblings == 2)
+ if (smp_num_siblings == 2){
num_counters = NUM_COUNTERS_HT2;
+ num_controls = NUM_CONTROLS_HT2;
+ }
#endif
}
@@ -97,15 +99,6 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = {
#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT
-/* All cccr we don't use. */
-static int p4_unused_cccr[NUM_UNUSED_CCCRS] = {
- MSR_P4_BPU_CCCR1, MSR_P4_BPU_CCCR3,
- MSR_P4_MS_CCCR1, MSR_P4_MS_CCCR3,
- MSR_P4_FLAME_CCCR1, MSR_P4_FLAME_CCCR3,
- MSR_P4_IQ_CCCR0, MSR_P4_IQ_CCCR1,
- MSR_P4_IQ_CCCR2, MSR_P4_IQ_CCCR3
-};
-
/* p4 event codes in libop/op_event.h are indices into this table. */
static struct p4_event_binding p4_events[NUM_EVENTS] = {
@@ -372,6 +365,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = {
#define CCCR_OVF_P(cccr) ((cccr) & (1U<<31))
#define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31)))
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0)
#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0)
#define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000))
@@ -401,29 +396,34 @@ static unsigned long reset_value[NUM_COUNTERS_NON_HT];
static void p4_fill_in_addresses(struct op_msrs * const msrs)
{
unsigned int i;
- unsigned int addr, stag;
+ unsigned int addr, cccraddr, stag;
setup_num_counters();
stag = get_stagger();
- /* the counter registers we pay attention to */
+ /* initialize some registers */
for (i = 0; i < num_counters; ++i) {
- msrs->counters[i].addr =
- p4_counters[VIRT_CTR(stag, i)].counter_address;
+ msrs->counters[i].addr = 0;
}
-
- /* FIXME: bad feeling, we don't save the 10 counters we don't use. */
-
- /* 18 CCCR registers */
- for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag;
- addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ for (i = 0; i < num_controls; ++i) {
+ msrs->controls[i].addr = 0;
}
+ /* the counter & cccr registers we pay attention to */
+ for (i = 0; i < num_counters; ++i) {
+ addr = p4_counters[VIRT_CTR(stag, i)].counter_address;
+ cccraddr = p4_counters[VIRT_CTR(stag, i)].cccr_address;
+ if (reserve_perfctr_nmi(addr)){
+ msrs->counters[i].addr = addr;
+ msrs->controls[i].addr = cccraddr;
+ }
+ }
+
/* 43 ESCR registers in three or four discontiguous group */
for (addr = MSR_P4_BSU_ESCR0 + stag;
addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
/* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
@@ -431,47 +431,57 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs)
if (boot_cpu_data.x86_model >= 0x3) {
for (addr = MSR_P4_BSU_ESCR0 + stag;
addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
} else {
for (addr = MSR_P4_IQ_ESCR0 + stag;
addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
}
for (addr = MSR_P4_RAT_ESCR0 + stag;
addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
for (addr = MSR_P4_MS_ESCR0 + stag;
addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
for (addr = MSR_P4_IX_ESCR0 + stag;
addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) {
- msrs->controls[i].addr = addr;
+ if (reserve_evntsel_nmi(addr))
+ msrs->controls[i].addr = addr;
}
/* there are 2 remaining non-contiguously located ESCRs */
if (num_counters == NUM_COUNTERS_NON_HT) {
/* standard non-HT CPUs handle both remaining ESCRs*/
- msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
- msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
+ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5))
+ msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR4))
+ msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
} else if (stag == 0) {
/* HT CPUs give the first remainder to the even thread, as
the 32nd control register */
- msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
+ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR4))
+ msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
} else {
/* and two copies of the second to the odd thread,
for the 22st and 23nd control registers */
- msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
- msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5)) {
+ msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+ msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+ }
}
}
@@ -544,7 +554,6 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
{
unsigned int i;
unsigned int low, high;
- unsigned int addr;
unsigned int stag;
stag = get_stagger();
@@ -557,59 +566,24 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
/* clear the cccrs we will use */
for (i = 0 ; i < num_counters ; i++) {
+ if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+ continue;
rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
CCCR_CLEAR(low);
CCCR_SET_REQUIRED_BITS(low);
wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
}
- /* clear cccrs outside our concern */
- for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
- rdmsr(p4_unused_cccr[i], low, high);
- CCCR_CLEAR(low);
- CCCR_SET_REQUIRED_BITS(low);
- wrmsr(p4_unused_cccr[i], low, high);
- }
-
/* clear all escrs (including those outside our concern) */
- for (addr = MSR_P4_BSU_ESCR0 + stag;
- addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) {
- wrmsr(addr, 0, 0);
- }
-
- /* On older models clear also MSR_P4_IQ_ESCR0/1 */
- if (boot_cpu_data.x86_model < 0x3) {
- wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
- wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
- }
-
- for (addr = MSR_P4_RAT_ESCR0 + stag;
- addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
- wrmsr(addr, 0, 0);
- }
-
- for (addr = MSR_P4_MS_ESCR0 + stag;
- addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){
- wrmsr(addr, 0, 0);
- }
-
- for (addr = MSR_P4_IX_ESCR0 + stag;
- addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){
- wrmsr(addr, 0, 0);
+ for (i = num_counters; i < num_controls; i++) {
+ if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+ continue;
+ wrmsr(msrs->controls[i].addr, 0, 0);
}
- if (num_counters == NUM_COUNTERS_NON_HT) {
- wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
- wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
- } else if (stag == 0) {
- wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
- } else {
- wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
- }
-
/* setup all counters */
for (i = 0 ; i < num_counters ; ++i) {
- if (counter_config[i].enabled) {
+ if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs,i))) {
reset_value[i] = counter_config[i].count;
pmc_setup_one_p4_counter(i);
CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
@@ -696,12 +670,32 @@ static void p4_stop(struct op_msrs const * const msrs)
stag = get_stagger();
for (i = 0; i < num_counters; ++i) {
+ if (!reset_value[i])
+ continue;
CCCR_READ(low, high, VIRT_CTR(stag, i));
CCCR_SET_DISABLE(low);
CCCR_WRITE(low, high, VIRT_CTR(stag, i));
}
}
+static void p4_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
+
+ for (i = 0 ; i < num_counters ; ++i) {
+ if (CTR_IS_RESERVED(msrs,i))
+ release_perfctr_nmi(msrs->counters[i].addr);
+ }
+ /* some of the control registers are specially reserved in
+ * conjunction with the counter registers (hence the starting offset).
+ * This saves a few bits.
+ */
+ for (i = num_counters ; i < num_controls ; ++i) {
+ if (CTRL_IS_RESERVED(msrs,i))
+ release_evntsel_nmi(msrs->controls[i].addr);
+ }
+}
+
#ifdef CONFIG_SMP
struct op_x86_model_spec const op_p4_ht2_spec = {
@@ -711,7 +705,8 @@ struct op_x86_model_spec const op_p4_ht2_spec = {
.setup_ctrs = &p4_setup_ctrs,
.check_ctrs = &p4_check_ctrs,
.start = &p4_start,
- .stop = &p4_stop
+ .stop = &p4_stop,
+ .shutdown = &p4_shutdown
};
#endif
@@ -722,5 +717,6 @@ struct op_x86_model_spec const op_p4_spec = {
.setup_ctrs = &p4_setup_ctrs,
.check_ctrs = &p4_check_ctrs,
.start = &p4_start,
- .stop = &p4_stop
+ .stop = &p4_stop,
+ .shutdown = &p4_shutdown
};
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index 5c3ab4b027a..f88e05ba8eb 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -22,10 +22,12 @@
#define NUM_COUNTERS 2
#define NUM_CONTROLS 2
+#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), -1);} while (0)
#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
@@ -41,11 +43,21 @@ static unsigned long reset_value[NUM_COUNTERS];
static void ppro_fill_in_addresses(struct op_msrs * const msrs)
{
- msrs->counters[0].addr = MSR_P6_PERFCTR0;
- msrs->counters[1].addr = MSR_P6_PERFCTR1;
+ int i;
+
+ for (i=0; i < NUM_COUNTERS; i++) {
+ if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+ msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ else
+ msrs->counters[i].addr = 0;
+ }
- msrs->controls[0].addr = MSR_P6_EVNTSEL0;
- msrs->controls[1].addr = MSR_P6_EVNTSEL1;
+ for (i=0; i < NUM_CONTROLS; i++) {
+ if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
+ msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+ else
+ msrs->controls[i].addr = 0;
+ }
}
@@ -56,6 +68,8 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
/* clear all counters */
for (i = 0 ; i < NUM_CONTROLS; ++i) {
+ if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+ continue;
CTRL_READ(low, high, msrs, i);
CTRL_CLEAR(low);
CTRL_WRITE(low, high, msrs, i);
@@ -63,12 +77,14 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
/* avoid a false detection of ctr overflows in NMI handler */
for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (unlikely(!CTR_IS_RESERVED(msrs,i)))
+ continue;
CTR_WRITE(1, msrs, i);
}
/* enable active counters */
for (i = 0; i < NUM_COUNTERS; ++i) {
- if (counter_config[i].enabled) {
+ if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
reset_value[i] = counter_config[i].count;
CTR_WRITE(counter_config[i].count, msrs, i);
@@ -81,6 +97,8 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
CTRL_SET_UM(low, counter_config[i].unit_mask);
CTRL_SET_EVENT(low, counter_config[i].event);
CTRL_WRITE(low, high, msrs, i);
+ } else {
+ reset_value[i] = 0;
}
}
}
@@ -93,6 +111,8 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
int i;
for (i = 0 ; i < NUM_COUNTERS; ++i) {
+ if (!reset_value[i])
+ continue;
CTR_READ(low, high, msrs, i);
if (CTR_OVERFLOWED(low)) {
oprofile_add_sample(regs, i);
@@ -118,18 +138,38 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
static void ppro_start(struct op_msrs const * const msrs)
{
unsigned int low,high;
- CTRL_READ(low, high, msrs, 0);
- CTRL_SET_ACTIVE(low);
- CTRL_WRITE(low, high, msrs, 0);
+
+ if (reset_value[0]) {
+ CTRL_READ(low, high, msrs, 0);
+ CTRL_SET_ACTIVE(low);
+ CTRL_WRITE(low, high, msrs, 0);
+ }
}
static void ppro_stop(struct op_msrs const * const msrs)
{
unsigned int low,high;
- CTRL_READ(low, high, msrs, 0);
- CTRL_SET_INACTIVE(low);
- CTRL_WRITE(low, high, msrs, 0);
+
+ if (reset_value[0]) {
+ CTRL_READ(low, high, msrs, 0);
+ CTRL_SET_INACTIVE(low);
+ CTRL_WRITE(low, high, msrs, 0);
+ }
+}
+
+static void ppro_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
+
+ for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+ if (CTR_IS_RESERVED(msrs,i))
+ release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+ }
+ for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+ if (CTRL_IS_RESERVED(msrs,i))
+ release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+ }
}
@@ -140,5 +180,6 @@ struct op_x86_model_spec const op_ppro_spec = {
.setup_ctrs = &ppro_setup_ctrs,
.check_ctrs = &ppro_check_ctrs,
.start = &ppro_start,
- .stop = &ppro_stop
+ .stop = &ppro_stop,
+ .shutdown = &ppro_shutdown
};
diff --git a/arch/i386/oprofile/op_x86_model.h b/arch/i386/oprofile/op_x86_model.h
index 123b7e90a9e..abb1aa95b97 100644
--- a/arch/i386/oprofile/op_x86_model.h
+++ b/arch/i386/oprofile/op_x86_model.h
@@ -40,6 +40,7 @@ struct op_x86_model_spec {
struct op_msrs const * const msrs);
void (*start)(struct op_msrs const * const msrs);
void (*stop)(struct op_msrs const * const msrs);
+ void (*shutdown)(struct op_msrs const * const msrs);
};
extern struct op_x86_model_spec const op_ppro_spec;
diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile
index 62ad75c57e6..1594d2f55c8 100644
--- a/arch/i386/pci/Makefile
+++ b/arch/i386/pci/Makefile
@@ -11,4 +11,4 @@ pci-y += legacy.o irq.o
pci-$(CONFIG_X86_VISWS) := visws.o fixup.o
pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o
-obj-y += $(pci-y) common.o
+obj-y += $(pci-y) common.o early.o
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 0a362e3aeac..68bce194e68 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -242,6 +242,10 @@ char * __devinit pcibios_setup(char *str)
acpi_noirq_set();
return NULL;
}
+ else if (!strcmp(str, "noearly")) {
+ pci_probe |= PCI_PROBE_NOEARLY;
+ return NULL;
+ }
#ifndef CONFIG_X86_VISWS
else if (!strcmp(str, "usepirqmask")) {
pci_probe |= PCI_USE_PIRQ_MASK;
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 5d81fb51037..5acf0b4743c 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -254,7 +254,16 @@ static int __init pci_check_type2(void)
return works;
}
-void __init pci_direct_init(void)
+void __init pci_direct_init(int type)
+{
+ printk(KERN_INFO "PCI: Using configuration type %d\n", type);
+ if (type == 1)
+ raw_pci_ops = &pci_direct_conf1;
+ else
+ raw_pci_ops = &pci_direct_conf2;
+}
+
+int __init pci_direct_probe(void)
{
struct resource *region, *region2;
@@ -264,19 +273,16 @@ void __init pci_direct_init(void)
if (!region)
goto type2;
- if (pci_check_type1()) {
- printk(KERN_INFO "PCI: Using configuration type 1\n");
- raw_pci_ops = &pci_direct_conf1;
- return;
- }
+ if (pci_check_type1())
+ return 1;
release_resource(region);
type2:
if ((pci_probe & PCI_PROBE_CONF2) == 0)
- return;
+ return 0;
region = request_region(0xCF8, 4, "PCI conf2");
if (!region)
- return;
+ return 0;
region2 = request_region(0xC000, 0x1000, "PCI conf2");
if (!region2)
goto fail2;
@@ -284,10 +290,11 @@ void __init pci_direct_init(void)
if (pci_check_type2()) {
printk(KERN_INFO "PCI: Using configuration type 2\n");
raw_pci_ops = &pci_direct_conf2;
- return;
+ return 2;
}
release_resource(region2);
fail2:
release_resource(region);
+ return 0;
}
diff --git a/arch/i386/pci/early.c b/arch/i386/pci/early.c
new file mode 100644
index 00000000000..713d6c866ca
--- /dev/null
+++ b/arch/i386/pci/early.c
@@ -0,0 +1,52 @@
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/pci-direct.h>
+#include <asm/io.h>
+#include "pci.h"
+
+/* Direct PCI access. This is used for PCI accesses in early boot before
+ the PCI subsystem works. */
+
+#define PDprintk(x...)
+
+u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
+{
+ u32 v;
+ outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+ v = inl(0xcfc);
+ if (v != 0xffffffff)
+ PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
+ return v;
+}
+
+u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
+{
+ u8 v;
+ outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+ v = inb(0xcfc + (offset&3));
+ PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
+ return v;
+}
+
+u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
+{
+ u16 v;
+ outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+ v = inw(0xcfc + (offset&2));
+ PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
+ return v;
+}
+
+void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
+ u32 val)
+{
+ PDprintk("%x writing to %x: %x\n", slot, offset, val);
+ outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+ outl(val, 0xcfc);
+}
+
+int early_pci_allowed(void)
+{
+ return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
+ PCI_PROBE_CONF1;
+}
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
index 51087a9d917..d028e1b05c3 100644
--- a/arch/i386/pci/init.c
+++ b/arch/i386/pci/init.c
@@ -6,8 +6,13 @@
in the right sequence from here. */
static __init int pci_access_init(void)
{
+ int type = 0;
+
+#ifdef CONFIG_PCI_DIRECT
+ type = pci_direct_probe();
+#endif
#ifdef CONFIG_PCI_MMCONFIG
- pci_mmcfg_init();
+ pci_mmcfg_init(type);
#endif
if (raw_pci_ops)
return 0;
@@ -21,7 +26,7 @@ static __init int pci_access_init(void)
* fails.
*/
#ifdef CONFIG_PCI_DIRECT
- pci_direct_init();
+ pci_direct_init(type);
#endif
return 0;
}
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 972180f738d..05be8db58a8 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -151,6 +151,38 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};
+
+static __init void pci_mmcfg_insert_resources(void)
+{
+#define PCI_MMCFG_RESOURCE_NAME_LEN 19
+ int i;
+ struct resource *res;
+ char *names;
+ unsigned num_buses;
+
+ res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
+ pci_mmcfg_config_num, GFP_KERNEL);
+
+ if (!res) {
+ printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
+ return;
+ }
+
+ names = (void *)&res[pci_mmcfg_config_num];
+ for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
+ num_buses = pci_mmcfg_config[i].end_bus_number -
+ pci_mmcfg_config[i].start_bus_number + 1;
+ res->name = names;
+ snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+ pci_mmcfg_config[i].pci_segment_group_number);
+ res->start = pci_mmcfg_config[i].base_address;
+ res->end = res->start + (num_buses << 20) - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ insert_resource(&iomem_resource, res);
+ names += PCI_MMCFG_RESOURCE_NAME_LEN;
+ }
+}
+
/* K8 systems have some devices (typically in the builtin northbridge)
that are only accessible using type1
Normally this can be expressed in the MCFG by not listing them
@@ -187,7 +219,9 @@ static __init void unreachable_devices(void)
}
}
-void __init pci_mmcfg_init(void)
+
+
+void __init pci_mmcfg_init(int type)
{
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
return;
@@ -198,7 +232,9 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ /* Only do this check when type 1 works. If it doesn't work
+ assume we run on a Mac and always use MCFG */
+ if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address,
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
E820_RESERVED)) {
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
@@ -212,4 +248,5 @@ void __init pci_mmcfg_init(void)
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
unreachable_devices();
+ pci_mmcfg_insert_resources();
}
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index bf4e7933538..1814f74569c 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -17,6 +17,7 @@
#define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008
#define PCI_PROBE_MASK 0x000f
+#define PCI_PROBE_NOEARLY 0x0010
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200
@@ -81,7 +82,9 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus,
extern int pci_conf1_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value);
-extern void pci_direct_init(void);
+extern int pci_direct_probe(void);
+extern void pci_direct_init(int type);
extern void pci_pcbios_init(void);
-extern void pci_mmcfg_init(void);
+extern void pci_mmcfg_init(int type);
extern void pcibios_sort(void);
+
diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
index c893b897217..8a2b50a0aaa 100644
--- a/arch/i386/power/swsusp.S
+++ b/arch/i386/power/swsusp.S
@@ -32,7 +32,7 @@ ENTRY(swsusp_arch_resume)
movl $swsusp_pg_dir-__PAGE_OFFSET, %ecx
movl %ecx, %cr3
- movl pagedir_nosave, %edx
+ movl restore_pblist, %edx
.p2align 4,,7
copy_loop:
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index db274da7dba..0b7f701d5cf 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -66,15 +66,6 @@ config IA64_UNCACHED_ALLOCATOR
bool
select GENERIC_ALLOCATOR
-config DMA_IS_DMA32
- bool
- default y
-
-config DMA_IS_NORMAL
- bool
- depends on IA64_SGI_SN2
- default y
-
config AUDIT_ARCH
bool
default y
@@ -365,6 +356,9 @@ config NODES_SHIFT
MAX_NUMNODES will be 2^(This value).
If in doubt, use the default.
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
# VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
# VIRTUAL_MEM_MAP has been retained for historical reasons.
config VIRTUAL_MEM_MAP
@@ -429,6 +423,14 @@ config IA64_PALINFO
config SGI_SN
def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
+config IA64_ESI
+ bool "ESI (Extensible SAL Interface) support"
+ help
+ If you say Y here, support is built into the kernel to
+ make ESI calls. ESI calls are used to support vendor-specific
+ firmware extensions, such as the ability to inject memory-errors
+ for test-purposes. If you're unsure, say N.
+
source "drivers/sn/Kconfig"
source "drivers/firmware/Kconfig"
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 6aa3c51619c..bddbd22706e 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1942,7 +1942,7 @@ struct sysctl32 {
unsigned int __unused[4];
};
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
asmlinkage long
sys32_sysctl (struct sysctl32 __user *args)
{
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index ad8215a3c58..31497496eb4 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -32,6 +32,11 @@ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
obj-$(CONFIG_AUDIT) += audit.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
+obj-$(CONFIG_IA64_ESI) += esi.o
+ifneq ($(CONFIG_IA64_ESI),)
+obj-y += esi_stub.o # must be in kernel proper
+endif
+
# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 0176556aeec..32c3abededc 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -771,16 +771,19 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
{
#ifdef CONFIG_ACPI_NUMA
int pxm_id;
+ int nid;
pxm_id = acpi_get_pxm(handle);
-
/*
- * Assuming that the container driver would have set the proximity
- * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag
+ * We don't have cpu-only-node hotadd. But if the system equips
+ * SRAT table, pxm is already found and node is ready.
+ * So, just pxm_to_nid(pxm) is OK.
+ * This code here is for the system which doesn't have full SRAT
+ * table for possible cpus.
*/
- node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id);
-
+ nid = acpi_map_pxm_to_node(pxm_id);
node_cpuid[cpu].phys_id = physid;
+ node_cpuid[cpu].nid = nid;
#endif
return (0);
}
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index fef06571be9..12701cf32d9 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1605,8 +1605,8 @@ sys_call_table:
data8 sys_ni_syscall // 1295 reserved for ppoll
data8 sys_unshare
data8 sys_splice
- data8 sys_ni_syscall // reserved for set_robust_list
- data8 sys_ni_syscall // reserved for get_robust_list
+ data8 sys_set_robust_list
+ data8 sys_get_robust_list
data8 sys_sync_file_range // 1300
data8 sys_tee
data8 sys_vmsplice
diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c
new file mode 100644
index 00000000000..ebf4e988e78
--- /dev/null
+++ b/arch/ia64/kernel/esi.c
@@ -0,0 +1,205 @@
+/*
+ * Extensible SAL Interface (ESI) support routines.
+ *
+ * Copyright (C) 2006 Hewlett-Packard Co
+ * Alex Williamson <alex.williamson@hp.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/esi.h>
+#include <asm/sal.h>
+
+MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
+MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
+MODULE_LICENSE("GPL");
+
+#define MODULE_NAME "esi"
+
+#define ESI_TABLE_GUID \
+ EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \
+ 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
+
+enum esi_systab_entry_type {
+ ESI_DESC_ENTRY_POINT = 0
+};
+
+/*
+ * Entry type: Size:
+ * 0 48
+ */
+#define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
+
+typedef struct ia64_esi_desc_entry_point {
+ u8 type;
+ u8 reserved1[15];
+ u64 esi_proc;
+ u64 gp;
+ efi_guid_t guid;
+} ia64_esi_desc_entry_point_t;
+
+struct pdesc {
+ void *addr;
+ void *gp;
+};
+
+static struct ia64_sal_systab *esi_systab;
+
+static int __init esi_init (void)
+{
+ efi_config_table_t *config_tables;
+ struct ia64_sal_systab *systab;
+ unsigned long esi = 0;
+ char *p;
+ int i;
+
+ config_tables = __va(efi.systab->tables);
+
+ for (i = 0; i < (int) efi.systab->nr_tables; ++i) {
+ if (efi_guidcmp(config_tables[i].guid, ESI_TABLE_GUID) == 0) {
+ esi = config_tables[i].table;
+ break;
+ }
+ }
+
+ if (!esi)
+ return -ENODEV;;
+
+ systab = __va(esi);
+
+ if (strncmp(systab->signature, "ESIT", 4) != 0) {
+ printk(KERN_ERR "bad signature in ESI system table!");
+ return -ENODEV;
+ }
+
+ p = (char *) (systab + 1);
+ for (i = 0; i < systab->entry_count; i++) {
+ /*
+ * The first byte of each entry type contains the type
+ * descriptor.
+ */
+ switch (*p) {
+ case ESI_DESC_ENTRY_POINT:
+ break;
+ default:
+ printk(KERN_WARNING "Unkown table type %d found in "
+ "ESI table, ignoring rest of table\n", *p);
+ return -ENODEV;
+ }
+
+ p += ESI_DESC_SIZE(*p);
+ }
+
+ esi_systab = systab;
+ return 0;
+}
+
+
+int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+ enum esi_proc_type proc_type, u64 func,
+ u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+ u64 arg7)
+{
+ struct ia64_fpreg fr[6];
+ unsigned long flags = 0;
+ int i;
+ char *p;
+
+ if (!esi_systab)
+ return -1;
+
+ p = (char *) (esi_systab + 1);
+ for (i = 0; i < esi_systab->entry_count; i++) {
+ if (*p == ESI_DESC_ENTRY_POINT) {
+ ia64_esi_desc_entry_point_t *esi = (void *)p;
+ if (!efi_guidcmp(guid, esi->guid)) {
+ ia64_sal_handler esi_proc;
+ struct pdesc pdesc;
+
+ pdesc.addr = __va(esi->esi_proc);
+ pdesc.gp = __va(esi->gp);
+
+ esi_proc = (ia64_sal_handler) &pdesc;
+
+ ia64_save_scratch_fpregs(fr);
+ if (proc_type == ESI_PROC_SERIALIZED)
+ spin_lock_irqsave(&sal_lock, flags);
+ else if (proc_type == ESI_PROC_MP_SAFE)
+ local_irq_save(flags);
+ else
+ preempt_disable();
+ *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
+ arg4, arg5, arg6, arg7);
+ if (proc_type == ESI_PROC_SERIALIZED)
+ spin_unlock_irqrestore(&sal_lock,
+ flags);
+ else if (proc_type == ESI_PROC_MP_SAFE)
+ local_irq_restore(flags);
+ else
+ preempt_enable();
+ ia64_load_scratch_fpregs(fr);
+ return 0;
+ }
+ }
+ p += ESI_DESC_SIZE(*p);
+ }
+ return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call);
+
+int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+ u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
+ u64 arg5, u64 arg6, u64 arg7)
+{
+ struct ia64_fpreg fr[6];
+ unsigned long flags;
+ u64 esi_params[8];
+ char *p;
+ int i;
+
+ if (!esi_systab)
+ return -1;
+
+ p = (char *) (esi_systab + 1);
+ for (i = 0; i < esi_systab->entry_count; i++) {
+ if (*p == ESI_DESC_ENTRY_POINT) {
+ ia64_esi_desc_entry_point_t *esi = (void *)p;
+ if (!efi_guidcmp(guid, esi->guid)) {
+ ia64_sal_handler esi_proc;
+ struct pdesc pdesc;
+
+ pdesc.addr = (void *)esi->esi_proc;
+ pdesc.gp = (void *)esi->gp;
+
+ esi_proc = (ia64_sal_handler) &pdesc;
+
+ esi_params[0] = func;
+ esi_params[1] = arg1;
+ esi_params[2] = arg2;
+ esi_params[3] = arg3;
+ esi_params[4] = arg4;
+ esi_params[5] = arg5;
+ esi_params[6] = arg6;
+ esi_params[7] = arg7;
+ ia64_save_scratch_fpregs(fr);
+ spin_lock_irqsave(&sal_lock, flags);
+ *isrvp = esi_call_phys(esi_proc, esi_params);
+ spin_unlock_irqrestore(&sal_lock, flags);
+ ia64_load_scratch_fpregs(fr);
+ return 0;
+ }
+ }
+ p += ESI_DESC_SIZE(*p);
+ }
+ return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
+
+static void __exit esi_exit (void)
+{
+}
+
+module_init(esi_init);
+module_exit(esi_exit); /* makes module removable... */
diff --git a/arch/ia64/kernel/esi_stub.S b/arch/ia64/kernel/esi_stub.S
new file mode 100644
index 00000000000..6b3d6c1f99b
--- /dev/null
+++ b/arch/ia64/kernel/esi_stub.S
@@ -0,0 +1,96 @@
+/*
+ * ESI call stub.
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Alex Williamson <alex.williamson@hp.com>
+ *
+ * Based on EFI call stub by David Mosberger. The stub is virtually
+ * identical to the one for EFI phys-mode calls, except that ESI
+ * calls may have up to 8 arguments, so they get passed to this routine
+ * through memory.
+ *
+ * This stub allows us to make ESI calls in physical mode with interrupts
+ * turned off. ESI calls may not support calling from virtual mode.
+ *
+ * Google for "Extensible SAL specification" for a document describing the
+ * ESI standard.
+ */
+
+/*
+ * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
+ * Abstraction Layer Specification", revision 2.6e). Note that
+ * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
+ * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
+ * (the br.ia instruction fails unless psr.dfl and psr.dfh are
+ * cleared). Fortunately, SAL promises not to touch the floating
+ * point regs, so at least we don't have to save f2-f127.
+ */
+#define PSR_BITS_TO_CLEAR \
+ (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT | \
+ IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
+ IA64_PSR_DFL | IA64_PSR_DFH)
+
+#define PSR_BITS_TO_SET \
+ (IA64_PSR_BN)
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/*
+ * Inputs:
+ * in0 = address of function descriptor of ESI routine to call
+ * in1 = address of array of ESI parameters
+ *
+ * Outputs:
+ * r8 = result returned by called function
+ */
+GLOBAL_ENTRY(esi_call_phys)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+ alloc loc1=ar.pfs,2,7,8,0
+ ld8 r2=[in0],8 // load ESI function's entry point
+ mov loc0=rp
+ .body
+ ;;
+ ld8 out0=[in1],8 // ESI params loaded from array
+ ;; // passing all as inputs doesn't work
+ ld8 out1=[in1],8
+ ;;
+ ld8 out2=[in1],8
+ ;;
+ ld8 out3=[in1],8
+ ;;
+ ld8 out4=[in1],8
+ ;;
+ ld8 out5=[in1],8
+ ;;
+ ld8 out6=[in1],8
+ ;;
+ ld8 out7=[in1]
+ mov loc2=gp // save global pointer
+ mov loc4=ar.rsc // save RSE configuration
+ mov ar.rsc=0 // put RSE in enforced lazy, LE mode
+ ;;
+ ld8 gp=[in0] // load ESI function's global pointer
+ movl r16=PSR_BITS_TO_CLEAR
+ mov loc3=psr // save processor status word
+ movl r17=PSR_BITS_TO_SET
+ ;;
+ or loc3=loc3,r17
+ mov b6=r2
+ ;;
+ andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared
+ br.call.sptk.many rp=ia64_switch_mode_phys
+.ret0: mov loc5=r19 // old ar.bsp
+ mov loc6=r20 // old sp
+ br.call.sptk.many rp=b6 // call the ESI function
+.ret1: mov ar.rsc=0 // put RSE in enforced lazy, LE mode
+ mov r16=loc3 // save virtual mode psr
+ mov r19=loc5 // save virtual mode bspstore
+ mov r20=loc6 // save virtual mode sp
+ br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
+.ret2: mov ar.rsc=loc4 // restore RSE configuration
+ mov ar.pfs=loc1
+ mov rp=loc0
+ mov gp=loc2
+ br.ret.sptk.many rp
+END(esi_call_phys)
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index 3ead20fb6f4..879c1817bd1 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -105,5 +105,9 @@ EXPORT_SYMBOL(ia64_spinlock_contention);
# endif
#endif
+#if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE)
+extern void esi_call_phys (void);
+EXPORT_SYMBOL_GPL(esi_call_phys);
+#endif
extern char ia64_ivt[];
EXPORT_SYMBOL(ia64_ivt);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 781960f80b6..169ec3a7156 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -136,10 +136,8 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
static int __kprobes unsupported_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
- struct kprobe *p)
+ unsigned long addr)
{
- unsigned long addr = (unsigned long)p->addr;
-
if (bundle_encoding[template][slot] == I) {
switch (major_opcode) {
case 0x0: //I_UNIT_MISC_OPCODE:
@@ -217,7 +215,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot,
struct kprobe *p)
{
unsigned long break_inst = BREAK_INST;
- bundle_t *bundle = &p->ainsn.insn.bundle;
+ bundle_t *bundle = &p->opcode.bundle;
/*
* Copy the original kprobe_inst qualifying predicate(qp)
@@ -423,11 +421,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
unsigned long kprobe_inst=0;
unsigned int slot = addr & 0xf, template, major_opcode = 0;
- bundle_t *bundle = &p->ainsn.insn.bundle;
-
- memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
- memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+ bundle_t *bundle;
+ bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
template = bundle->quad0.template;
if(valid_kprobe_addr(template, slot, addr))
@@ -440,20 +436,19 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
/* Get kprobe_inst and major_opcode from the bundle */
get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
- if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+ if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
return -EINVAL;
- prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
- return 0;
-}
+ p->ainsn.insn = get_insn_slot();
+ if (!p->ainsn.insn)
+ return -ENOMEM;
+ memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
+ memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
-void __kprobes flush_insn_slot(struct kprobe *p)
-{
- unsigned long arm_addr;
+ prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
- arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
- flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+ return 0;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -461,9 +456,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;
- flush_insn_slot(p);
- memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
- flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+ flush_icache_range((unsigned long)p->ainsn.insn,
+ (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
+ memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
+ flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}
void __kprobes arch_disarm_kprobe(struct kprobe *p)
@@ -471,11 +467,18 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;
- /* p->opcode contains the original unaltered bundle */
- memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
- flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+ /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
+ memcpy((char *) arm_addr, (char *) p->ainsn.insn,
+ sizeof(kprobe_opcode_t));
+ flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ mutex_lock(&kprobe_mutex);
+ free_insn_slot(p->ainsn.insn);
+ mutex_unlock(&kprobe_mutex);
+}
/*
* We are resuming execution after a single step fault, so the pt_regs
* structure reflects the register state after we executed the instruction
@@ -486,12 +489,12 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
*/
static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
- unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+ unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
unsigned long template;
int slot = ((unsigned long)p->addr & 0xf);
- template = p->opcode.bundle.quad0.template;
+ template = p->ainsn.insn->bundle.quad0.template;
if (slot == 1 && bundle_encoding[template][1] == L)
slot = 2;
@@ -553,7 +556,7 @@ turn_ss_off:
static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
{
- unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+ unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
unsigned long slot = (unsigned long)p->addr & 0xf;
/* single step inline if break instruction */
@@ -768,6 +771,12 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
*/
if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
+ if (ia64_done_with_exception(regs))
+ return 1;
/*
* Let ia64_do_page_fault() fix it.
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 2fbe4536fe1..bfbd8986153 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -54,6 +54,9 @@
*
* 2005-10-07 Keith Owens <kaos@sgi.com>
* Add notify_die() hooks.
+ *
+ * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
+ * Add printing support for MCA/INIT.
*/
#include <linux/types.h>
#include <linux/init.h>
@@ -136,11 +139,175 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
static int mca_init __initdata;
+/*
+ * limited & delayed printing support for MCA/INIT handler
+ */
+
+#define mprintk(fmt...) ia64_mca_printk(fmt)
+
+#define MLOGBUF_SIZE (512+256*NR_CPUS)
+#define MLOGBUF_MSGMAX 256
+static char mlogbuf[MLOGBUF_SIZE];
+static DEFINE_SPINLOCK(mlogbuf_wlock); /* mca context only */
+static DEFINE_SPINLOCK(mlogbuf_rlock); /* normal context only */
+static unsigned long mlogbuf_start;
+static unsigned long mlogbuf_end;
+static unsigned int mlogbuf_finished = 0;
+static unsigned long mlogbuf_timestamp = 0;
+
+static int loglevel_save = -1;
+#define BREAK_LOGLEVEL(__console_loglevel) \
+ oops_in_progress = 1; \
+ if (loglevel_save < 0) \
+ loglevel_save = __console_loglevel; \
+ __console_loglevel = 15;
+
+#define RESTORE_LOGLEVEL(__console_loglevel) \
+ if (loglevel_save >= 0) { \
+ __console_loglevel = loglevel_save; \
+ loglevel_save = -1; \
+ } \
+ mlogbuf_finished = 0; \
+ oops_in_progress = 0;
+
+/*
+ * Push messages into buffer, print them later if not urgent.
+ */
+void ia64_mca_printk(const char *fmt, ...)
+{
+ va_list args;
+ int printed_len;
+ char temp_buf[MLOGBUF_MSGMAX];
+ char *p;
+
+ va_start(args, fmt);
+ printed_len = vscnprintf(temp_buf, sizeof(temp_buf), fmt, args);
+ va_end(args);
+
+ /* Copy the output into mlogbuf */
+ if (oops_in_progress) {
+ /* mlogbuf was abandoned, use printk directly instead. */
+ printk(temp_buf);
+ } else {
+ spin_lock(&mlogbuf_wlock);
+ for (p = temp_buf; *p; p++) {
+ unsigned long next = (mlogbuf_end + 1) % MLOGBUF_SIZE;
+ if (next != mlogbuf_start) {
+ mlogbuf[mlogbuf_end] = *p;
+ mlogbuf_end = next;
+ } else {
+ /* buffer full */
+ break;
+ }
+ }
+ mlogbuf[mlogbuf_end] = '\0';
+ spin_unlock(&mlogbuf_wlock);
+ }
+}
+EXPORT_SYMBOL(ia64_mca_printk);
+
+/*
+ * Print buffered messages.
+ * NOTE: call this after returning normal context. (ex. from salinfod)
+ */
+void ia64_mlogbuf_dump(void)
+{
+ char temp_buf[MLOGBUF_MSGMAX];
+ char *p;
+ unsigned long index;
+ unsigned long flags;
+ unsigned int printed_len;
+
+ /* Get output from mlogbuf */
+ while (mlogbuf_start != mlogbuf_end) {
+ temp_buf[0] = '\0';
+ p = temp_buf;
+ printed_len = 0;
+
+ spin_lock_irqsave(&mlogbuf_rlock, flags);
+
+ index = mlogbuf_start;
+ while (index != mlogbuf_end) {
+ *p = mlogbuf[index];
+ index = (index + 1) % MLOGBUF_SIZE;
+ if (!*p)
+ break;
+ p++;
+ if (++printed_len >= MLOGBUF_MSGMAX - 1)
+ break;
+ }
+ *p = '\0';
+ if (temp_buf[0])
+ printk(temp_buf);
+ mlogbuf_start = index;
+
+ mlogbuf_timestamp = 0;
+ spin_unlock_irqrestore(&mlogbuf_rlock, flags);
+ }
+}
+EXPORT_SYMBOL(ia64_mlogbuf_dump);
+
+/*
+ * Call this if system is going to down or if immediate flushing messages to
+ * console is required. (ex. recovery was failed, crash dump is going to be
+ * invoked, long-wait rendezvous etc.)
+ * NOTE: this should be called from monarch.
+ */
+static void ia64_mlogbuf_finish(int wait)
+{
+ BREAK_LOGLEVEL(console_loglevel);
+
+ spin_lock_init(&mlogbuf_rlock);
+ ia64_mlogbuf_dump();
+ printk(KERN_EMERG "mlogbuf_finish: printing switched to urgent mode, "
+ "MCA/INIT might be dodgy or fail.\n");
+
+ if (!wait)
+ return;
+
+ /* wait for console */
+ printk("Delaying for 5 seconds...\n");
+ udelay(5*1000000);
+
+ mlogbuf_finished = 1;
+}
+EXPORT_SYMBOL(ia64_mlogbuf_finish);
+
+/*
+ * Print buffered messages from INIT context.
+ */
+static void ia64_mlogbuf_dump_from_init(void)
+{
+ if (mlogbuf_finished)
+ return;
+
+ if (mlogbuf_timestamp && (mlogbuf_timestamp + 30*HZ > jiffies)) {
+ printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
+ " and the system seems to be messed up.\n");
+ ia64_mlogbuf_finish(0);
+ return;
+ }
+
+ if (!spin_trylock(&mlogbuf_rlock)) {
+ printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT. "
+ "Generated messages other than stack dump will be "
+ "buffered to mlogbuf and will be printed later.\n");
+ printk(KERN_ERR "INIT: If messages would not printed after "
+ "this INIT, wait 30sec and assert INIT again.\n");
+ if (!mlogbuf_timestamp)
+ mlogbuf_timestamp = jiffies;
+ return;
+ }
+ spin_unlock(&mlogbuf_rlock);
+ ia64_mlogbuf_dump();
+}
static void inline
ia64_mca_spin(const char *func)
{
- printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
+ if (monarch_cpu == smp_processor_id())
+ ia64_mlogbuf_finish(0);
+ mprintk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
while (1)
cpu_relax();
}
@@ -344,9 +511,6 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
/* SAL spec states this should run w/ interrupts enabled */
local_irq_enable();
- /* Get the CPE error record and log it */
- ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
-
spin_lock(&cpe_history_lock);
if (!cpe_poll_enabled && cpe_vector >= 0) {
@@ -375,7 +539,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL);
/* lock already released, get out now */
- return IRQ_HANDLED;
+ goto out;
} else {
cpe_history[index++] = now;
if (index == CPE_HISTORY_LENGTH)
@@ -383,6 +547,10 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
}
}
spin_unlock(&cpe_history_lock);
+out:
+ /* Get the CPE error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
+
return IRQ_HANDLED;
}
@@ -988,18 +1156,22 @@ ia64_wait_for_slaves(int monarch, const char *type)
}
if (!missing)
goto all_in;
- printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
+ /*
+ * Maybe slave(s) dead. Print buffered messages immediately.
+ */
+ ia64_mlogbuf_finish(0);
+ mprintk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
for_each_online_cpu(c) {
if (c == monarch)
continue;
if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
- printk(" %d", c);
+ mprintk(" %d", c);
}
- printk("\n");
+ mprintk("\n");
return;
all_in:
- printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
+ mprintk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
return;
}
@@ -1027,10 +1199,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
struct ia64_mca_notify_die nd =
{ .sos = sos, .monarch_cpu = &monarch_cpu };
- oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
- console_loglevel = 15; /* make sure printks make it to console */
- printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
- sos->proc_state_param, cpu, sos->monarch);
+ mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
+ "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
monarch_cpu = cpu;
@@ -1066,6 +1236,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
rh->severity = sal_log_severity_corrected;
ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
sos->os_status = IA64_MCA_CORRECTED;
+ } else {
+ /* Dump buffered message to console */
+ ia64_mlogbuf_finish(1);
}
if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
== NOTIFY_STOP)
@@ -1106,9 +1279,6 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
/* SAL spec states this should run w/ interrupts enabled */
local_irq_enable();
- /* Get the CMC error record and log it */
- ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
-
spin_lock(&cmc_history_lock);
if (!cmc_polling_enabled) {
int i, count = 1; /* we know 1 happened now */
@@ -1141,7 +1311,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
/* lock already released, get out now */
- return IRQ_HANDLED;
+ goto out;
} else {
cmc_history[index++] = now;
if (index == CMC_HISTORY_LENGTH)
@@ -1149,6 +1319,10 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
}
}
spin_unlock(&cmc_history_lock);
+out:
+ /* Get the CMC error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
+
return IRQ_HANDLED;
}
@@ -1305,6 +1479,15 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
struct task_struct *g, *t;
if (val != DIE_INIT_MONARCH_PROCESS)
return NOTIFY_DONE;
+
+ /*
+ * FIXME: mlogbuf will brim over with INIT stack dumps.
+ * To enable show_stack from INIT, we use oops_in_progress which should
+ * be used in real oops. This would cause something wrong after INIT.
+ */
+ BREAK_LOGLEVEL(console_loglevel);
+ ia64_mlogbuf_dump_from_init();
+
printk(KERN_ERR "Processes interrupted by INIT -");
for_each_online_cpu(c) {
struct ia64_sal_os_state *s;
@@ -1326,6 +1509,8 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
} while_each_thread (g, t);
read_unlock(&tasklist_lock);
}
+ /* FIXME: This will not restore zapped printk locks. */
+ RESTORE_LOGLEVEL(console_loglevel);
return NOTIFY_DONE;
}
@@ -1357,12 +1542,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
struct ia64_mca_notify_die nd =
{ .sos = sos, .monarch_cpu = &monarch_cpu };
- oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
- console_loglevel = 15; /* make sure printks make it to console */
-
(void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
- printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+ mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
sos->proc_state_param, cpu, sos->monarch);
salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
@@ -1375,7 +1557,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
* fix their proms and get their customers updated.
*/
if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
- printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
+ mprintk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
__FUNCTION__, cpu);
atomic_dec(&slaves);
sos->monarch = 1;
@@ -1387,7 +1569,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
* fix their proms and get their customers updated.
*/
if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
- printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
+ mprintk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
__FUNCTION__, cpu);
atomic_dec(&monarchs);
sos->monarch = 0;
@@ -1408,7 +1590,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- printk("Slave on cpu %d returning to normal service.\n", cpu);
+ mprintk("Slave on cpu %d returning to normal service.\n", cpu);
set_curr_task(cpu, previous_current);
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
atomic_dec(&slaves);
@@ -1426,7 +1608,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
* same serial line, the user will need some time to switch out of the BMC before
* the dump begins.
*/
- printk("Delaying for 5 seconds...\n");
+ mprintk("Delaying for 5 seconds...\n");
udelay(5*1000000);
ia64_wait_for_slaves(cpu, "INIT");
/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
@@ -1439,7 +1621,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
+ mprintk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
atomic_dec(&monarchs);
set_curr_task(cpu, previous_current);
monarch_cpu = -1;
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 96047491d1b..c6b607c00de 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -1025,18 +1025,13 @@ ia64_old_stack:
ia64_set_kernel_registers:
add temp3=MCA_SP_OFFSET, r3
- add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
mov b0=r2 // save return address
GET_IA64_MCA_DATA(temp1)
;;
- add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp
add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack
add r13=temp1, r3 // set current to start of MCA/INIT stack
add r20=temp1, r3 // physical start of MCA/INIT stack
;;
- ld8 r1=[temp4] // OS GP from SAL OS state
- ;;
- DATA_PA_TO_VA(r1,temp1)
DATA_PA_TO_VA(r12,temp2)
DATA_PA_TO_VA(r13,temp3)
;;
@@ -1067,6 +1062,10 @@ ia64_set_kernel_registers:
mov cr.itir=r18
mov cr.ifa=r13
mov r20=IA64_TR_CURRENT_STACK
+
+ movl r17=FPSR_DEFAULT
+ ;;
+ mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
;;
itr.d dtr[r20]=r21
;;
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 8db6e0cedad..a45009d2bc9 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -79,14 +79,30 @@ static int
fatal_mca(const char *fmt, ...)
{
va_list args;
+ char buf[256];
va_start(args, fmt);
- vprintk(fmt, args);
+ vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+ ia64_mca_printk(KERN_ALERT "MCA: %s\n", buf);
return MCA_NOT_RECOVERED;
}
+static int
+mca_recovered(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ ia64_mca_printk(KERN_INFO "MCA: %s\n", buf);
+
+ return MCA_RECOVERED;
+}
+
/**
* mca_page_isolate - isolate a poisoned page in order not to use it later
* @paddr: poisoned memory location
@@ -140,6 +156,7 @@ mca_page_isolate(unsigned long paddr)
void
mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
{
+ ia64_mlogbuf_dump();
printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
"iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
raw_smp_processor_id(), current->pid, current->uid,
@@ -440,7 +457,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is target address valid? */
if (!pbci->tv)
- return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
+ return fatal_mca("target address not valid");
/*
* cpu read or memory-mapped io read
@@ -458,7 +475,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is minstate valid? */
if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
- return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
+ return fatal_mca("minstate not valid");
psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
@@ -492,13 +509,14 @@ recover_from_read_error(slidx_table_t *slidx,
psr2->bn = 1;
psr2->i = 0;
- return MCA_RECOVERED;
+ return mca_recovered("user memory corruption. "
+ "kill affected process - recovered.");
}
}
- return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
- " iip 0x%lx\n", pmsa->pmsa_iip);
+ return fatal_mca("kernel context not recovered, iip 0x%lx\n",
+ pmsa->pmsa_iip);
}
/**
@@ -584,13 +602,13 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* The machine check is corrected.
*/
if (psp->cm == 1)
- return MCA_RECOVERED;
+ return mca_recovered("machine check is already corrected.");
/*
* The error was not contained. Software must be reset.
*/
if (psp->us || psp->ci == 0)
- return fatal_mca(KERN_ALERT "MCA: error not contained\n");
+ return fatal_mca("error not contained");
/*
* The cache check and bus check bits have four possible states
@@ -601,22 +619,22 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* 1 1 Memory error, attempt recovery
*/
if (psp->bc == 0 || pbci == NULL)
- return fatal_mca(KERN_ALERT "MCA: No bus check\n");
+ return fatal_mca("No bus check");
/*
* Sorry, we cannot handle so many.
*/
if (peidx_bus_check_num(peidx) > 1)
- return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
+ return fatal_mca("Too many bus checks");
/*
* Well, here is only one bus error.
*/
if (pbci->ib)
- return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+ return fatal_mca("Internal Bus error");
if (pbci->cc)
- return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
+ return fatal_mca("Cache-cache error");
if (pbci->eb && pbci->bsi > 0)
- return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
+ return fatal_mca("External bus check fatal status");
/*
* This is a local MCA and estimated as recoverble external bus error.
@@ -628,7 +646,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
/*
* On account of strange SAL error record, we cannot recover.
*/
- return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
+ return fatal_mca("Strange SAL record");
}
/**
@@ -657,10 +675,10 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Now, OS can recover when there is one processor error section */
if (n_proc_err > 1)
- return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+ return fatal_mca("Too Many Errors");
else if (n_proc_err == 0)
- /* Weird SAL record ... We need not to recover */
- return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
+ /* Weird SAL record ... We can't do anything */
+ return fatal_mca("Weird SAL record");
/* Make index of processor error section */
mca_make_peidx((sal_log_processor_info_t*)
@@ -671,7 +689,7 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Check whether MCA is global or not */
if (is_mca_global(&peidx, &pbci, sos))
- return fatal_mca(KERN_ALERT "MCA: global MCA\n");
+ return fatal_mca("global MCA");
/* Try to recover a processor error */
return recover_from_processor_error(platform_err, &slidx, &peidx,
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 31a2e52bb16..c85e943ba5f 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -118,3 +118,7 @@ struct mca_table_entry {
extern const struct mca_table_entry *search_mca_tables (unsigned long addr);
extern int mca_recover_range(unsigned long);
+extern void ia64_mca_printk(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+extern void ia64_mlogbuf_dump(void);
+
diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
index 1cc360c83e7..20340631179 100644
--- a/arch/ia64/kernel/numa.c
+++ b/arch/ia64/kernel/numa.c
@@ -29,6 +29,36 @@ EXPORT_SYMBOL(cpu_to_node_map);
cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+void __cpuinit map_cpu_to_node(int cpu, int nid)
+{
+ int oldnid;
+ if (nid < 0) { /* just initialize by zero */
+ cpu_to_node_map[cpu] = 0;
+ return;
+ }
+ /* sanity check first */
+ oldnid = cpu_to_node_map[cpu];
+ if (cpu_isset(cpu, node_to_cpu_mask[oldnid])) {
+ return; /* nothing to do */
+ }
+ /* we don't have cpu-driven node hot add yet...
+ In usual case, node is created from SRAT at boot time. */
+ if (!node_online(nid))
+ nid = first_online_node;
+ cpu_to_node_map[cpu] = nid;
+ cpu_set(cpu, node_to_cpu_mask[nid]);
+ return;
+}
+
+void __cpuinit unmap_cpu_from_node(int cpu, int nid)
+{
+ WARN_ON(!cpu_isset(cpu, node_to_cpu_mask[nid]));
+ WARN_ON(cpu_to_node_map[cpu] != nid);
+ cpu_to_node_map[cpu] = 0;
+ cpu_clear(cpu, node_to_cpu_mask[nid]);
+}
+
+
/**
* build_cpu_to_node_map - setup cpu to node and node to cpumask arrays
*
@@ -49,8 +79,6 @@ void __init build_cpu_to_node_map(void)
node = node_cpuid[i].nid;
break;
}
- cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
- if (node >= 0)
- cpu_set(cpu, node_to_cpu_mask[node]);
+ map_cpu_to_node(cpu, node);
}
}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 84a7e52f56f..281004ff7b0 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -34,6 +34,7 @@
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/vfs.h>
+#include <linux/smp.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/bitops.h>
@@ -62,6 +63,9 @@
#define PFM_INVALID_ACTIVATION (~0UL)
+#define PFM_NUM_PMC_REGS 64 /* PMC save area for ctxsw */
+#define PFM_NUM_PMD_REGS 64 /* PMD save area for ctxsw */
+
/*
* depth of message queue
*/
@@ -296,14 +300,17 @@ typedef struct pfm_context {
unsigned long ctx_reload_pmcs[4]; /* bitmask of force reload PMC on ctxsw in */
unsigned long ctx_used_monitors[4]; /* bitmask of monitor PMC being used */
- unsigned long ctx_pmcs[IA64_NUM_PMC_REGS]; /* saved copies of PMC values */
+ unsigned long ctx_pmcs[PFM_NUM_PMC_REGS]; /* saved copies of PMC values */
unsigned int ctx_used_ibrs[1]; /* bitmask of used IBR (speedup ctxsw in) */
unsigned int ctx_used_dbrs[1]; /* bitmask of used DBR (speedup ctxsw in) */
unsigned long ctx_dbrs[IA64_NUM_DBG_REGS]; /* DBR values (cache) when not loaded */
unsigned long ctx_ibrs[IA64_NUM_DBG_REGS]; /* IBR values (cache) when not loaded */
- pfm_counter_t ctx_pmds[IA64_NUM_PMD_REGS]; /* software state for PMDS */
+ pfm_counter_t ctx_pmds[PFM_NUM_PMD_REGS]; /* software state for PMDS */
+
+ unsigned long th_pmcs[PFM_NUM_PMC_REGS]; /* PMC thread save state */
+ unsigned long th_pmds[PFM_NUM_PMD_REGS]; /* PMD thread save state */
u64 ctx_saved_psr_up; /* only contains psr.up value */
@@ -867,7 +874,6 @@ static void
pfm_mask_monitoring(struct task_struct *task)
{
pfm_context_t *ctx = PFM_GET_CTX(task);
- struct thread_struct *th = &task->thread;
unsigned long mask, val, ovfl_mask;
int i;
@@ -888,7 +894,7 @@ pfm_mask_monitoring(struct task_struct *task)
* So in both cases, the live register contains the owner's
* state. We can ONLY touch the PMU registers and NOT the PSR.
*
- * As a consequence to this call, the thread->pmds[] array
+ * As a consequence to this call, the ctx->th_pmds[] array
* contains stale information which must be ignored
* when context is reloaded AND monitoring is active (see
* pfm_restart).
@@ -923,9 +929,9 @@ pfm_mask_monitoring(struct task_struct *task)
mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
if ((mask & 0x1) == 0UL) continue;
- ia64_set_pmc(i, th->pmcs[i] & ~0xfUL);
- th->pmcs[i] &= ~0xfUL;
- DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, th->pmcs[i]));
+ ia64_set_pmc(i, ctx->th_pmcs[i] & ~0xfUL);
+ ctx->th_pmcs[i] &= ~0xfUL;
+ DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
}
/*
* make all of this visible
@@ -942,7 +948,6 @@ static void
pfm_restore_monitoring(struct task_struct *task)
{
pfm_context_t *ctx = PFM_GET_CTX(task);
- struct thread_struct *th = &task->thread;
unsigned long mask, ovfl_mask;
unsigned long psr, val;
int i, is_system;
@@ -1008,9 +1013,9 @@ pfm_restore_monitoring(struct task_struct *task)
mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
if ((mask & 0x1) == 0UL) continue;
- th->pmcs[i] = ctx->ctx_pmcs[i];
- ia64_set_pmc(i, th->pmcs[i]);
- DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, th->pmcs[i]));
+ ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+ ia64_set_pmc(i, ctx->th_pmcs[i]);
+ DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, ctx->th_pmcs[i]));
}
ia64_srlz_d();
@@ -1069,7 +1074,6 @@ pfm_restore_pmds(unsigned long *pmds, unsigned long mask)
static inline void
pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
{
- struct thread_struct *thread = &task->thread;
unsigned long ovfl_val = pmu_conf->ovfl_val;
unsigned long mask = ctx->ctx_all_pmds[0];
unsigned long val;
@@ -1091,11 +1095,11 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
ctx->ctx_pmds[i].val = val & ~ovfl_val;
val &= ovfl_val;
}
- thread->pmds[i] = val;
+ ctx->th_pmds[i] = val;
DPRINT(("pmd[%d]=0x%lx soft_val=0x%lx\n",
i,
- thread->pmds[i],
+ ctx->th_pmds[i],
ctx->ctx_pmds[i].val));
}
}
@@ -1106,7 +1110,6 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
static inline void
pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
{
- struct thread_struct *thread = &task->thread;
unsigned long mask = ctx->ctx_all_pmcs[0];
int i;
@@ -1114,8 +1117,8 @@ pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
for (i=0; mask; i++, mask>>=1) {
/* masking 0 with ovfl_val yields 0 */
- thread->pmcs[i] = ctx->ctx_pmcs[i];
- DPRINT(("pmc[%d]=0x%lx\n", i, thread->pmcs[i]));
+ ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+ DPRINT(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
}
}
@@ -2859,7 +2862,6 @@ pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int is_long_reset)
static int
pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
{
- struct thread_struct *thread = NULL;
struct task_struct *task;
pfarg_reg_t *req = (pfarg_reg_t *)arg;
unsigned long value, pmc_pm;
@@ -2880,7 +2882,6 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
if (state == PFM_CTX_ZOMBIE) return -EINVAL;
if (is_loaded) {
- thread = &task->thread;
/*
* In system wide and when the context is loaded, access can only happen
* when the caller is running on the CPU being monitored by the session.
@@ -3035,7 +3036,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
*
* The value in ctx_pmcs[] can only be changed in pfm_write_pmcs().
*
- * The value in thread->pmcs[] may be modified on overflow, i.e., when
+ * The value in th_pmcs[] may be modified on overflow, i.e., when
* monitoring needs to be stopped.
*/
if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum);
@@ -3049,7 +3050,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* write thread state
*/
- if (is_system == 0) thread->pmcs[cnum] = value;
+ if (is_system == 0) ctx->th_pmcs[cnum] = value;
/*
* write hardware register if we can
@@ -3101,7 +3102,6 @@ error:
static int
pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
{
- struct thread_struct *thread = NULL;
struct task_struct *task;
pfarg_reg_t *req = (pfarg_reg_t *)arg;
unsigned long value, hw_value, ovfl_mask;
@@ -3125,7 +3125,6 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* the owner of the local PMU.
*/
if (likely(is_loaded)) {
- thread = &task->thread;
/*
* In system wide and when the context is loaded, access can only happen
* when the caller is running on the CPU being monitored by the session.
@@ -3233,7 +3232,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* write thread state
*/
- if (is_system == 0) thread->pmds[cnum] = hw_value;
+ if (is_system == 0) ctx->th_pmds[cnum] = hw_value;
/*
* write hardware register if we can
@@ -3299,7 +3298,6 @@ abort_mission:
static int
pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
{
- struct thread_struct *thread = NULL;
struct task_struct *task;
unsigned long val = 0UL, lval, ovfl_mask, sval;
pfarg_reg_t *req = (pfarg_reg_t *)arg;
@@ -3323,7 +3321,6 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
if (state == PFM_CTX_ZOMBIE) return -EINVAL;
if (likely(is_loaded)) {
- thread = &task->thread;
/*
* In system wide and when the context is loaded, access can only happen
* when the caller is running on the CPU being monitored by the session.
@@ -3385,7 +3382,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* if context is zombie, then task does not exist anymore.
* In this case, we use the full value saved in the context (pfm_flush_regs()).
*/
- val = is_loaded ? thread->pmds[cnum] : 0UL;
+ val = is_loaded ? ctx->th_pmds[cnum] : 0UL;
}
rd_func = pmu_conf->pmd_desc[cnum].read_check;
@@ -4354,8 +4351,8 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
pfm_copy_pmds(task, ctx);
pfm_copy_pmcs(task, ctx);
- pmcs_source = thread->pmcs;
- pmds_source = thread->pmds;
+ pmcs_source = ctx->th_pmcs;
+ pmds_source = ctx->th_pmds;
/*
* always the case for system-wide
@@ -5864,14 +5861,12 @@ void
pfm_save_regs(struct task_struct *task)
{
pfm_context_t *ctx;
- struct thread_struct *t;
unsigned long flags;
u64 psr;
ctx = PFM_GET_CTX(task);
if (ctx == NULL) return;
- t = &task->thread;
/*
* we always come here with interrupts ALREADY disabled by
@@ -5929,19 +5924,19 @@ pfm_save_regs(struct task_struct *task)
* guarantee we will be schedule at that same
* CPU again.
*/
- pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+ pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
/*
* save pmc0 ia64_srlz_d() done in pfm_save_pmds()
* we will need it on the restore path to check
* for pending overflow.
*/
- t->pmcs[0] = ia64_get_pmc(0);
+ ctx->th_pmcs[0] = ia64_get_pmc(0);
/*
* unfreeze PMU if had pending overflows
*/
- if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+ if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
/*
* finally, allow context access.
@@ -5986,7 +5981,6 @@ static void
pfm_lazy_save_regs (struct task_struct *task)
{
pfm_context_t *ctx;
- struct thread_struct *t;
unsigned long flags;
{ u64 psr = pfm_get_psr();
@@ -5994,7 +5988,6 @@ pfm_lazy_save_regs (struct task_struct *task)
}
ctx = PFM_GET_CTX(task);
- t = &task->thread;
/*
* we need to mask PMU overflow here to
@@ -6019,19 +6012,19 @@ pfm_lazy_save_regs (struct task_struct *task)
/*
* save all the pmds we use
*/
- pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+ pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
/*
* save pmc0 ia64_srlz_d() done in pfm_save_pmds()
* it is needed to check for pended overflow
* on the restore path
*/
- t->pmcs[0] = ia64_get_pmc(0);
+ ctx->th_pmcs[0] = ia64_get_pmc(0);
/*
* unfreeze PMU if had pending overflows
*/
- if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+ if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
/*
* now get can unmask PMU interrupts, they will
@@ -6050,7 +6043,6 @@ void
pfm_load_regs (struct task_struct *task)
{
pfm_context_t *ctx;
- struct thread_struct *t;
unsigned long pmc_mask = 0UL, pmd_mask = 0UL;
unsigned long flags;
u64 psr, psr_up;
@@ -6061,11 +6053,10 @@ pfm_load_regs (struct task_struct *task)
BUG_ON(GET_PMU_OWNER());
- t = &task->thread;
/*
* possible on unload
*/
- if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) return;
+ if (unlikely((task->thread.flags & IA64_THREAD_PM_VALID) == 0)) return;
/*
* we always come here with interrupts ALREADY disabled by
@@ -6147,21 +6138,21 @@ pfm_load_regs (struct task_struct *task)
*
* XXX: optimize here
*/
- if (pmd_mask) pfm_restore_pmds(t->pmds, pmd_mask);
- if (pmc_mask) pfm_restore_pmcs(t->pmcs, pmc_mask);
+ if (pmd_mask) pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+ if (pmc_mask) pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
/*
* check for pending overflow at the time the state
* was saved.
*/
- if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+ if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
/*
* reload pmc0 with the overflow information
* On McKinley PMU, this will trigger a PMU interrupt
*/
- ia64_set_pmc(0, t->pmcs[0]);
+ ia64_set_pmc(0, ctx->th_pmcs[0]);
ia64_srlz_d();
- t->pmcs[0] = 0UL;
+ ctx->th_pmcs[0] = 0UL;
/*
* will replay the PMU interrupt
@@ -6214,7 +6205,6 @@ pfm_load_regs (struct task_struct *task)
void
pfm_load_regs (struct task_struct *task)
{
- struct thread_struct *t;
pfm_context_t *ctx;
struct task_struct *owner;
unsigned long pmd_mask, pmc_mask;
@@ -6223,7 +6213,6 @@ pfm_load_regs (struct task_struct *task)
owner = GET_PMU_OWNER();
ctx = PFM_GET_CTX(task);
- t = &task->thread;
psr = pfm_get_psr();
BUG_ON(psr & (IA64_PSR_UP|IA64_PSR_PP));
@@ -6286,22 +6275,22 @@ pfm_load_regs (struct task_struct *task)
*/
pmc_mask = ctx->ctx_all_pmcs[0];
- pfm_restore_pmds(t->pmds, pmd_mask);
- pfm_restore_pmcs(t->pmcs, pmc_mask);
+ pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+ pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
/*
* check for pending overflow at the time the state
* was saved.
*/
- if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+ if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
/*
* reload pmc0 with the overflow information
* On McKinley PMU, this will trigger a PMU interrupt
*/
- ia64_set_pmc(0, t->pmcs[0]);
+ ia64_set_pmc(0, ctx->th_pmcs[0]);
ia64_srlz_d();
- t->pmcs[0] = 0UL;
+ ctx->th_pmcs[0] = 0UL;
/*
* will replay the PMU interrupt
@@ -6376,11 +6365,11 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
*/
pfm_unfreeze_pmu();
} else {
- pmc0 = task->thread.pmcs[0];
+ pmc0 = ctx->th_pmcs[0];
/*
* clear whatever overflow status bits there were
*/
- task->thread.pmcs[0] = 0;
+ ctx->th_pmcs[0] = 0;
}
ovfl_val = pmu_conf->ovfl_val;
/*
@@ -6401,7 +6390,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
/*
* can access PMU always true in system wide mode
*/
- val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : task->thread.pmds[i];
+ val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : ctx->th_pmds[i];
if (PMD_IS_COUNTING(i)) {
DPRINT(("[%d] pmd[%d] ctx_pmd=0x%lx hw_pmd=0x%lx\n",
@@ -6433,7 +6422,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
DPRINT(("[%d] ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, i, val, pmd_val));
- if (is_self) task->thread.pmds[i] = pmd_val;
+ if (is_self) ctx->th_pmds[i] = pmd_val;
ctx->ctx_pmds[i].val = val;
}
@@ -6677,7 +6666,7 @@ pfm_init(void)
ffz(pmu_conf->ovfl_val));
/* sanity check */
- if (pmu_conf->num_pmds >= IA64_NUM_PMD_REGS || pmu_conf->num_pmcs >= IA64_NUM_PMC_REGS) {
+ if (pmu_conf->num_pmds >= PFM_NUM_PMD_REGS || pmu_conf->num_pmcs >= PFM_NUM_PMC_REGS) {
printk(KERN_ERR "perfmon: not enough pmc/pmd, perfmon disabled\n");
pmu_conf = NULL;
return -1;
@@ -6752,7 +6741,6 @@ void
dump_pmu_state(const char *from)
{
struct task_struct *task;
- struct thread_struct *t;
struct pt_regs *regs;
pfm_context_t *ctx;
unsigned long psr, dcr, info, flags;
@@ -6797,16 +6785,14 @@ dump_pmu_state(const char *from)
ia64_psr(regs)->up = 0;
ia64_psr(regs)->pp = 0;
- t = &current->thread;
-
for (i=1; PMC_IS_LAST(i) == 0; i++) {
if (PMC_IS_IMPL(i) == 0) continue;
- printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, t->pmcs[i]);
+ printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, ctx->th_pmcs[i]);
}
for (i=1; PMD_IS_LAST(i) == 0; i++) {
if (PMD_IS_IMPL(i) == 0) continue;
- printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, t->pmds[i]);
+ printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, ctx->th_pmds[i]);
}
if (ctx) {
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 9065f0f01ba..e63b8ca5344 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -266,6 +266,7 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
/* Check for outstanding MCA/INIT records every minute (arbitrary) */
#define SALINFO_TIMER_DELAY (60*HZ)
static struct timer_list salinfo_timer;
+extern void ia64_mlogbuf_dump(void);
static void
salinfo_timeout_check(struct salinfo_data *data)
@@ -283,6 +284,7 @@ salinfo_timeout_check(struct salinfo_data *data)
static void
salinfo_timeout (unsigned long arg)
{
+ ia64_mlogbuf_dump();
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
@@ -332,6 +334,8 @@ retry:
if (cpu == -1)
goto retry;
+ ia64_mlogbuf_dump();
+
/* for next read, start checking at next CPU */
data->cpu_check = cpu;
if (++data->cpu_check == NR_CPUS)
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 7ad0d9cc6db..84f93c0f2c6 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -509,7 +509,7 @@ show_cpuinfo (struct seq_file *m, void *v)
{ 1UL << 1, "spontaneous deferral"},
{ 1UL << 2, "16-byte atomic ops" }
};
- char family[32], features[128], *cp, sep;
+ char features[128], *cp, sep;
struct cpuinfo_ia64 *c = v;
unsigned long mask;
unsigned long proc_freq;
@@ -517,12 +517,6 @@ show_cpuinfo (struct seq_file *m, void *v)
mask = c->features;
- switch (c->family) {
- case 0x07: memcpy(family, "Itanium", 8); break;
- case 0x1f: memcpy(family, "Itanium 2", 10); break;
- default: sprintf(family, "%u", c->family); break;
- }
-
/* build the feature string: */
memcpy(features, " standard", 10);
cp = features;
@@ -553,8 +547,9 @@ show_cpuinfo (struct seq_file *m, void *v)
"processor : %d\n"
"vendor : %s\n"
"arch : IA-64\n"
- "family : %s\n"
+ "family : %u\n"
"model : %u\n"
+ "model name : %s\n"
"revision : %u\n"
"archrev : %u\n"
"features :%s\n" /* don't change this---it _is_ right! */
@@ -563,7 +558,8 @@ show_cpuinfo (struct seq_file *m, void *v)
"cpu MHz : %lu.%06lu\n"
"itc MHz : %lu.%06lu\n"
"BogoMIPS : %lu.%02lu\n",
- cpunum, c->vendor, family, c->model, c->revision, c->archrev,
+ cpunum, c->vendor, c->family, c->model,
+ c->model_name, c->revision, c->archrev,
features, c->ppn, c->number,
proc_freq / 1000, proc_freq % 1000,
c->itc_freq / 1000000, c->itc_freq % 1000000,
@@ -611,6 +607,31 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo
};
+static char brandname[128];
+
+static char * __cpuinit
+get_model_name(__u8 family, __u8 model)
+{
+ char brand[128];
+
+ if (ia64_pal_get_brand_info(brand)) {
+ if (family == 0x7)
+ memcpy(brand, "Merced", 7);
+ else if (family == 0x1f) switch (model) {
+ case 0: memcpy(brand, "McKinley", 9); break;
+ case 1: memcpy(brand, "Madison", 8); break;
+ case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
+ } else
+ memcpy(brand, "Unknown", 8);
+ }
+ if (brandname[0] == '\0')
+ return strcpy(brandname, brand);
+ else if (strcmp(brandname, brand) == 0)
+ return brandname;
+ else
+ return kstrdup(brand, GFP_KERNEL);
+}
+
static void __cpuinit
identify_cpu (struct cpuinfo_ia64 *c)
{
@@ -640,7 +661,6 @@ identify_cpu (struct cpuinfo_ia64 *c)
pal_status_t status;
unsigned long impl_va_msb = 50, phys_addr_size = 44; /* Itanium defaults */
int i;
-
for (i = 0; i < 5; ++i)
cpuid.bits[i] = ia64_get_cpuid(i);
@@ -663,6 +683,7 @@ identify_cpu (struct cpuinfo_ia64 *c)
c->family = cpuid.field.family;
c->archrev = cpuid.field.archrev;
c->features = cpuid.field.features;
+ c->model_name = get_model_name(c->family, c->model);
status = ia64_pal_vm_summary(&vm1, &vm2);
if (status == PAL_STATUS_SUCCESS) {
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 6203ed4ec8c..f7d7f566814 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -879,3 +879,27 @@ identify_siblings(struct cpuinfo_ia64 *c)
c->core_id = info.log1_cid;
c->thread_id = info.log1_tid;
}
+
+/*
+ * returns non zero, if multi-threading is enabled
+ * on at least one physical package. Due to hotplug cpu
+ * and (maxcpus=), all threads may not necessarily be enabled
+ * even though the processor supports multi-threading.
+ */
+int is_multithreading_enabled(void)
+{
+ int i, j;
+
+ for_each_present_cpu(i) {
+ for_each_present_cpu(j) {
+ if (j == i)
+ continue;
+ if ((cpu_data(j)->socket_id == cpu_data(i)->socket_id)) {
+ if (cpu_data(j)->core_id == cpu_data(i)->core_id)
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(is_multithreading_enabled);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index f648c610b10..5629b45e89c 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -36,6 +36,7 @@ int arch_register_cpu(int num)
*/
if (!can_cpei_retarget() && is_cpu_cpei_target(num))
sysfs_cpus[num].cpu.no_control = 1;
+ map_cpu_to_node(num, node_cpuid[num].nid);
#endif
return register_cpu(&sysfs_cpus[num].cpu, num);
@@ -45,7 +46,8 @@ int arch_register_cpu(int num)
void arch_unregister_cpu(int num)
{
- return unregister_cpu(&sysfs_cpus[num].cpu);
+ unregister_cpu(&sysfs_cpus[num].cpu);
+ unmap_cpu_from_node(num, cpu_to_node(num));
}
EXPORT_SYMBOL(arch_register_cpu);
EXPORT_SYMBOL(arch_unregister_cpu);
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 4c73a676366..c58e933694d 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -98,7 +98,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
/* attempt to allocate a granule's worth of cached memory pages */
- page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
+ page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
IA64_GRANULE_SHIFT-PAGE_SHIFT);
if (!page) {
mutex_unlock(&uc_pool->add_chunk_mutex);
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 5b0d5f64a9b..b3b2e389d6b 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -184,7 +184,9 @@ SECTIONS
*(.data.gate)
__stop_gate_section = .;
}
- . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose kernel data */
+ . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose
+ * kernel data
+ */
.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET)
{ *(.data.read_mostly) }
@@ -202,7 +204,9 @@ SECTIONS
*(.data.percpu)
__per_cpu_end = .;
}
- . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits into percpu page size */
+ . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits
+ * into percpu page size
+ */
data : { } :data
.data : AT(ADDR(.data) - LOAD_OFFSET)
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index e004143ba86..daf977ff292 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -26,7 +26,6 @@
#include <asm/mca.h>
#ifdef CONFIG_VIRTUAL_MEM_MAP
-static unsigned long num_dma_physpages;
static unsigned long max_gap;
#endif
@@ -41,10 +40,11 @@ show_mem (void)
int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
- 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));
i = max_mapnr;
for (i = 0; i < max_mapnr; i++) {
if (!pfn_valid(i)) {
@@ -63,12 +63,12 @@ show_mem (void)
else if (page_count(mem_map + i))
shared += page_count(mem_map + i) - 1;
}
- printk("%d pages of RAM\n", total);
- printk("%d reserved pages\n", reserved);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
- printk("%ld pages in page table cache\n",
- pgtable_quicklist_total_size());
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ 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);
+ printk(KERN_INFO "%ld pages in page table cache\n",
+ pgtable_quicklist_total_size());
}
/* physical address where the bootmem map is located */
@@ -218,18 +218,6 @@ count_pages (u64 start, u64 end, void *arg)
return 0;
}
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-static int
-count_dma_pages (u64 start, u64 end, void *arg)
-{
- unsigned long *count = arg;
-
- if (start < MAX_DMA_ADDRESS)
- *count += (min(end, MAX_DMA_ADDRESS) - start) >> PAGE_SHIFT;
- return 0;
-}
-#endif
-
/*
* Set up the page tables.
*/
@@ -238,45 +226,22 @@ void __init
paging_init (void)
{
unsigned long max_dma;
- unsigned long zones_size[MAX_NR_ZONES];
-#ifdef CONFIG_VIRTUAL_MEM_MAP
- unsigned long zholes_size[MAX_NR_ZONES];
-#endif
-
- /* initialize mem_map[] */
-
- memset(zones_size, 0, sizeof(zones_size));
+ unsigned long nid = 0;
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
num_physpages = 0;
efi_memmap_walk(count_pages, &num_physpages);
max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ max_zone_pfns[ZONE_DMA] = max_dma;
+ max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_VIRTUAL_MEM_MAP
- memset(zholes_size, 0, sizeof(zholes_size));
-
- num_dma_physpages = 0;
- efi_memmap_walk(count_dma_pages, &num_dma_physpages);
-
- if (max_low_pfn < max_dma) {
- zones_size[ZONE_DMA] = max_low_pfn;
- zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages;
- } else {
- zones_size[ZONE_DMA] = max_dma;
- zholes_size[ZONE_DMA] = max_dma - num_dma_physpages;
- if (num_physpages > num_dma_physpages) {
- zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
- zholes_size[ZONE_NORMAL] =
- ((max_low_pfn - max_dma) -
- (num_physpages - num_dma_physpages));
- }
- }
-
+ efi_memmap_walk(register_active_ranges, &nid);
efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
if (max_gap < LARGE_GAP) {
vmem_map = (struct page *) 0;
- free_area_init_node(0, NODE_DATA(0), zones_size, 0,
- zholes_size);
+ free_area_init_nodes(max_zone_pfns);
} else {
unsigned long map_size;
@@ -288,20 +253,19 @@ paging_init (void)
vmem_map = (struct page *) vmalloc_end;
efi_memmap_walk(create_mem_map_page_table, NULL);
- NODE_DATA(0)->node_mem_map = vmem_map;
- free_area_init_node(0, NODE_DATA(0), zones_size,
- 0, zholes_size);
+ /*
+ * alloc_node_mem_map makes an adjustment for mem_map
+ * which isn't compatible with vmem_map.
+ */
+ NODE_DATA(0)->node_mem_map = vmem_map +
+ find_min_pfn_with_active_regions();
+ free_area_init_nodes(max_zone_pfns);
printk("Virtual mem_map starts at 0x%p\n", mem_map);
}
#else /* !CONFIG_VIRTUAL_MEM_MAP */
- if (max_low_pfn < max_dma)
- zones_size[ZONE_DMA] = max_low_pfn;
- else {
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
- }
- free_area_init(zones_size);
+ add_active_range(0, 0, max_low_pfn);
+ free_area_init_nodes(max_zone_pfns);
#endif /* !CONFIG_VIRTUAL_MEM_MAP */
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
}
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index d260bffa01a..d497b6b0f5b 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -547,15 +547,16 @@ void show_mem(void)
unsigned long total_present = 0;
pg_data_t *pgdat;
- 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));
+ printk(KERN_INFO "Node memory in pages:\n");
for_each_online_pgdat(pgdat) {
unsigned long present;
unsigned long flags;
int shared = 0, cached = 0, reserved = 0;
- printk("Node ID: %d\n", pgdat->node_id);
pgdat_resize_lock(pgdat, &flags);
present = pgdat->node_present_pages;
for(i = 0; i < pgdat->node_spanned_pages; i++) {
@@ -579,18 +580,17 @@ void show_mem(void)
total_reserved += reserved;
total_cached += cached;
total_shared += shared;
- printk("\t%ld pages of RAM\n", present);
- printk("\t%d reserved pages\n", reserved);
- printk("\t%d pages shared\n", shared);
- printk("\t%d pages swap cached\n", cached);
+ printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, "
+ "shrd: %10d, swpd: %10d\n", pgdat->node_id,
+ present, reserved, shared, cached);
}
- printk("%ld pages of RAM\n", total_present);
- printk("%d reserved pages\n", total_reserved);
- printk("%d pages shared\n", total_shared);
- printk("%d pages swap cached\n", total_cached);
- printk("Total of %ld pages in page table cache\n",
- pgtable_quicklist_total_size());
- printk("%d free buffer pages\n", nr_free_buffer_pages());
+ printk(KERN_INFO "%ld pages of RAM\n", total_present);
+ printk(KERN_INFO "%d reserved pages\n", total_reserved);
+ printk(KERN_INFO "%d pages shared\n", total_shared);
+ printk(KERN_INFO "%d pages swap cached\n", total_cached);
+ printk(KERN_INFO "Total of %ld pages in page table cache\n",
+ pgtable_quicklist_total_size());
+ printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
}
/**
@@ -654,6 +654,7 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
{
unsigned long end = start + len;
+ add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
mem_data[node].num_physpages += len >> PAGE_SHIFT;
if (start <= __pa(MAX_DMA_ADDRESS))
mem_data[node].num_dma_physpages +=
@@ -678,10 +679,10 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
void __init paging_init(void)
{
unsigned long max_dma;
- unsigned long zones_size[MAX_NR_ZONES];
- unsigned long zholes_size[MAX_NR_ZONES];
unsigned long pfn_offset = 0;
+ unsigned long max_pfn = 0;
int node;
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
@@ -698,47 +699,20 @@ void __init paging_init(void)
#endif
for_each_online_node(node) {
- memset(zones_size, 0, sizeof(zones_size));
- memset(zholes_size, 0, sizeof(zholes_size));
-
num_physpages += mem_data[node].num_physpages;
-
- if (mem_data[node].min_pfn >= max_dma) {
- /* All of this node's memory is above ZONE_DMA */
- zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
- mem_data[node].min_pfn;
- zholes_size[ZONE_NORMAL] = mem_data[node].max_pfn -
- mem_data[node].min_pfn -
- mem_data[node].num_physpages;
- } else if (mem_data[node].max_pfn < max_dma) {
- /* All of this node's memory is in ZONE_DMA */
- zones_size[ZONE_DMA] = mem_data[node].max_pfn -
- mem_data[node].min_pfn;
- zholes_size[ZONE_DMA] = mem_data[node].max_pfn -
- mem_data[node].min_pfn -
- mem_data[node].num_dma_physpages;
- } else {
- /* This node has memory in both zones */
- zones_size[ZONE_DMA] = max_dma -
- mem_data[node].min_pfn;
- zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
- mem_data[node].num_dma_physpages;
- zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
- max_dma;
- zholes_size[ZONE_NORMAL] = zones_size[ZONE_NORMAL] -
- (mem_data[node].num_physpages -
- mem_data[node].num_dma_physpages);
- }
-
pfn_offset = mem_data[node].min_pfn;
#ifdef CONFIG_VIRTUAL_MEM_MAP
NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
#endif
- free_area_init_node(node, NODE_DATA(node), zones_size,
- pfn_offset, zholes_size);
+ if (mem_data[node].max_pfn > max_pfn)
+ max_pfn = mem_data[node].max_pfn;
}
+ max_zone_pfns[ZONE_DMA] = max_dma;
+ max_zone_pfns[ZONE_NORMAL] = max_pfn;
+ free_area_init_nodes(max_zone_pfns);
+
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
}
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 30617ccb4f7..ff87a5cba39 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -593,6 +593,18 @@ find_largest_hole (u64 start, u64 end, void *arg)
last_end = end;
return 0;
}
+
+int __init
+register_active_ranges(u64 start, u64 end, void *nid)
+{
+ BUG_ON(nid == NULL);
+ BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES);
+
+ add_active_range(*(unsigned long *)nid,
+ __pa(start) >> PAGE_SHIFT,
+ __pa(end) >> PAGE_SHIFT);
+ return 0;
+}
#endif /* CONFIG_VIRTUAL_MEM_MAP */
static int __init
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 60b45e79f08..15c7c670da3 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -562,7 +562,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
void
pcibios_disable_device (struct pci_dev *dev)
{
- acpi_pci_irq_disable(dev);
+ if (dev->is_enabled)
+ acpi_pci_irq_disable(dev);
}
void
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 27dee458406..7f73ad4408a 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -277,8 +277,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
}
/* temporary buffer used during unaligned transfers */
- bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES,
- GFP_KERNEL | GFP_DMA);
+ bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES, GFP_KERNEL);
if (bteBlock_unaligned == NULL) {
return BTEFAIL_NOTAVAIL;
}
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 9a8a29339d2..b632b9c1e3b 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -32,9 +32,10 @@
#include <linux/cpumask.h>
#include <linux/smp_lock.h>
#include <linux/nodemask.h>
+#include <linux/smp.h>
+
#include <asm/processor.h>
#include <asm/topology.h>
-#include <asm/smp.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include <asm/sal.h>
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index b71348fec1f..bbd97c85bc5 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -100,7 +100,7 @@ void free_initrd_mem(unsigned long, unsigned long);
#ifndef CONFIG_DISCONTIGMEM
unsigned long __init zone_sizes_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
unsigned long max_dma;
unsigned long low;
unsigned long start_pfn;
diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
index e4c233eef19..06e538d1be3 100644
--- a/arch/m68knommu/mm/init.c
+++ b/arch/m68knommu/mm/init.c
@@ -136,7 +136,7 @@ void paging_init(void)
#endif
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 330f6abc770..30750c54bdf 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -126,7 +126,7 @@ config BASLER_EXCITE
select IRQ_CPU
select IRQ_CPU_RM7K
select IRQ_CPU_RM9K
- select SERIAL_RM9000
+ select MIPS_RM9122
select SYS_HAS_CPU_RM9000
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
@@ -203,26 +203,6 @@ config MIPS_EV64120
<http://www.marvell.com/>. Say Y here if you wish to build a
kernel for this platform.
-config MIPS_EV96100
- bool "Galileo EV96100 Evaluation board (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select MIPS_GT96100
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_R5000
- select SYS_HAS_CPU_RM7000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
- select SYS_SUPPORTS_BIG_ENDIAN
- help
- This is an evaluation board based on the Galileo GT-96100 LAN/WAN
- communications controllers containing a MIPS R5000 compatible core
- running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
- here if you wish to build a kernel for this platform.
-
config MIPS_IVR
bool "Globespan IVR board"
select DMA_NONCOHERENT
@@ -974,6 +954,12 @@ config MIPS_TX3927
bool
select HAS_TXX9_SERIAL
+config MIPS_RM9122
+ bool
+ select SERIAL_RM9000
+ select GPI_RM9000
+ select WDT_RM9000
+
config PCI_MARVELL
bool
@@ -1024,6 +1010,15 @@ config EMMA2RH
depends on MARKEINS
default y
+config SERIAL_RM9000
+ bool
+
+config GPI_RM9000
+ bool
+
+config WDT_RM9000
+ bool
+
#
# Unfortunately not all GT64120 systems run the chip at the same clock.
# As the user for the clock rate and try to minimize the available options.
@@ -1054,10 +1049,6 @@ config AU1X00_USB_DEVICE
depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
default n
-config MIPS_GT96100
- bool
- select MIPS_GT64120
-
config IT8172_CIR
bool
depends on MIPS_ITE8172 || MIPS_IVR
@@ -1527,6 +1518,7 @@ config MIPS_MT_SMTC
select CPU_MIPSR2_SRS
select MIPS_MT
select SMP
+ select SYS_SUPPORTS_SMP
help
This is a kernel model which is known a SMTC or lately has been
marketesed into SMVP.
@@ -1538,6 +1530,7 @@ config MIPS_MT_SMP
select CPU_MIPSR2_SRS
select MIPS_MT
select SMP
+ select SYS_SUPPORTS_SMP
help
This is a kernel model which is also known a VSMP or lately
has been marketesed into SMVP.
@@ -1649,9 +1642,7 @@ config GENERIC_IRQ_PROBE
default y
config IRQ_PER_CPU
- depends on SMP
bool
- default y
#
# - Highmem only makes sense for the 32-bit kernel.
@@ -1719,6 +1710,7 @@ source "mm/Kconfig"
config SMP
bool "Multi-Processing support"
depends on SYS_SUPPORTS_SMP
+ select IRQ_PER_CPU
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
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index d333ce4ba26..e521826b423 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -280,13 +280,6 @@ cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120
load-$(CONFIG_MIPS_EV64120) += 0xffffffff80100000
#
-# Galileo EV96100 Board
-#
-core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/ev96100/
-cflags-$(CONFIG_MIPS_EV96100) += -Iinclude/asm-mips/mach-ev96100
-load-$(CONFIG_MIPS_EV96100) += 0xffffffff80100000
-
-#
# Wind River PPMC Board (4KC + GT64120)
#
core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/
@@ -330,6 +323,7 @@ load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
# MIPS SEAD board
#
core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/
+cflags-$(CONFIG_MIPS_SEAD) += -Iinclude/asm-mips/mach-mips
load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000
#
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index 98244d51c15..c4fae8ff467 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -230,7 +230,7 @@ EXPORT_SYMBOL(au1xxx_ddma_add_device);
*/
u32
au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
- void (*callback)(int, void *, struct pt_regs *), void *callparam)
+ void (*callback)(int, void *), void *callparam)
{
unsigned long flags;
u32 used, chan, rv;
@@ -248,8 +248,10 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
au1xxx_dbdma_init();
dbdma_initialized = 1;
- if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
- if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
+ if ((stp = find_dbdev_id(srcid)) == NULL)
+ return 0;
+ if ((dtp = find_dbdev_id(destid)) == NULL)
+ return 0;
used = 0;
rv = 0;
@@ -869,7 +871,7 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
au_sync();
if (ctp->chan_callback)
- (ctp->chan_callback)(irq, ctp->chan_callparam, regs);
+ (ctp->chan_callback)(irq, ctp->chan_callparam);
ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
return IRQ_RETVAL(1);
diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile
index 4c7d763f211..51d62bd5d90 100644
--- a/arch/mips/au1000/db1x00/Makefile
+++ b/arch/mips/au1000/db1x00/Makefile
@@ -6,4 +6,3 @@
# Makefile for the Alchemy Semiconductor Db1x00 board.
lib-y := init.o board_setup.o irqmap.o
-obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
deleted file mode 100644
index 0942dcf6951..00000000000
--- a/arch/mips/au1000/db1x00/mirage_ts.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/mips/au1000/db1x00/mirage_ts.c
- *
- * BRIEF MODULE DESCRIPTION
- * Glue between Mirage board-specific touchscreen pieces
- * and generic Wolfson Codec touchscreen support.
- *
- * Based on pb1100_ts.c used in Hydrogen II.
- *
- * Copyright (c) 2003 Embedded Edge, LLC
- * dan@embeddededge.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/wait.h>
-
-#include <asm/segment.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/au1000.h>
-
-/*
- * Imported interface to Wolfson Codec driver.
- */
-extern void *wm97xx_ts_get_handle(int which);
-extern int wm97xx_ts_ready(void* ts_handle);
-extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
-extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
-extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
-extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
-extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
-
-int wm97xx_comodule_present = 1;
-
-
-#define TS_NAME "mirage_ts"
-
-#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
-#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
-
-
-#define PEN_DOWN_IRQ AU1000_GPIO_7
-
-static struct task_struct *ts_task = 0;
-static DECLARE_COMPLETION(ts_complete);
-static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
-
-#ifdef CONFIG_WM97XX_FIVEWIRETS
-static int release_pressure = 1;
-#else
-static int release_pressure = 50;
-#endif
-
-typedef struct {
- long x;
- long y;
-} DOWN_EVENT;
-
-#define SAMPLE_RATE 50 /* samples per second */
-#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
-#define PEN_UP_TIMEOUT 10 /* in seconds */
-#define PEN_UP_SETTLE 5 /* samples per second */
-
-static struct {
- int xscale;
- int xtrans;
- int yscale;
- int ytrans;
-} mirage_ts_cal =
-{
-#if 0
- .xscale = 84,
- .xtrans = -157,
- .yscale = 66,
- .ytrans = -150,
-#else
- .xscale = 84,
- .xtrans = -150,
- .yscale = 66,
- .ytrans = -146,
-#endif
-};
-
-
-static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
-{
-//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
- wake_up(&pendown_wait);
-}
-
-static int ts_thread(void *id)
-{
- static int pen_was_down = 0;
- static DOWN_EVENT pen_xy;
- long x, y, z;
- void *ts; /* handle */
- struct task_struct *tsk = current;
- int timeout = HZ / SAMPLE_RATE;
-
- ts_task = tsk;
-
- daemonize();
- tsk->tty = NULL;
- tsk->policy = SCHED_FIFO;
- tsk->rt_priority = 1;
- strcpy(tsk->comm, "touchscreen");
-
- /* only want to receive SIGKILL */
- spin_lock_irq(&tsk->sigmask_lock);
- siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
- recalc_sigpending(tsk);
- spin_unlock_irq(&tsk->sigmask_lock);
-
- /* get handle for codec */
- ts = wm97xx_ts_get_handle(0);
-
- /* proceed only after everybody is ready */
- wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
-
- /* board-specific calibration */
- wm97xx_ts_set_cal(ts,
- mirage_ts_cal.xscale,
- mirage_ts_cal.xtrans,
- mirage_ts_cal.yscale,
- mirage_ts_cal.ytrans);
-
- /* route Wolfson pendown interrupts to our GPIO */
- au_sync();
- wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
- au_sync();
- wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
- au_sync();
- wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
- au_sync();
-
- for (;;) {
- interruptible_sleep_on_timeout(&pendown_wait, timeout);
- disable_irq(PEN_DOWN_IRQ);
- if (signal_pending(tsk)) {
- break;
- }
-
- /* read codec */
- if (!wm97xx_ts_read_data(ts, &x, &y, &z))
- z = 0; /* treat no-data and pen-up the same */
-
- if (signal_pending(tsk)) {
- break;
- }
-
- if (z >= release_pressure) {
- y = ~y; /* top to bottom */
- if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
- /* bounce ? */
- x = pen_xy.x;
- y = pen_xy.y;
- --pen_was_down;
- } else if (pen_was_down <= 1) {
- pen_xy.x = x;
- pen_xy.y = y;
- if (pen_was_down)
- wm97xx_ts_send_data(ts, x, y, z);
- pen_was_down = PEN_DEBOUNCE;
- }
- //wm97xx_ts_send_data(ts, x, y, z);
- timeout = HZ / SAMPLE_RATE;
- } else {
- if (pen_was_down) {
- if (--pen_was_down)
- z = release_pressure;
- else //THXXX
- wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
- }
- /* The pendown signal takes some time to settle after
- * reading the pen pressure so wait a little
- * before enabling the pen.
- */
- if (! pen_was_down) {
-// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
- timeout = HZ * PEN_UP_TIMEOUT;
- }
- }
- enable_irq(PEN_DOWN_IRQ);
- }
- enable_irq(PEN_DOWN_IRQ);
- ts_task = NULL;
- complete(&ts_complete);
- return 0;
-}
-
-static int __init ts_mirage_init(void)
-{
- int ret;
-
- /* pen down signal is connected to GPIO 7 */
-
- ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
- if (ret) {
- err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
- return ret;
- }
-
- lock_kernel();
- ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
- if (ret < 0) {
- unlock_kernel();
- return ret;
- }
- unlock_kernel();
-
- info("Mirage touchscreen IRQ initialized.");
-
- return 0;
-}
-
-static void __exit ts_mirage_exit(void)
-{
- if (ts_task) {
- send_sig(SIGKILL, ts_task, 1);
- wait_for_completion(&ts_complete);
- }
-
- free_irq(PEN_DOWN_IRQ, NULL);
-}
-
-module_init(ts_mirage_init);
-module_exit(ts_mirage_exit);
-
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
index bbb4ea43da8..cc1ce77eab4 100644
--- a/arch/mips/basler/excite/excite_device.c
+++ b/arch/mips/basler/excite/excite_device.c
@@ -68,7 +68,7 @@ enum {
static struct resource
- excite_ctr_resource = {
+ excite_ctr_resource __attribute__((unused)) = {
.name = "GPI counters",
.start = 0,
.end = 5,
@@ -77,7 +77,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_gpislice_resource = {
+ excite_gpislice_resource __attribute__((unused)) = {
.name = "GPI slices",
.start = 0,
.end = 1,
@@ -86,7 +86,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_mdio_channel_resource = {
+ excite_mdio_channel_resource __attribute__((unused)) = {
.name = "MDIO channels",
.start = 0,
.end = 1,
@@ -95,7 +95,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_fifomem_resource = {
+ excite_fifomem_resource __attribute__((unused)) = {
.name = "FIFO memory",
.start = 0,
.end = 767,
@@ -104,7 +104,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_scram_resource = {
+ excite_scram_resource __attribute__((unused)) = {
.name = "Scratch RAM",
.start = EXCITE_PHYS_SCRAM,
.end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
@@ -113,7 +113,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_fpga_resource = {
+ excite_fpga_resource __attribute__((unused)) = {
.name = "System FPGA",
.start = EXCITE_PHYS_FPGA,
.end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
@@ -122,7 +122,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_nand_resource = {
+ excite_nand_resource __attribute__((unused)) = {
.name = "NAND flash control",
.start = EXCITE_PHYS_NAND,
.end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
@@ -131,7 +131,7 @@ static struct resource
.sibling = NULL,
.child = NULL
},
- excite_titan_resource = {
+ excite_titan_resource __attribute__((unused)) = {
.name = "TITAN registers",
.start = EXCITE_PHYS_TITAN,
.end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h
deleted file mode 100644
index 38fcda703a0..00000000000
--- a/arch/mips/basler/excite/excite_fpga.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef EXCITE_FPGA_H_INCLUDED
-#define EXCITE_FPGA_H_INCLUDED
-
-
-/**
- * Adress alignment of the individual FPGA bytes.
- * The address arrangement of the individual bytes of the FPGA is two
- * byte aligned at the embedded MK2 platform.
- */
-#ifdef EXCITE_CCI_FPGA_MK2
-typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
-#else
-typedef unsigned char excite_cci_fpga_align_t;
-#endif
-
-
-/**
- * Size of Dual Ported RAM.
- */
-#define EXCITE_DPR_SIZE 263
-
-
-/**
- * Size of Reserved Status Fields in Dual Ported RAM.
- */
-#define EXCITE_DPR_STATUS_SIZE 7
-
-
-
-/**
- * FPGA.
- * Hardware register layout of the FPGA interface. The FPGA must accessed
- * byte wise solely.
- * @see EXCITE_CCI_DPR_MK2
- */
-typedef struct excite_fpga {
-
- /**
- * Dual Ported RAM.
- */
- excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
-
- /**
- * Status.
- */
- excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
-
-#ifdef EXCITE_CCI_FPGA_MK2
- /**
- * RM9000 Interrupt.
- * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
- */
- excite_cci_fpga_align_t rm9k_int;
-#else
- /**
- * MK2 Interrupt.
- * Write access initiates interrupt at the ARM processor of the MK2.
- */
- excite_cci_fpga_align_t mk2_int;
-
- excite_cci_fpga_align_t gap[0x1000-0x10f];
-
- /**
- * IRQ Source/Acknowledge.
- */
- excite_cci_fpga_align_t rm9k_irq_src;
-
- /**
- * IRQ Mask.
- * Set bits enable the related interrupt.
- */
- excite_cci_fpga_align_t rm9k_irq_mask;
-#endif
-
-
-} excite_fpga;
-
-
-
-#endif /* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 54274065e9a..d3705284de3 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -1193,7 +1192,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 887fd959482..e12a475dcbf 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index a01344f3a4c..bfade9abb76 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index c95682445a2..4baf2ff1128 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
CONFIG_MIPS_COBALT=y
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -828,7 +827,7 @@ CONFIG_FUSE_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index c2f33d3af62..93cca1585bc 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1000=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 8c44d16ae9a..ffd99252a83 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1100=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index c13768e75ac..63eac5e89b9 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1200=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 8aea73fae7f..25a095f7dc4 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1500=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 90ccb735963..dda469c842b 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1550=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index b598cf08f15..fcd3dd19bc7 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 597150b1407..8683e0df12e 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
CONFIG_MACH_DECSTATION=y
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index fa2996bb4b7..4ace61c9577 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul 6 10:04:02 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:15:03 2006
#
CONFIG_MIPS=y
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -227,7 +226,6 @@ CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
#
# PCI Hotplug Support
@@ -254,7 +252,6 @@ CONFIG_TRAD_SIGNALS=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
# CONFIG_SYS_HYPERVISOR is not set
#
@@ -284,6 +281,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -643,6 +641,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -650,7 +649,7 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M"
#
# Security options
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 375b2ac24a4..5847c916c13 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index b0afc118bd5..bc4c4f125c4 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
CONFIG_MIPS_EV64120=y
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 045ebd08989..eb87cbbfd03 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -26,7 +26,6 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index ef16d1fb507..cc9b24eda9e 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 4bf1ee7f5f0..50092ba8aa7 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -900,7 +899,7 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index f83dc09c3ca..dec2ba6ba03 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index a91d72a9ca8..37f9dd7187b 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
CONFIG_MIPS_ITE8172=y
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index cebc67212d0..18874a4c24f 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
CONFIG_MIPS_IVR=y
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 5d9eb11aba3..9f1e3048d62 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -731,7 +730,7 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index be45a9044d0..fded3f73815 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 64dc9f45a19..320b8cdd6e5 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -905,7 +904,7 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 2690baf15a8..0ba1ef5048f 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -1230,7 +1229,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index c298979c18a..adbeeadddb8 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 938b38ab523..79fd544fcb2 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul 6 10:04:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:16:46 2006
#
CONFIG_MIPS=y
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -71,7 +70,6 @@ CONFIG_MACH_VR41XX=y
CONFIG_VICTOR_MPC30X=y
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_PCI_VR41XX=y
-CONFIG_VRC4173=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
@@ -168,6 +166,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
@@ -841,7 +840,7 @@ CONFIG_USB_PEGASUS=m
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
@@ -982,7 +981,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1007,6 +1005,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1014,7 +1013,7 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
+CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73"
#
# Security options
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index ec5758f2267..4d87da2b99f 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index 0d33d87de1a..a7ac2b0a827 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -774,7 +773,7 @@ CONFIG_FUSE_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 4b999102715..853e7bba512 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -723,7 +722,7 @@ CONFIG_FUSE_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index 827b344f601..8524efa23a4 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -777,7 +776,7 @@ CONFIG_FUSE_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 9ed60fef69e..1a16e92900c 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1100=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 6774254b1be..9ea8edea6f2 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1500=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 1afe5bf6e76..c4a158976f8 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1550=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index ac616c82d34..1cbf270c301 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index a8eb51bae3f..bec30b15b9b 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 6a63a113b7e..f5f799e9370 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -687,7 +686,7 @@ CONFIG_FUSE_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 6779f449bd2..2f5650227ba 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index b7826d3a2b7..4fee90b2b10 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -1442,7 +1441,7 @@ CONFIG_NTFS_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 625c1c619b6..9041f095f96 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 4401b602118..02abb2f1bfa 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index 2ba4e25e8c3..ca3d0c4ba15 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index fc8a407c1ad..4e2009ace27 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index effcb63b81a..535a813d01a 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 4891d02ef8c..3a3ef20b21c 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul 6 10:04:21 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:13:04 2006
#
CONFIG_MIPS=y
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -166,6 +165,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
@@ -379,6 +379,7 @@ CONFIG_CONNECTOR=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -855,7 +856,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -880,6 +880,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -887,7 +888,7 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
#
# Security options
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 3e4b16b3982..e6b1dea5584 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 3a68d8a25b6..06a072b77b1 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index fff6fcc9621..cc9b24eda9e 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.18-rc1
-# Thu Jul 6 09:49:33 2006
+# Thu Jul 6 10:04:10 2006
#
CONFIG_MIPS=y
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
# CONFIG_MIPS_IVR is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
deleted file mode 100644
index cd868ec78cb..00000000000
--- a/arch/mips/galileo-boards/ev96100/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Copyright 2000 MontaVista Software Inc.
-# Author: MontaVista Software, Inc.
-# ppopov@mvista.com or source@mvista.com
-#
-# Makefile for the Galileo EV96100 board.
-#
-
-obj-y += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c
deleted file mode 100644
index a01fe9b36f2..00000000000
--- a/arch/mips/galileo-boards/ev96100/init.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/generic.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/gt64120.h>
-
-
-/* Environment variable */
-
-typedef struct {
- char *name;
- char *val;
-} t_env_var;
-
-int prom_argc;
-char **prom_argv, **prom_envp;
-
-int init_debug = 0;
-
-char * __init prom_getcmdline(void)
-{
- return &(arcs_cmdline[0]);
-}
-
-unsigned long __init prom_free_prom_memory(void)
-{
- return 0;
-}
-
-void __init prom_init_cmdline(void)
-{
- char *cp;
- int actr;
-
- actr = 1; /* Always ignore argv[0] */
-
- cp = &(arcs_cmdline[0]);
- while(actr < prom_argc) {
- strcpy(cp, prom_argv[actr]);
- cp += strlen(prom_argv[actr]);
- *cp++ = ' ';
- actr++;
- }
- if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
- --cp;
- *cp = '\0';
-}
-
-char *prom_getenv(char *envname)
-{
- /*
- * Return a pointer to the given environment variable.
- */
-
- t_env_var *env = (t_env_var *) prom_envp;
- int i;
-
- i = strlen(envname);
-
- while (env->name) {
- if (strncmp(envname, env->name, i) == 0) {
- return (env->val);
- }
- env++;
- }
- return (NULL);
-}
-
-static inline unsigned char str2hexnum(unsigned char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0; /* foo */
-}
-
-static inline void str2eaddr(unsigned char *ea, unsigned char *str)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- unsigned char num;
-
- if ((*str == '.') || (*str == ':'))
- str++;
- num = str2hexnum(*str++) << 4;
- num |= (str2hexnum(*str++));
- ea[i] = num;
- }
-}
-
-int get_ethernet_addr(char *ethernet_addr)
-{
- char *ethaddr_str;
-
- ethaddr_str = prom_getenv("ethaddr");
- if (!ethaddr_str) {
- printk("ethaddr not set in boot prom\n");
- return -1;
- }
- str2eaddr(ethernet_addr, ethaddr_str);
-
- if (init_debug > 1) {
- int i;
- printk("get_ethernet_addr: ");
- for (i = 0; i < 5; i++)
- printk("%02x:",
- (unsigned char) *(ethernet_addr + i));
- printk("%02x\n", *(ethernet_addr + i));
- }
-
- return 0;
-}
-
-const char *get_system_type(void)
-{
- return "Galileo EV96100";
-}
-
-void __init prom_init(void)
-{
- volatile unsigned char *uart;
- char ppbuf[8];
-
- prom_argc = fw_arg0;
- prom_argv = (char **) fw_arg1;
- prom_envp = (char **) fw_arg2;
-
- mips_machgroup = MACH_GROUP_GALILEO;
- mips_machtype = MACH_EV96100;
-
- prom_init_cmdline();
-
- /* 32 MB upgradable */
- add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
deleted file mode 100644
index ee5d6720f23..00000000000
--- a/arch/mips/galileo-boards/ev96100/irq.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_int.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/irq_cpu.h>
-
-static inline unsigned int ffz8(unsigned int word)
-{
- unsigned long k;
-
- k = 7;
- if (word & 0x0fUL) { k -= 4; word <<= 4; }
- if (word & 0x30UL) { k -= 2; word <<= 2; }
- if (word & 0x40UL) { k -= 1; }
-
- return k;
-}
-
-extern void mips_timer_interrupt(struct pt_regs *regs);
-
-asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
-{
- do_IRQ(ffz8(pending >> 8), regs);
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
- unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
- if (pending & CAUSEF_IP7)
- mips_timer_interrupt(regs);
- else if (pending)
- ev96100_cpu_irq(pending, regs);
- else
- spurious_interrupt(regs);
-}
-
-void __init arch_init_irq(void)
-{
- mips_cpu_irq_init(0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c
deleted file mode 100644
index 49dc6d137b9..00000000000
--- a/arch/mips/galileo-boards/ev96100/puts.c
+++ /dev/null
@@ -1,138 +0,0 @@
-
-/*
- * Debug routines which directly access the uart.
- */
-
-#include <linux/types.h>
-#include <asm/gt64120.h>
-
-
-//#define SERIAL_BASE EV96100_UART0_REGS_BASE
-#define SERIAL_BASE 0xBD000020
-#define NS16550_BASE SERIAL_BASE
-
-#define SERA_CMD 0x0D
-#define SERA_DATA 0x08
-//#define SERB_CMD 0x05
-#define SERB_CMD 20
-#define SERB_DATA 0x00
-#define TX_BUSY 0x20
-
-#define TIMEOUT 0xffff
-#undef SLOW_DOWN
-
-static const char digits[16] = "0123456789abcdef";
-static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
-
-
-#ifdef SLOW_DOWN
-static inline void slow_down()
-{
- int k;
- for (k = 0; k < 10000; k++);
-}
-#else
-#define slow_down()
-#endif
-
-void putch(const unsigned char c)
-{
- unsigned char ch;
- int i = 0;
-
- do {
- ch = com1[SERB_CMD];
- slow_down();
- i++;
- if (i > TIMEOUT) {
- break;
- }
- } while (0 == (ch & TX_BUSY));
- com1[SERB_DATA] = c;
-}
-
-void putchar(const unsigned char c)
-{
- unsigned char ch;
- int i = 0;
-
- do {
- ch = com1[SERB_CMD];
- slow_down();
- i++;
- if (i > TIMEOUT) {
- break;
- }
- } while (0 == (ch & TX_BUSY));
- com1[SERB_DATA] = c;
-}
-
-void puts(unsigned char *cp)
-{
- unsigned char ch;
- int i = 0;
-
- while (*cp) {
- do {
- ch = com1[SERB_CMD];
- slow_down();
- i++;
- if (i > TIMEOUT) {
- break;
- }
- } while (0 == (ch & TX_BUSY));
- com1[SERB_DATA] = *cp++;
- }
- putch('\r');
- putch('\n');
-}
-
-void fputs(unsigned char *cp)
-{
- unsigned char ch;
- int i = 0;
-
- while (*cp) {
-
- do {
- ch = com1[SERB_CMD];
- slow_down();
- i++;
- if (i > TIMEOUT) {
- break;
- }
- } while (0 == (ch & TX_BUSY));
- com1[SERB_DATA] = *cp++;
- }
-}
-
-
-void put64(uint64_t ul)
-{
- int cnt;
- unsigned ch;
-
- cnt = 16; /* 16 nibbles in a 64 bit long */
- putch('0');
- putch('x');
- do {
- cnt--;
- ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
- putch(digits[ch]);
- } while (cnt > 0);
-}
-
-void put32(unsigned u)
-{
- int cnt;
- unsigned ch;
-
- cnt = 8; /* 8 nibbles in a 32 bit long */
- putch('0');
- putch('x');
- do {
- cnt--;
- ch = (unsigned char) (u >> cnt * 4) & 0x0F;
- putch(digits[ch]);
- } while (cnt > 0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/reset.c b/arch/mips/galileo-boards/ev96100/reset.c
deleted file mode 100644
index 5ef9b7f896e..00000000000
--- a/arch/mips/galileo-boards/ev96100/reset.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo EV96100 reset routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/reset.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
-static void mips_machine_restart(char *command)
-{
- set_c0_status(ST0_BEV | ST0_ERL);
- change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
- flush_cache_all();
- write_c0_wired(0);
- __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
- while (1);
-}
-
-static void mips_machine_halt(void)
-{
- printk(KERN_NOTICE "You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void mips_reboot_setup(void)
-{
- _machine_restart = mips_machine_restart;
- _machine_halt = mips_machine_halt;
-}
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
deleted file mode 100644
index 639ad5562c6..00000000000
--- a/arch/mips/galileo-boards/ev96100/setup.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo EV96100 setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_setup.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/pci.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100int.h>
-
-
-extern char *__init prom_getcmdline(void);
-
-extern void mips_reboot_setup(void);
-
-unsigned char mac_0_1[12];
-
-void __init plat_mem_setup(void)
-{
- unsigned int config = read_c0_config();
- unsigned int status = read_c0_status();
- unsigned int info = read_c0_info();
- u32 tmp;
-
- char *argptr;
-
- clear_c0_status(ST0_FR);
-
- if (config & 0x8)
- printk("Secondary cache is enabled\n");
- else
- printk("Secondary cache is disabled\n");
-
- if (status & (1 << 27))
- printk("User-mode cache ops enabled\n");
- else
- printk("User-mode cache ops disabled\n");
-
- printk("CP0 info reg: %x\n", (unsigned) info);
- if (info & (1 << 28))
- printk("burst mode Scache RAMS\n");
- else
- printk("pipelined Scache RAMS\n");
-
- if (info & 0x1)
- printk("Atomic Enable is set\n");
-
- argptr = prom_getcmdline();
-#ifdef CONFIG_SERIAL_CONSOLE
- if (strstr(argptr, "console=") == NULL) {
- argptr = prom_getcmdline();
- strcat(argptr, " console=ttyS0,115200");
- }
-#endif
-
- mips_reboot_setup();
-
- set_io_port_base(KSEG1);
- ioport_resource.start = GT_PCI_IO_BASE;
- ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-#endif
-
-
- /*
- * Setup GT controller master bit so we can do config cycles
- */
-
- /* Clear cause register bits */
- GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
- GT_INTRCAUSE_TARABORT0_BIT));
- /* Setup address */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
- udelay(2);
- tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-
- tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
- udelay(2);
- GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
-
- /* Setup address */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
- udelay(2);
- tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-}
-
-unsigned short get_gt_devid(void)
-{
- u32 gt_devid;
-
- /* Figure out if this is a gt96100 or gt96100A */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
- udelay(4);
- gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS);
-
- return gt_devid >> 16;
-}
diff --git a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c
deleted file mode 100644
index 8cbe8426491..00000000000
--- a/arch/mips/galileo-boards/ev96100/time.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo EV96100 rtc routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_rtc.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/timex.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/time.h>
-
-
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-
-extern volatile unsigned long wall_jiffies;
-unsigned long missed_heart_beats = 0;
-
-static unsigned long r4k_offset; /* Amount to increment compare reg each time */
-static unsigned long r4k_cur; /* What counter should be at next timer irq */
-
-static inline void ack_r4ktimer(unsigned long newval)
-{
- write_c0_compare(newval);
-}
-
-/*
- * There are a lot of conceptually broken versions of the MIPS timer interrupt
- * handler floating around. This one is rather different, but the algorithm
- * is probably more robust.
- */
-void mips_timer_interrupt(struct pt_regs *regs)
-{
- int irq = 7; /* FIX ME */
-
- if (r4k_offset == 0) {
- goto null;
- }
-
- do {
- kstat_this_cpu.irqs[irq]++;
- do_timer(regs);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
-#endif
- r4k_cur += r4k_offset;
- ack_r4ktimer(r4k_cur);
-
- } while (((unsigned long)read_c0_count()
- - r4k_cur) < 0x7fffffff);
- return;
-
-null:
- ack_r4ktimer(0);
-}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index aa2caa67299..9fbf8430c84 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -38,15 +38,40 @@ static void r3081_wait(void)
static void r39xx_wait(void)
{
- unsigned long cfg = read_c0_conf();
- write_c0_conf(cfg | TX39_CONF_HALT);
+ local_irq_disable();
+ if (!need_resched())
+ write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
+ local_irq_enable();
}
+/*
+ * There is a race when WAIT instruction executed with interrupt
+ * enabled.
+ * But it is implementation-dependent wheter the pipelie restarts when
+ * a non-enabled interrupt is requested.
+ */
static void r4k_wait(void)
{
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
+ __asm__(" .set mips3 \n"
+ " wait \n"
+ " .set mips0 \n");
+}
+
+/*
+ * This variant is preferable as it allows testing need_resched and going to
+ * sleep depending on the outcome atomically. Unfortunately the "It is
+ * implementation-dependent whether the pipeline restarts when a non-enabled
+ * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
+ * using this version a gamble.
+ */
+static void r4k_wait_irqoff(void)
+{
+ local_irq_disable();
+ if (!need_resched())
+ __asm__(" .set mips3 \n"
+ " wait \n"
+ " .set mips0 \n");
+ local_irq_enable();
}
/* The Au1xxx wait is available only if using 32khz counter or
@@ -56,17 +81,17 @@ int allow_au1k_wait;
static void au1k_wait(void)
{
/* using the wait instruction makes CP0 counter unusable */
- __asm__(".set mips3\n\t"
- "cache 0x14, 0(%0)\n\t"
- "cache 0x14, 32(%0)\n\t"
- "sync\n\t"
- "nop\n\t"
- "wait\n\t"
- "nop\n\t"
- "nop\n\t"
- "nop\n\t"
- "nop\n\t"
- ".set mips0\n\t"
+ __asm__(" .set mips3 \n"
+ " cache 0x14, 0(%0) \n"
+ " cache 0x14, 32(%0) \n"
+ " sync \n"
+ " nop \n"
+ " wait \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " .set mips0 \n"
: : "r" (au1k_wait));
}
@@ -111,7 +136,6 @@ static inline void check_wait(void)
case CPU_NEVADA:
case CPU_RM7000:
case CPU_RM9000:
- case CPU_TX49XX:
case CPU_4KC:
case CPU_4KEC:
case CPU_4KSC:
@@ -125,6 +149,10 @@ static inline void check_wait(void)
cpu_wait = r4k_wait;
printk(" available.\n");
break;
+ case CPU_TX49XX:
+ cpu_wait = r4k_wait_irqoff;
+ printk(" available.\n");
+ break;
case CPU_AU1000:
case CPU_AU1100:
case CPU_AU1500:
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 676e868d26f..2132485caa7 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -17,6 +17,7 @@
#include <asm/ptrace.h>
#include <asm/uaccess.h>
+#include <asm/unistd.h>
#undef DEBUG_SIG
@@ -172,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
return ret;
}
-asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
+void do_irix_signal(struct pt_regs *regs)
{
struct k_sigaction ka;
siginfo_t info;
int signr;
+ sigset_t *oldset;
/*
* We want the common case to go fast, which is why we may in certain
@@ -184,19 +186,28 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
* if so.
*/
if (!user_mode(regs))
- return 1;
+ return;
- if (try_to_freeze())
- goto no_signal;
-
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0)
- return handle_signal(signr, &info, &ka, oldset, regs);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
+ }
-no_signal:
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
@@ -208,8 +219,22 @@ no_signal:
regs->regs[2] == ERESTARTNOINTR) {
regs->cp0_epc -= 8;
}
+ if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+ regs->regs[2] = __NR_restart_syscall;
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 4;
+ }
+ regs->regs[0] = 0; /* Don't deal with this again. */
+ }
+
+ /*
+ * If there's no signal to deliver, we just put the saved sigmask
+ * back
+ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
- return 0;
}
asmlinkage void
@@ -298,6 +323,9 @@ struct sigact_irix5 {
int _unused0[2];
};
+#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility:
+ set only the low 32 bit of the sigset. */
+
#ifdef DEBUG_SIG
static inline void dump_sigact_irix5(struct sigact_irix5 *p)
{
@@ -413,7 +441,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
asmlinkage int irix_sigsuspend(struct pt_regs *regs)
{
- sigset_t saveset, newset;
+ sigset_t newset;
sigset_t __user *uset;
uset = (sigset_t __user *) regs->regs[4];
@@ -422,18 +450,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs->regs[2] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_irix_signal(&saveset, regs))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
/* hate hate hate... */
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 450ac592da5..43b1162d714 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -991,7 +991,7 @@ struct sysctl_args32
unsigned int __unused[4];
};
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
{
@@ -1032,7 +1032,7 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
return error;
}
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
asmlinkage long sys32_newuname(struct new_utsname __user * name)
{
@@ -1296,9 +1296,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
return do_fork(clone_flags, newsp, &regs, 0,
parent_tidptr, child_tidptr);
}
-
-extern asmlinkage void sys_set_thread_area(u32 addr);
-asmlinkage void sys32_set_thread_area(u32 addr)
-{
- sys_set_thread_area(AA(addr));
-}
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 7ab67f786bf..2613a0dd4b8 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -273,104 +273,107 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
}
-static struct mips_frame_info {
- void *func;
- unsigned long func_size;
- int frame_size;
- int pc_offset;
-} *schedule_frame, mfinfo[64];
-static int mfinfo_num;
-
-static int __init get_frame_info(struct mips_frame_info *info)
+/*
+ *
+ */
+struct mips_frame_info {
+ void *func;
+ unsigned long func_size;
+ int frame_size;
+ int pc_offset;
+};
+
+static inline int is_ra_save_ins(union mips_instruction *ip)
{
- int i;
- void *func = info->func;
- union mips_instruction *ip = (union mips_instruction *)func;
+ /* sw / sd $ra, offset($sp) */
+ return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
+ ip->i_format.rs == 29 &&
+ ip->i_format.rt == 31;
+}
+
+static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
+{
+ if (ip->j_format.opcode == jal_op)
+ return 1;
+ if (ip->r_format.opcode != spec_op)
+ return 0;
+ return ip->r_format.func == jalr_op || ip->r_format.func == jr_op;
+}
+
+static inline int is_sp_move_ins(union mips_instruction *ip)
+{
+ /* addiu/daddiu sp,sp,-imm */
+ if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
+ return 0;
+ if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+ return 1;
+ return 0;
+}
+
+static int get_frame_info(struct mips_frame_info *info)
+{
+ union mips_instruction *ip = info->func;
+ unsigned max_insns = info->func_size / sizeof(union mips_instruction);
+ unsigned i;
+
info->pc_offset = -1;
info->frame_size = 0;
- for (i = 0; i < 128; i++, ip++) {
- /* if jal, jalr, jr, stop. */
- if (ip->j_format.opcode == jal_op ||
- (ip->r_format.opcode == spec_op &&
- (ip->r_format.func == jalr_op ||
- ip->r_format.func == jr_op)))
- break;
- if (info->func_size && i >= info->func_size / 4)
+ if (!ip)
+ goto err;
+
+ if (max_insns == 0)
+ max_insns = 128U; /* unknown function size */
+ max_insns = min(128U, max_insns);
+
+ for (i = 0; i < max_insns; i++, ip++) {
+
+ if (is_jal_jalr_jr_ins(ip))
break;
- if (
-#ifdef CONFIG_32BIT
- ip->i_format.opcode == addiu_op &&
-#endif
-#ifdef CONFIG_64BIT
- ip->i_format.opcode == daddiu_op &&
-#endif
- ip->i_format.rs == 29 &&
- ip->i_format.rt == 29) {
- /* addiu/daddiu sp,sp,-imm */
- if (info->frame_size)
- continue;
- info->frame_size = - ip->i_format.simmediate;
+ if (!info->frame_size) {
+ if (is_sp_move_ins(ip))
+ info->frame_size = - ip->i_format.simmediate;
+ continue;
}
-
- if (
-#ifdef CONFIG_32BIT
- ip->i_format.opcode == sw_op &&
-#endif
-#ifdef CONFIG_64BIT
- ip->i_format.opcode == sd_op &&
-#endif
- ip->i_format.rs == 29 &&
- ip->i_format.rt == 31) {
- /* sw / sd $ra, offset($sp) */
- if (info->pc_offset != -1)
- continue;
+ if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
info->pc_offset =
ip->i_format.simmediate / sizeof(long);
+ break;
}
}
- if (info->pc_offset == -1 || info->frame_size == 0) {
- if (func == schedule)
- printk("Can't analyze prologue code at %p\n", func);
- info->pc_offset = -1;
- info->frame_size = 0;
- }
-
- return 0;
+ if (info->frame_size && info->pc_offset >= 0) /* nested */
+ return 0;
+ if (info->pc_offset < 0) /* leaf */
+ return 1;
+ /* prologue seems boggus... */
+err:
+ return -1;
}
+static struct mips_frame_info schedule_mfi __read_mostly;
+
static int __init frame_info_init(void)
{
- int i;
+ unsigned long size = 0;
#ifdef CONFIG_KALLSYMS
+ unsigned long ofs;
char *modname;
char namebuf[KSYM_NAME_LEN + 1];
- unsigned long start, size, ofs;
- extern char __sched_text_start[], __sched_text_end[];
- extern char __lock_text_start[], __lock_text_end[];
-
- start = (unsigned long)__sched_text_start;
- for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
- if (start == (unsigned long)schedule)
- schedule_frame = &mfinfo[i];
- if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
- break;
- mfinfo[i].func = (void *)(start + ofs);
- mfinfo[i].func_size = size;
- start += size - ofs;
- if (start >= (unsigned long)__lock_text_end)
- break;
- if (start == (unsigned long)__sched_text_end)
- start = (unsigned long)__lock_text_start;
- }
-#else
- mfinfo[0].func = schedule;
- schedule_frame = &mfinfo[0];
+
+ kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
#endif
- for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
- get_frame_info(&mfinfo[i]);
+ schedule_mfi.func = schedule;
+ schedule_mfi.func_size = size;
+
+ get_frame_info(&schedule_mfi);
+
+ /*
+ * Without schedule() frame info, result given by
+ * thread_saved_pc() and get_wchan() are not reliable.
+ */
+ if (schedule_mfi.pc_offset < 0)
+ printk("Can't analyze schedule() prologue at %p\n", schedule);
- mfinfo_num = i;
return 0;
}
@@ -386,54 +389,86 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
/* New born processes are a special case */
if (t->reg31 == (unsigned long) ret_from_fork)
return t->reg31;
-
- if (!schedule_frame || schedule_frame->pc_offset < 0)
+ if (schedule_mfi.pc_offset < 0)
return 0;
- return ((unsigned long *)t->reg29)[schedule_frame->pc_offset];
+ return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
}
-/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */
-unsigned long get_wchan(struct task_struct *p)
+
+#ifdef CONFIG_KALLSYMS
+/* used by show_backtrace() */
+unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+ unsigned long pc, unsigned long ra)
{
unsigned long stack_page;
- unsigned long pc;
-#ifdef CONFIG_KALLSYMS
- unsigned long frame;
-#endif
+ struct mips_frame_info info;
+ char *modname;
+ char namebuf[KSYM_NAME_LEN + 1];
+ unsigned long size, ofs;
+ int leaf;
- if (!p || p == current || p->state == TASK_RUNNING)
+ stack_page = (unsigned long)task_stack_page(task);
+ if (!stack_page)
return 0;
- stack_page = (unsigned long)task_stack_page(p);
- if (!stack_page || !mfinfo_num)
+ if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf))
+ return 0;
+ /*
+ * Return ra if an exception occured at the first instruction
+ */
+ if (unlikely(ofs == 0))
+ return ra;
+
+ info.func = (void *)(pc - ofs);
+ info.func_size = ofs; /* analyze from start to ofs */
+ leaf = get_frame_info(&info);
+ if (leaf < 0)
+ return 0;
+
+ if (*sp < stack_page ||
+ *sp + info.frame_size > stack_page + THREAD_SIZE - 32)
return 0;
- pc = thread_saved_pc(p);
+ if (leaf)
+ /*
+ * For some extreme cases, get_frame_info() can
+ * consider wrongly a nested function as a leaf
+ * one. In that cases avoid to return always the
+ * same value.
+ */
+ pc = pc != ra ? ra : 0;
+ else
+ pc = ((unsigned long *)(*sp))[info.pc_offset];
+
+ *sp += info.frame_size;
+ return __kernel_text_address(pc) ? pc : 0;
+}
+#endif
+
+/*
+ * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
+ */
+unsigned long get_wchan(struct task_struct *task)
+{
+ unsigned long pc = 0;
#ifdef CONFIG_KALLSYMS
- if (!in_sched_functions(pc))
- return pc;
+ unsigned long sp;
+#endif
- frame = p->thread.reg29 + schedule_frame->frame_size;
- do {
- int i;
+ if (!task || task == current || task->state == TASK_RUNNING)
+ goto out;
+ if (!task_stack_page(task))
+ goto out;
- if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
- return 0;
+ pc = thread_saved_pc(task);
- for (i = mfinfo_num - 1; i >= 0; i--) {
- if (pc >= (unsigned long) mfinfo[i].func)
- break;
- }
- if (i < 0)
- break;
+#ifdef CONFIG_KALLSYMS
+ sp = task->thread.reg29 + schedule_mfi.frame_size;
- pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
- if (!mfinfo[i].frame_size)
- break;
- frame += mfinfo[i].frame_size;
- } while (in_sched_functions(pc));
+ while (in_sched_functions(pc))
+ pc = unwind_stack(task, &sp, pc, 0);
#endif
+out:
return pc;
}
-
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index ba1bcd83c7d..e7178510220 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -662,6 +662,8 @@ einval: li v0, -EINVAL
sys sys_tee 4
sys sys_vmsplice 4
sys sys_move_pages 6
+ sys sys_set_robust_list 2
+ sys sys_get_robust_list 3
.endm
/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 939e172db95..4c22d0b4825 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -466,3 +466,5 @@ sys_call_table:
PTR sys_tee /* 5265 */
PTR sys_vmsplice
PTR sys_move_pages
+ PTR sys_set_robust_list
+ PTR sys_get_robust_list
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 98abbc5a9f1..f25c2a2f103 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -247,7 +247,7 @@ EXPORT(sysn32_call_table)
PTR sys_capset
PTR sys32_rt_sigpending /* 6125 */
PTR compat_sys_rt_sigtimedwait
- PTR sys_rt_sigqueueinfo
+ PTR sys32_rt_sigqueueinfo
PTR sysn32_rt_sigsuspend
PTR sys32_sigaltstack
PTR compat_sys_utime /* 6130 */
@@ -390,5 +390,7 @@ EXPORT(sysn32_call_table)
PTR sys_splice
PTR sys_sync_file_range
PTR sys_tee
- PTR sys_vmsplice /* 6271 */
+ PTR sys_vmsplice /* 6270 */
PTR sys_move_pages
+ PTR compat_sys_set_robust_list
+ PTR compat_sys_get_robust_list
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 505c9ee5400..288ee4ac4db 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -498,7 +498,7 @@ sys_call_table:
PTR sys_mknodat /* 4290 */
PTR sys_fchownat
PTR compat_sys_futimesat
- PTR compat_sys_newfstatat
+ PTR sys_newfstatat
PTR sys_unlinkat
PTR sys_renameat /* 4295 */
PTR sys_linkat
@@ -514,4 +514,6 @@ sys_call_table:
PTR sys_tee
PTR sys_vmsplice
PTR compat_sys_move_pages
+ PTR compat_sys_set_robust_list
+ PTR compat_sys_get_robust_list /* 4310 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8c2b596a136..fdbb508661c 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -10,29 +10,15 @@
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) 2000 2001, 2002 Maciej W. Rozycki
*/
-#include <linux/errno.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
#include <linux/screen_info.h>
#include <linux/bootmem.h>
#include <linux/initrd.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <linux/highmem.h>
#include <linux/console.h>
-#include <linux/mmzone.h>
#include <linux/pfn.h>
#include <asm/addrspace.h>
@@ -96,6 +82,12 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
int x = boot_mem_map.nr_map;
struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+ /* Sanity check */
+ if (start + size < start) {
+ printk("Trying to add an invalid memory region, skipped\n");
+ return;
+ }
+
/*
* Try to merge with previous entry if any. This is far less than
* perfect but is sufficient for most real world cases.
@@ -143,167 +135,132 @@ static void __init print_memory_map(void)
}
}
-static inline void parse_cmdline_early(void)
+/*
+ * Manage initrd
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init rd_start_early(char *p)
{
- char c = ' ', *to = command_line, *from = saved_command_line;
- unsigned long start_at, mem_size;
- int len = 0;
- int usermem = 0;
+ unsigned long start = memparse(p, &p);
- printk("Determined physical RAM map:\n");
- print_memory_map();
+#ifdef CONFIG_64BIT
+ /* HACK: Guess if the sign extension was forgotten */
+ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+ start |= 0xffffffff00000000UL;
+#endif
+ initrd_start = start;
+ initrd_end += start;
- for (;;) {
- /*
- * "mem=XXX[kKmM]" defines a memory region from
- * 0 to <XXX>, overriding the determined size.
- * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
- * <YYY> to <YYY>+<XXX>, overriding the determined size.
- */
- if (c == ' ' && !memcmp(from, "mem=", 4)) {
- if (to != command_line)
- to--;
- /*
- * If a user specifies memory size, we
- * blow away any automatically generated
- * size.
- */
- if (usermem == 0) {
- boot_mem_map.nr_map = 0;
- usermem = 1;
- }
- mem_size = memparse(from + 4, &from);
- if (*from == '@')
- start_at = memparse(from + 1, &from);
- else
- start_at = 0;
- add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
- }
- c = *(from++);
- if (!c)
- break;
- if (CL_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
+ return 0;
+}
+early_param("rd_start", rd_start_early);
- if (usermem) {
- printk("User-defined physical RAM map:\n");
- print_memory_map();
- }
+static int __init rd_size_early(char *p)
+{
+ initrd_end += memparse(p, &p);
+
+ return 0;
}
+early_param("rd_size", rd_size_early);
-static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+static unsigned long __init init_initrd(void)
{
+ unsigned long tmp, end, size;
+ u32 *initrd_header;
+
+ ROOT_DEV = Root_RAM0;
+
/*
- * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
- * "rd_size=0xNN" it's size
+ * Board specific code or command line parser should have
+ * already set up initrd_start and initrd_end. In these cases
+ * perfom sanity checks and use them if all looks good.
*/
- unsigned long start = 0;
- unsigned long size = 0;
- unsigned long end;
- char cmd_line[CL_SIZE];
- char *start_str;
- char *size_str;
- char *tmp;
-
- strcpy(cmd_line, command_line);
- *command_line = 0;
- tmp = cmd_line;
- /* Ignore "rd_start=" strings in other parameters. */
- start_str = strstr(cmd_line, "rd_start=");
- if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
- start_str = strstr(start_str, " rd_start=");
- while (start_str) {
- if (start_str != cmd_line)
- strncat(command_line, tmp, start_str - tmp);
- start = memparse(start_str + 9, &start_str);
- tmp = start_str + 1;
- start_str = strstr(start_str, " rd_start=");
+ size = initrd_end - initrd_start;
+ if (initrd_end == 0 || size == 0) {
+ initrd_start = 0;
+ initrd_end = 0;
+ } else
+ return initrd_end;
+
+ end = (unsigned long)&_end;
+ tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
+ if (tmp < end)
+ tmp += PAGE_SIZE;
+
+ initrd_header = (u32 *)tmp;
+ if (initrd_header[0] == 0x494E5244) {
+ initrd_start = (unsigned long)&initrd_header[2];
+ initrd_end = initrd_start + initrd_header[1];
}
- if (*tmp)
- strcat(command_line, tmp);
-
- strcpy(cmd_line, command_line);
- *command_line = 0;
- tmp = cmd_line;
- /* Ignore "rd_size" strings in other parameters. */
- size_str = strstr(cmd_line, "rd_size=");
- if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
- size_str = strstr(size_str, " rd_size=");
- while (size_str) {
- if (size_str != cmd_line)
- strncat(command_line, tmp, size_str - tmp);
- size = memparse(size_str + 8, &size_str);
- tmp = size_str + 1;
- size_str = strstr(size_str, " rd_size=");
+ return initrd_end;
+}
+
+static void __init finalize_initrd(void)
+{
+ unsigned long size = initrd_end - initrd_start;
+
+ if (size == 0) {
+ printk(KERN_INFO "Initrd not found or empty");
+ goto disable;
+ }
+ if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ printk("Initrd extends beyond end of memory");
+ goto disable;
}
- if (*tmp)
- strcat(command_line, tmp);
-#ifdef CONFIG_64BIT
- /* HACK: Guess if the sign extension was forgotten */
- if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
- start |= 0xffffffff00000000UL;
+ reserve_bootmem(CPHYSADDR(initrd_start), size);
+ initrd_below_start_ok = 1;
+
+ printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
+ initrd_start, size);
+ return;
+disable:
+ printk(" - disabling initrd\n");
+ initrd_start = 0;
+ initrd_end = 0;
+}
+
+#else /* !CONFIG_BLK_DEV_INITRD */
+
+#define init_initrd() 0
+#define finalize_initrd() do {} while (0)
+
#endif
- end = start + size;
- if (start && end) {
- *rd_start = start;
- *rd_end = end;
- return 1;
- }
- return 0;
+/*
+ * Initialize the bootmem allocator. It also setup initrd related data
+ * if needed.
+ */
+#ifdef CONFIG_SGI_IP27
+
+static void __init bootmem_init(void)
+{
+ init_initrd();
+ finalize_initrd();
}
-#define MAXMEM HIGHMEM_START
-#define MAXMEM_PFN PFN_DOWN(MAXMEM)
+#else /* !CONFIG_SGI_IP27 */
-static inline void bootmem_init(void)
+static void __init bootmem_init(void)
{
- unsigned long start_pfn;
- unsigned long reserved_end = (unsigned long)&_end;
-#ifndef CONFIG_SGI_IP27
- unsigned long first_usable_pfn;
+ unsigned long reserved_end;
+ unsigned long highest = 0;
+ unsigned long mapstart = -1UL;
unsigned long bootmap_size;
int i;
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
- int initrd_reserve_bootmem = 0;
-
- /* Board specific code should have set up initrd_start and initrd_end */
- ROOT_DEV = Root_RAM0;
- if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
- reserved_end = max(reserved_end, initrd_end);
- initrd_reserve_bootmem = 1;
- } else {
- unsigned long tmp;
- u32 *initrd_header;
-
- tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2;
- if (tmp < reserved_end)
- tmp += PAGE_SIZE;
- initrd_header = (u32 *)tmp;
- if (initrd_header[0] == 0x494E5244) {
- initrd_start = (unsigned long)&initrd_header[2];
- initrd_end = initrd_start + initrd_header[1];
- reserved_end = max(reserved_end, initrd_end);
- initrd_reserve_bootmem = 1;
- }
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
/*
- * Partially used pages are not usable - thus
- * we are rounding upwards.
+ * Init any data related to initrd. It's a nop if INITRD is
+ * not selected. Once that done we can determine the low bound
+ * of usable memory.
*/
- start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+ reserved_end = init_initrd();
+ reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
-#ifndef CONFIG_SGI_IP27
- /* Find the highest page frame number we have available. */
- max_pfn = 0;
- first_usable_pfn = -1UL;
+ /*
+ * Find the highest page frame number we have available.
+ */
for (i = 0; i < boot_mem_map.nr_map; i++) {
unsigned long start, end;
@@ -312,56 +269,38 @@ static inline void bootmem_init(void)
start = PFN_UP(boot_mem_map.map[i].addr);
end = PFN_DOWN(boot_mem_map.map[i].addr
- + boot_mem_map.map[i].size);
+ + boot_mem_map.map[i].size);
- if (start >= end)
+ if (end > highest)
+ highest = end;
+ if (end <= reserved_end)
continue;
- if (end > max_pfn)
- max_pfn = end;
- if (start < first_usable_pfn) {
- if (start > start_pfn) {
- first_usable_pfn = start;
- } else if (end > start_pfn) {
- first_usable_pfn = start_pfn;
- }
- }
+ if (start >= mapstart)
+ continue;
+ mapstart = max(reserved_end, start);
}
/*
* Determine low and high memory ranges
*/
- max_low_pfn = max_pfn;
- if (max_low_pfn > MAXMEM_PFN) {
- max_low_pfn = MAXMEM_PFN;
-#ifndef CONFIG_HIGHMEM
- /* Maximum memory usable is what is directly addressable */
- printk(KERN_WARNING "Warning only %ldMB will be used.\n",
- MAXMEM >> 20);
- printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+ if (highest > PFN_DOWN(HIGHMEM_START)) {
+#ifdef CONFIG_HIGHMEM
+ highstart_pfn = PFN_DOWN(HIGHMEM_START);
+ highend_pfn = highest;
#endif
+ highest = PFN_DOWN(HIGHMEM_START);
}
-#ifdef CONFIG_HIGHMEM
/*
- * Crude, we really should make a better attempt at detecting
- * highstart_pfn
+ * Initialize the boot-time allocator with low memory only.
*/
- highstart_pfn = highend_pfn = max_pfn;
- if (max_pfn > MAXMEM_PFN) {
- highstart_pfn = MAXMEM_PFN;
- printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
- (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT));
- }
-#endif
-
- /* Initialize the boot-time allocator with low memory only. */
- bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
+ bootmap_size = init_bootmem(mapstart, highest);
/*
* Register fully available low RAM pages with the bootmem allocator.
*/
for (i = 0; i < boot_mem_map.nr_map; i++) {
- unsigned long curr_pfn, last_pfn, size;
+ unsigned long start, end, size;
/*
* Reserve usable memory.
@@ -369,85 +308,50 @@ static inline void bootmem_init(void)
if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
continue;
- /*
- * We are rounding up the start address of usable memory:
- */
- curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
- if (curr_pfn >= max_low_pfn)
- continue;
- if (curr_pfn < start_pfn)
- curr_pfn = start_pfn;
-
- /*
- * ... and at the end of the usable range downwards:
- */
- last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+ start = PFN_UP(boot_mem_map.map[i].addr);
+ end = PFN_DOWN(boot_mem_map.map[i].addr
+ boot_mem_map.map[i].size);
-
- if (last_pfn > max_low_pfn)
- last_pfn = max_low_pfn;
-
/*
- * Only register lowmem part of lowmem segment with bootmem.
+ * We are rounding up the start address of usable memory
+ * and at the end of the usable range downwards.
*/
- size = last_pfn - curr_pfn;
- if (curr_pfn > PFN_DOWN(HIGHMEM_START))
- continue;
- if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START))
- size = PFN_DOWN(HIGHMEM_START) - curr_pfn;
- if (!size)
+ if (start >= max_low_pfn)
continue;
+ if (start < reserved_end)
+ start = reserved_end;
+ if (end > max_low_pfn)
+ end = max_low_pfn;
/*
- * ... finally, did all the rounding and playing
- * around just make the area go away?
+ * ... finally, is the area going away?
*/
- if (last_pfn <= curr_pfn)
+ if (end <= start)
continue;
+ size = end - start;
/* Register lowmem ranges */
- free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
- memory_present(0, curr_pfn, curr_pfn + size - 1);
+ free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT);
+ memory_present(0, start, end);
}
- /* Reserve the bootmap memory. */
- reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif /* CONFIG_SGI_IP27 */
-
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_below_start_ok = 1;
- if (initrd_start) {
- unsigned long initrd_size = ((unsigned char *)initrd_end) -
- ((unsigned char *)initrd_start);
- const int width = sizeof(long) * 2;
-
- printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
- (void *)initrd_start, initrd_size);
-
- if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
- printk("initrd extends beyond end of memory "
- "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
- width,
- (unsigned long long) CPHYSADDR(initrd_end),
- width,
- (unsigned long long) PFN_PHYS(max_low_pfn));
- initrd_start = initrd_end = 0;
- initrd_reserve_bootmem = 0;
- }
+ /*
+ * Reserve the bootmap memory.
+ */
+ reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
- if (initrd_reserve_bootmem)
- reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
+ /*
+ * Reserve initrd memory if needed.
+ */
+ finalize_initrd();
}
+#endif /* CONFIG_SGI_IP27 */
+
/*
* arch_mem_init - initialize memory managment subsystem
*
* o plat_mem_setup() detects the memory configuration and will record detected
* memory areas using add_memory_region.
- * o parse_cmdline_early() parses the command line for mem= options which,
- * iff detected, will override the results of the automatic detection.
*
* At this stage the memory configuration of the system is known to the
* kernel but generic memory managment system is still entirely uninitialized.
@@ -465,25 +369,59 @@ static inline void bootmem_init(void)
* initialization hook for anything else was introduced.
*/
-extern void plat_mem_setup(void);
+static int usermem __initdata = 0;
+
+static int __init early_parse_mem(char *p)
+{
+ unsigned long start, size;
+
+ /*
+ * If a user specifies memory size, we
+ * blow away any automatically generated
+ * size.
+ */
+ if (usermem == 0) {
+ boot_mem_map.nr_map = 0;
+ usermem = 1;
+ }
+ start = 0;
+ size = memparse(p, &p);
+ if (*p == '@')
+ start = memparse(p + 1, &p);
+
+ add_memory_region(start, size, BOOT_MEM_RAM);
+ return 0;
+}
+early_param("mem", early_parse_mem);
static void __init arch_mem_init(char **cmdline_p)
{
+ extern void plat_mem_setup(void);
+
/* call board setup routine */
plat_mem_setup();
+ printk("Determined physical RAM map:\n");
+ print_memory_map();
+
strlcpy(command_line, arcs_cmdline, sizeof(command_line));
strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
- parse_cmdline_early();
+ parse_early_param();
+
+ if (usermem) {
+ printk("User-defined physical RAM map:\n");
+ print_memory_map();
+ }
+
bootmem_init();
sparse_init();
paging_init();
}
-static inline void resource_init(void)
+static void __init resource_init(void)
{
int i;
@@ -504,10 +442,10 @@ static inline void resource_init(void)
start = boot_mem_map.map[i].addr;
end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1;
- if (start >= MAXMEM)
+ if (start >= HIGHMEM_START)
continue;
- if (end >= MAXMEM)
- end = MAXMEM - 1;
+ if (end >= HIGHMEM_START)
+ end = HIGHMEM_START - 1;
res = alloc_bootmem(sizeof(struct resource));
switch (boot_mem_map.map[i].type) {
@@ -536,9 +474,6 @@ static inline void resource_init(void)
}
}
-#undef MAXMEM
-#undef MAXMEM_PFN
-
void __init setup_arch(char **cmdline_p)
{
cpu_probe();
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 6b4d9be3161..b9d358e0521 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -424,15 +424,11 @@ void do_signal(struct pt_regs *regs)
if (!user_mode(regs))
return;
- if (try_to_freeze())
- goto no_signal;
-
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
-
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
@@ -446,9 +442,10 @@ void do_signal(struct pt_regs *regs)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
+
+ return;
}
-no_signal:
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
@@ -466,6 +463,7 @@ no_signal:
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4;
}
+ regs->regs[0] = 0; /* Don't deal with this again. */
}
/*
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index f32a22997c3..c86a5ddff05 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -815,9 +815,6 @@ void do_signal32(struct pt_regs *regs)
if (!user_mode(regs))
return;
- if (try_to_freeze())
- goto no_signal;
-
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
@@ -836,9 +833,10 @@ void do_signal32(struct pt_regs *regs)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
+
+ return;
}
-no_signal:
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
@@ -856,6 +854,7 @@ no_signal:
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4;
}
+ regs->regs[0] = 0; /* Don't deal with this again. */
}
/*
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 93429a4d301..766253c44f3 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -203,7 +203,7 @@ void plat_smp_setup(void)
write_vpe_c0_config( read_c0_config());
/* make sure there are no software interrupts pending */
- write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+ write_vpe_c0_cause(0);
/* Propagate Config7 */
write_vpe_c0_config7(read_c0_config7());
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 4cc3dea3661..76cb31d5748 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -8,7 +8,7 @@
#include <asm/regdef.h>
#include <asm/asmmacro.h>
#include <asm/stackframe.h>
-#include <asm/stackframe.h>
+#include <asm/irqflags.h>
/*
* "Software Interrupt" linkage.
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 0721314db65..9951240cc3f 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -263,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname __user * name)
return error;
}
-void sys_set_thread_area(unsigned long addr)
+asmlinkage int sys_set_thread_area(unsigned long addr)
{
struct thread_info *ti = task_thread_info(current);
@@ -271,6 +271,8 @@ void sys_set_thread_area(unsigned long addr)
/* If some future MIPS implementation has this register in hardware,
* we will need to update it here (and in context switches). */
+
+ return 0;
}
asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 954a198494e..e51d8fd9a15 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/kallsyms.h>
#include <linux/bootmem.h>
+#include <linux/interrupt.h>
#include <asm/bootinfo.h>
#include <asm/branch.h>
@@ -72,28 +73,68 @@ void (*board_nmi_handler_setup)(void);
void (*board_ejtag_handler_setup)(void);
void (*board_bind_eic_interrupt)(int irq, int regset);
-/*
- * These constant is for searching for possible module text segments.
- * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
- */
-#define MODULE_RANGE (8*1024*1024)
+
+static void show_raw_backtrace(unsigned long reg29)
+{
+ unsigned long *sp = (unsigned long *)reg29;
+ unsigned long addr;
+
+ printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ if (__kernel_text_address(addr))
+ print_ip_sym(addr);
+ }
+ printk("\n");
+}
+
+#ifdef CONFIG_KALLSYMS
+static int raw_show_trace;
+static int __init set_raw_show_trace(char *str)
+{
+ raw_show_trace = 1;
+ return 1;
+}
+__setup("raw_show_trace", set_raw_show_trace);
+
+extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+ unsigned long pc, unsigned long ra);
+
+static void show_backtrace(struct task_struct *task, struct pt_regs *regs)
+{
+ unsigned long sp = regs->regs[29];
+ unsigned long ra = regs->regs[31];
+ unsigned long pc = regs->cp0_epc;
+
+ if (raw_show_trace || !__kernel_text_address(pc)) {
+ show_raw_backtrace(sp);
+ return;
+ }
+ printk("Call Trace:\n");
+ do {
+ print_ip_sym(pc);
+ pc = unwind_stack(task, &sp, pc, ra);
+ ra = 0;
+ } while (pc);
+ printk("\n");
+}
+#else
+#define show_backtrace(task, r) show_raw_backtrace((r)->regs[29]);
+#endif
/*
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
-void show_stack(struct task_struct *task, unsigned long *sp)
+static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
long stackdata;
int i;
-
- if (!sp) {
- if (task && task != current)
- sp = (unsigned long *) task->thread.reg29;
- else
- sp = (unsigned long *) &sp;
- }
+ unsigned long *sp = (unsigned long *)regs->regs[29];
printk("Stack :");
i = 0;
@@ -114,32 +155,48 @@ void show_stack(struct task_struct *task, unsigned long *sp)
i++;
}
printk("\n");
+ show_backtrace(task, regs);
}
-void show_trace(struct task_struct *task, unsigned long *stack)
+static __always_inline void prepare_frametrace(struct pt_regs *regs)
{
- const int field = 2 * sizeof(unsigned long);
- unsigned long addr;
-
- if (!stack) {
- if (task && task != current)
- stack = (unsigned long *) task->thread.reg29;
- else
- stack = (unsigned long *) &stack;
- }
-
- printk("Call Trace:");
-#ifdef CONFIG_KALLSYMS
- printk("\n");
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set noat\n\t"
+#ifdef CONFIG_64BIT
+ "1: dla $1, 1b\n\t"
+ "sd $1, %0\n\t"
+ "sd $29, %1\n\t"
+ "sd $31, %2\n\t"
+#else
+ "1: la $1, 1b\n\t"
+ "sw $1, %0\n\t"
+ "sw $29, %1\n\t"
+ "sw $31, %2\n\t"
#endif
- while (!kstack_end(stack)) {
- addr = *stack++;
- if (__kernel_text_address(addr)) {
- printk(" [<%0*lx>] ", field, addr);
- print_symbol("%s\n", addr);
+ ".set pop\n\t"
+ : "=m" (regs->cp0_epc),
+ "=m" (regs->regs[29]), "=m" (regs->regs[31])
+ : : "memory");
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ struct pt_regs regs;
+ if (sp) {
+ regs.regs[29] = (unsigned long)sp;
+ regs.regs[31] = 0;
+ regs.cp0_epc = 0;
+ } else {
+ if (task && task != current) {
+ regs.regs[29] = task->thread.reg29;
+ regs.regs[31] = 0;
+ regs.cp0_epc = task->thread.reg31;
+ } else {
+ prepare_frametrace(&regs);
}
}
- printk("\n");
+ show_stacktrace(task, &regs);
}
/*
@@ -147,9 +204,15 @@ void show_trace(struct task_struct *task, unsigned long *stack)
*/
void dump_stack(void)
{
- unsigned long stack;
+ struct pt_regs regs;
- show_trace(current, &stack);
+ /*
+ * Remove any garbage that may be in regs (specially func
+ * addresses) to avoid show_raw_backtrace() to report them
+ */
+ memset(&regs, 0, sizeof(regs));
+ prepare_frametrace(&regs);
+ show_backtrace(current, &regs);
}
EXPORT_SYMBOL(dump_stack);
@@ -268,8 +331,7 @@ void show_registers(struct pt_regs *regs)
print_modules();
printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
current->comm, current->pid, current_thread_info(), current);
- show_stack(current, (long *) regs->regs[29]);
- show_trace(current, (long *) regs->regs[29]);
+ show_stacktrace(current, regs);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
}
@@ -292,6 +354,16 @@ NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
spin_unlock_irq(&die_lock);
+
+ if (in_interrupt())
+ panic("Fatal exception in interrupt");
+
+ if (panic_on_oops) {
+ printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+ ssleep(5);
+ panic("Fatal exception");
+ }
+
do_exit(SIGSEGV);
}
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 9ee0ec2cd06..51ddd216689 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -768,10 +768,16 @@ int vpe_run(struct vpe * v)
*/
write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA));
+
+ back_to_back_c0_hazard();
+
/* Set up the XTC bit in vpeconf0 to point at our tc */
write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
| (t->index << VPECONF0_XTC_SHIFT));
+ back_to_back_c0_hazard();
+
/* enable this VPE */
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index fb25e0377f1..a020a3cb4f4 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -1,6 +1,8 @@
/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 1999, 2000, 2006 MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ * Maciej W. Rozycki <macro@mips.com>
*
* ########################################################################
*
@@ -25,17 +27,20 @@
*/
#include <linux/compiler.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
-#include <asm/irq.h>
+#include <asm/gdb-stub.h>
#include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/msc01_ic.h>
+
#include <asm/mips-boards/atlas.h>
#include <asm/mips-boards/atlasint.h>
-#include <asm/gdb-stub.h>
-
+#include <asm/mips-boards/generic.h>
static struct atlas_ictrl_regs *atlas_hw0_icregs;
@@ -47,13 +52,13 @@ static struct atlas_ictrl_regs *atlas_hw0_icregs;
void disable_atlas_irq(unsigned int irq_nr)
{
- atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+ atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE);
iob();
}
void enable_atlas_irq(unsigned int irq_nr)
{
- atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+ atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE);
iob();
}
@@ -107,7 +112,7 @@ static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
if (unlikely(int_status == 0))
return;
- irq = ATLASINT_BASE + ls1bit32(int_status);
+ irq = ATLAS_INT_BASE + ls1bit32(int_status);
DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
@@ -161,15 +166,14 @@ static inline unsigned int irq_ffs(unsigned int pending)
}
/*
- * IRQs on the Atlas board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ * IRQs on the Atlas board look basically like (all external interrupt
+ * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)):
*
- * MIPS IRQ Source
+ * MIPS IRQ Source
* -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Combined hardware interrupt (hw0)
+ * 0 Software 0 (reschedule IPI on MT)
+ * 1 Software 1 (remote call IPI on MT)
+ * 2 Combined Atlas hardware interrupt (hw0)
* 3 Hardware (ignored)
* 4 Hardware (ignored)
* 5 Hardware (ignored)
@@ -179,7 +183,7 @@ static inline unsigned int irq_ffs(unsigned int pending)
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
- * Lowest ---- Combined hardware interrupt
+ * Lowest ---- Software 0
*
* then we just return, if multiple IRQs are pending then we will just take
* another exception, big deal.
@@ -193,17 +197,19 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
if (irq == MIPSCPU_INT_ATLAS)
atlas_hw0_irqdispatch(regs);
- else if (irq > 0)
+ else if (irq >= 0)
do_IRQ(MIPSCPU_INT_BASE + irq, regs);
else
spurious_interrupt(regs);
}
-void __init arch_init_irq(void)
+static inline void init_atlas_irqs (int base)
{
int i;
- atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+ atlas_hw0_icregs = (struct atlas_ictrl_regs *)
+ ioremap(ATLAS_ICTRL_REGS_BASE,
+ sizeof(struct atlas_ictrl_regs *));
/*
* Mask out all interrupt by writing "1" to all bit position in
@@ -211,7 +217,7 @@ void __init arch_init_irq(void)
*/
atlas_hw0_icregs->intrsten = 0xffffffff;
- for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+ for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
irq_desc[i].depth = 1;
@@ -219,3 +225,62 @@ void __init arch_init_irq(void)
spin_lock_init(&irq_desc[i].lock);
}
}
+
+static struct irqaction atlasirq = {
+ .handler = no_action,
+ .name = "Atlas cascade"
+};
+
+msc_irqmap_t __initdata msc_irqmap[] = {
+ {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0},
+ {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0},
+};
+int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+
+msc_irqmap_t __initdata msc_eicirqmap[] = {
+ {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_ATLAS, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0},
+ {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0},
+ {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0}
+};
+int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+
+void __init arch_init_irq(void)
+{
+ init_atlas_irqs(ATLAS_INT_BASE);
+
+ if (!cpu_has_veic)
+ mips_cpu_irq_init(MIPSCPU_INT_BASE);
+
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ if (cpu_has_veic)
+ init_msc_irqs (MSC01E_INT_BASE,
+ msc_eicirqmap, msc_nr_eicirqs);
+ else
+ init_msc_irqs (MSC01C_INT_BASE,
+ msc_irqmap, msc_nr_irqs);
+ }
+
+
+ if (cpu_has_veic) {
+ set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
+ setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
+ } else if (cpu_has_vint) {
+ set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+ &atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
+#else /* Not SMTC */
+ setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+ } else
+ setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 9871a91fdb0..0c6b0ce1502 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -77,7 +77,7 @@ static void __init serial_init(void)
#else
s.iobase = ATLAS_UART_REGS_BASE+3;
#endif
- s.irq = ATLASINT_UART;
+ s.irq = ATLAS_INT_UART;
s.uartclk = ATLAS_BASE_BAUD * 16;
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
s.iotype = UPIO_PORT;
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 557bf961f36..8d15861fce6 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -41,8 +41,13 @@
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#endif
+#ifdef CONFIG_MIPS_MALTA
#include <asm/mips-boards/maltaint.h>
-#include <asm/mc146818-time.h>
+#endif
unsigned long cpu_khz;
@@ -92,10 +97,9 @@ extern int (*perf_irq)(struct pt_regs *regs);
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int cpu = smp_processor_id();
- int r2 = cpu_has_mips_r2;
#ifdef CONFIG_MIPS_MT_SMTC
- /*
+ /*
* In an SMTC system, one Count/Compare set exists per VPE.
* Which TC within a VPE gets the interrupt is essentially
* random - we only know that it shouldn't be one with
@@ -108,29 +112,46 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* the general MIPS timer_interrupt routine.
*/
+ int vpflags;
+
/*
- * DVPE is necessary so long as cross-VPE interrupts
- * are done via read-modify-write of Cause register.
+ * We could be here due to timer interrupt,
+ * perf counter overflow, or both.
*/
- int vpflags = dvpe();
- write_c0_compare (read_c0_count() - 1);
- clear_c0_cause(CPUCTR_IMASKBIT);
- evpe(vpflags);
+ if (read_c0_cause() & (1 << 26))
+ perf_irq(regs);
- if (cpu_data[cpu].vpe_id == 0) {
- timer_interrupt(irq, dev_id, regs);
- scroll_display_message();
- } else
- write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
- smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-
- if (cpu != 0)
+ if (read_c0_cause() & (1 << 30)) {
+ /* If timer interrupt, make it de-assert */
+ write_c0_compare (read_c0_count() - 1);
/*
- * Other CPUs should do profiling and process accounting
+ * DVPE is necessary so long as cross-VPE interrupts
+ * are done via read-modify-write of Cause register.
*/
- local_timer_interrupt(irq, dev_id, regs);
-
+ vpflags = dvpe();
+ clear_c0_cause(CPUCTR_IMASKBIT);
+ evpe(vpflags);
+ /*
+ * There are things we only want to do once per tick
+ * in an "MP" system. One TC of each VPE will take
+ * the actual timer interrupt. The others will get
+ * timer broadcast IPIs. We use whoever it is that takes
+ * the tick on VPE 0 to run the full timer_interrupt().
+ */
+ if (cpu_data[cpu].vpe_id == 0) {
+ timer_interrupt(irq, NULL, regs);
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+ scroll_display_message();
+ } else {
+ write_c0_compare(read_c0_count() +
+ (mips_hpt_frequency/HZ));
+ local_timer_interrupt(irq, dev_id, regs);
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+ }
+ }
#else /* CONFIG_MIPS_MT_SMTC */
+ int r2 = cpu_has_mips_r2;
+
if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process
@@ -161,9 +182,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
local_timer_interrupt(irq, dev_id, regs);
}
-#endif /* CONFIG_MIPS_MT_SMTC */
-
out:
+#endif /* CONFIG_MIPS_MT_SMTC */
return IRQ_HANDLED;
}
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index bb041a22f20..e1f35ef8114 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -335,7 +335,7 @@ void __init r3k_cache_init(void)
flush_cache_mm = r3k_flush_cache_mm;
flush_cache_range = r3k_flush_cache_range;
flush_cache_page = r3k_flush_cache_page;
- flush_icache_page = r3k_flush_icache_page;
+ __flush_icache_page = r3k_flush_icache_page;
flush_icache_range = r3k_flush_icache_range;
flush_cache_sigtramp = r3k_flush_cache_sigtramp;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 069803f58f3..0b2da53750b 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -89,7 +89,7 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
blast_dcache32_page(addr);
}
-static inline void r4k_blast_dcache_page_setup(void)
+static void __init r4k_blast_dcache_page_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
@@ -103,7 +103,7 @@ static inline void r4k_blast_dcache_page_setup(void)
static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
-static inline void r4k_blast_dcache_page_indexed_setup(void)
+static void __init r4k_blast_dcache_page_indexed_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
@@ -117,7 +117,7 @@ static inline void r4k_blast_dcache_page_indexed_setup(void)
static void (* r4k_blast_dcache)(void);
-static inline void r4k_blast_dcache_setup(void)
+static void __init r4k_blast_dcache_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
@@ -202,7 +202,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page)
static void (* r4k_blast_icache_page)(unsigned long addr);
-static inline void r4k_blast_icache_page_setup(void)
+static void __init r4k_blast_icache_page_setup(void)
{
unsigned long ic_lsize = cpu_icache_line_size();
@@ -219,7 +219,7 @@ static inline void r4k_blast_icache_page_setup(void)
static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
-static inline void r4k_blast_icache_page_indexed_setup(void)
+static void __init r4k_blast_icache_page_indexed_setup(void)
{
unsigned long ic_lsize = cpu_icache_line_size();
@@ -243,7 +243,7 @@ static inline void r4k_blast_icache_page_indexed_setup(void)
static void (* r4k_blast_icache)(void);
-static inline void r4k_blast_icache_setup(void)
+static void __init r4k_blast_icache_setup(void)
{
unsigned long ic_lsize = cpu_icache_line_size();
@@ -264,7 +264,7 @@ static inline void r4k_blast_icache_setup(void)
static void (* r4k_blast_scache_page)(unsigned long addr);
-static inline void r4k_blast_scache_page_setup(void)
+static void __init r4k_blast_scache_page_setup(void)
{
unsigned long sc_lsize = cpu_scache_line_size();
@@ -282,7 +282,7 @@ static inline void r4k_blast_scache_page_setup(void)
static void (* r4k_blast_scache_page_indexed)(unsigned long addr);
-static inline void r4k_blast_scache_page_indexed_setup(void)
+static void __init r4k_blast_scache_page_indexed_setup(void)
{
unsigned long sc_lsize = cpu_scache_line_size();
@@ -300,7 +300,7 @@ static inline void r4k_blast_scache_page_indexed_setup(void)
static void (* r4k_blast_scache)(void);
-static inline void r4k_blast_scache_setup(void)
+static void __init r4k_blast_scache_setup(void)
{
unsigned long sc_lsize = cpu_scache_line_size();
@@ -475,7 +475,7 @@ static inline void local_r4k_flush_cache_page(void *args)
}
}
if (exec) {
- if (cpu_has_vtag_icache) {
+ if (cpu_has_vtag_icache && mm == current->active_mm) {
int cpu = smp_processor_id();
if (cpu_context(cpu, mm) != 0)
@@ -599,7 +599,7 @@ static inline void local_r4k_flush_icache_page(void *args)
* We're not sure of the virtual address(es) involved here, so
* we have to flush the entire I-cache.
*/
- if (cpu_has_vtag_icache) {
+ if (cpu_has_vtag_icache && vma->vm_mm == current->active_mm) {
int cpu = smp_processor_id();
if (cpu_context(cpu, vma->vm_mm) != 0)
@@ -1221,7 +1221,7 @@ void au1x00_fixup_config_od(void)
}
}
-static inline void coherency_setup(void)
+static void __init coherency_setup(void)
{
change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
@@ -1242,7 +1242,7 @@ static inline void coherency_setup(void)
clear_c0_config(CONF_CU);
break;
/*
- * We need to catch the ealry Alchemy SOCs with
+ * We need to catch the early Alchemy SOCs with
* the write-only co_config.od bit and set it back to one...
*/
case CPU_AU1000: /* rev. DA, HA, HB */
@@ -1291,7 +1291,7 @@ void __init r4k_cache_init(void)
__flush_cache_all = r4k___flush_cache_all;
flush_cache_mm = r4k_flush_cache_mm;
flush_cache_page = r4k_flush_cache_page;
- flush_icache_page = r4k_flush_icache_page;
+ __flush_icache_page = r4k_flush_icache_page;
flush_cache_range = r4k_flush_cache_range;
flush_cache_sigtramp = r4k_flush_cache_sigtramp;
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2d71efb82ac..16bad7c0a63 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -155,6 +155,26 @@ static inline void __sb1_flush_icache_all(void)
}
/*
+ * Invalidate a range of the icache. The addresses are virtual, and
+ * the cache is virtually indexed and tagged. However, we don't
+ * necessarily have the right ASID context, so use index ops instead
+ * of hit ops.
+ */
+static inline void __sb1_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+ start &= ~(icache_line_size - 1);
+ end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
+
+ while (start != end) {
+ cache_set_op(Index_Invalidate_I, start & icache_index_mask);
+ start += icache_line_size;
+ }
+ mispredict();
+ sync();
+}
+
+/*
* Flush the icache for a given physical page. Need to writeback the
* dcache first, then invalidate the icache. If the page isn't
* executable, nothing is required.
@@ -173,8 +193,11 @@ static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long
/*
* Bumping the ASID is probably cheaper than the flush ...
*/
- if (cpu_context(cpu, vma->vm_mm) != 0)
- drop_mmu_context(vma->vm_mm, cpu);
+ if (vma->vm_mm == current->active_mm) {
+ if (cpu_context(cpu, vma->vm_mm) != 0)
+ drop_mmu_context(vma->vm_mm, cpu);
+ } else
+ __sb1_flush_icache_range(addr, addr + PAGE_SIZE);
}
#ifdef CONFIG_SMP
@@ -210,26 +233,6 @@ void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsign
__attribute__((alias("local_sb1_flush_cache_page")));
#endif
-/*
- * Invalidate a range of the icache. The addresses are virtual, and
- * the cache is virtually indexed and tagged. However, we don't
- * necessarily have the right ASID context, so use index ops instead
- * of hit ops.
- */
-static inline void __sb1_flush_icache_range(unsigned long start,
- unsigned long end)
-{
- start &= ~(icache_line_size - 1);
- end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
-
- while (start != end) {
- cache_set_op(Index_Invalidate_I, start & icache_index_mask);
- start += icache_line_size;
- }
- mispredict();
- sync();
-}
-
/*
* Invalidate all caches on this CPU
@@ -326,9 +329,12 @@ static void local_sb1_flush_icache_page(struct vm_area_struct *vma,
* If there's a context, bump the ASID (cheaper than a flush,
* since we don't know VAs!)
*/
- if (cpu_context(cpu, vma->vm_mm) != 0) {
- drop_mmu_context(vma->vm_mm, cpu);
- }
+ if (vma->vm_mm == current->active_mm) {
+ if (cpu_context(cpu, vma->vm_mm) != 0)
+ drop_mmu_context(vma->vm_mm, cpu);
+ } else
+ __sb1_flush_icache_range(start, start + PAGE_SIZE);
+
}
#ifdef CONFIG_SMP
@@ -520,7 +526,7 @@ void sb1_cache_init(void)
/* These routines are for Icache coherence with the Dcache */
flush_icache_range = sb1_flush_icache_range;
- flush_icache_page = sb1_flush_icache_page;
+ __flush_icache_page = sb1_flush_icache_page;
flush_icache_all = __sb1_flush_icache_all; /* local only */
/* This implies an Icache flush too, so can't be nop'ed */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index 5dfc9b1901f..932a09d7ef8 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -382,7 +382,7 @@ void __init tx39_cache_init(void)
flush_cache_mm = (void *) tx39h_flush_icache_all;
flush_cache_range = (void *) tx39h_flush_icache_all;
flush_cache_page = (void *) tx39h_flush_icache_all;
- flush_icache_page = (void *) tx39h_flush_icache_all;
+ __flush_icache_page = (void *) tx39h_flush_icache_all;
flush_icache_range = (void *) tx39h_flush_icache_all;
flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
@@ -408,7 +408,7 @@ void __init tx39_cache_init(void)
flush_cache_mm = tx39_flush_cache_mm;
flush_cache_range = tx39_flush_cache_range;
flush_cache_page = tx39_flush_cache_page;
- flush_icache_page = tx39_flush_icache_page;
+ __flush_icache_page = tx39_flush_icache_page;
flush_icache_range = tx39_flush_icache_range;
flush_cache_sigtramp = tx39_flush_cache_sigtramp;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index ddd3a2de1d7..40c8b023518 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -25,7 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
unsigned long pfn);
void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
@@ -70,6 +70,8 @@ void __flush_dcache_page(struct page *page)
struct address_space *mapping = page_mapping(page);
unsigned long addr;
+ if (PageHighMem(page))
+ return;
if (mapping && !mapping_mapped(mapping)) {
SetPageDcacheDirty(page);
return;
@@ -91,16 +93,16 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
{
struct page *page;
unsigned long pfn, addr;
+ int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
pfn = pte_pfn(pte);
- if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) &&
- Page_dcache_dirty(page)) {
- if (pages_do_alias((unsigned long)page_address(page),
- address & PAGE_MASK)) {
- addr = (unsigned long) page_address(page);
+ if (unlikely(!pfn_valid(pfn)))
+ return;
+ page = pfn_to_page(pfn);
+ if (page_mapping(page) && Page_dcache_dirty(page)) {
+ addr = (unsigned long) page_address(page);
+ if (exec || pages_do_alias(addr, address & PAGE_MASK))
flush_data_cache_page(addr);
- }
-
ClearPageDcacheDirty(page);
}
}
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index e3a61722486..a4f8c45c4e8 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -89,7 +89,7 @@ good_area:
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
goto bad_area;
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index c52497bb102..5b06349af2d 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -163,10 +163,10 @@ static int __init page_is_ram(unsigned long pagenr)
void __init paging_init(void)
{
- unsigned long zones_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 };
+ unsigned long zones_size[] = { 0, };
unsigned long max_dma, high, low;
#ifndef CONFIG_FLATMEM
- unsigned long zholes_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 };
+ unsigned long zholes_size[] = { 0, };
unsigned long i, j, pfn;
#endif
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 2cde1b77244..2e0e21ef433 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -26,11 +26,6 @@ extern void build_tlb_refill_handler(void);
*/
#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
-/* CP0 hazard avoidance. */
-#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
- "nop; nop; nop; nop; nop; nop;\n\t" \
- ".set reorder\n\t")
-
/* Atomicity and interruptability */
#ifdef CONFIG_MIPS_MT_SMTC
@@ -126,7 +121,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
start += (PAGE_SIZE << 1);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
idx = read_c0_index();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
@@ -168,7 +163,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
start += (PAGE_SIZE << 1);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
idx = read_c0_index();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
@@ -202,7 +197,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
write_c0_entryhi(page | newpid);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
idx = read_c0_index();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
@@ -235,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
write_c0_entryhi(page);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
idx = read_c0_index();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
@@ -279,7 +274,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
pgdp = pgd_offset(vma->vm_mm, address);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
pudp = pud_offset(pgdp, address);
pmdp = pmd_offset(pudp, address);
idx = read_c0_index();
@@ -320,7 +315,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
pgdp = pgd_offset(vma->vm_mm, address);
mtc0_tlbw_hazard();
tlb_probe();
- BARRIER;
+ tlb_probe_hazard();
pmdp = pmd_offset(pgdp, address);
idx = read_c0_index();
ptep = pte_offset_map(pmdp, address);
@@ -351,7 +346,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
wired = read_c0_wired();
write_c0_wired(wired + 1);
write_c0_index(wired);
- BARRIER;
+ tlbw_use_hazard(); /* What is the hazard here? */
write_c0_pagemask(pagemask);
write_c0_entryhi(entryhi);
write_c0_entrylo0(entrylo0);
@@ -361,7 +356,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- BARRIER;
+ tlbw_use_hazard(); /* What is the hazard here? */
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
EXIT_CRITICAL(flags);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 35d5927706e..edefa97b233 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o
obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o
obj-$(CONFIG_MIPS_GT64111) += ops-gt64111.o
obj-$(CONFIG_MIPS_GT64120) += ops-gt64120.o
-obj-$(CONFIG_MIPS_GT96100) += ops-gt96100.o
obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o
obj-$(CONFIG_MIPS_MSC) += ops-msc.o
obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o
@@ -28,8 +27,7 @@ obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o
-obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o pci-ev96100.o
+obj-$(CONFIG_MIPS_EV64120) += fixup-ev64120.o
obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o
obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index 439510af303..c6cd6e9cdfb 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -21,16 +21,16 @@
#include <asm/mips-boards/atlasint.h>
-#define PCIA ATLASINT_PCIA
-#define PCIB ATLASINT_PCIB
-#define PCIC ATLASINT_PCIC
-#define PCID ATLASINT_PCID
-#define INTA ATLASINT_INTA
-#define INTB ATLASINT_INTB
-#define ETH ATLASINT_ETH
-#define INTC ATLASINT_INTC
-#define SCSI ATLASINT_SCSI
-#define INTD ATLASINT_INTD
+#define PCIA ATLAS_INT_PCIA
+#define PCIB ATLAS_INT_PCIB
+#define PCIC ATLAS_INT_PCIC
+#define PCID ATLAS_INT_PCID
+#define INTA ATLAS_INT_INTA
+#define INTB ATLAS_INT_INTB
+#define ETH ATLAS_INT_ETH
+#define INTC ATLAS_INT_INTC
+#define SCSI ATLAS_INT_SCSI
+#define INTD ATLAS_INT_INTD
static char irq_tab[][5] __initdata = {
/* INTA INTB INTC INTD */
diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c
deleted file mode 100644
index e2bc977b6d5..00000000000
--- a/arch/mips/pci/fixup-ev96100.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * EV96100 Board specific pci fixups.
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-static char irq_tab_ev96100[][5] __initdata = {
- [8] = { 0, 5, 5, 5, 5 },
- [9] = { 0, 2, 2, 2, 2 }
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- return irq_tab_ev96100[slot][pin];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c
index 0c0c1e6519f..8ae46481fcb 100644
--- a/arch/mips/pci/ops-au1000.c
+++ b/arch/mips/pci/ops-au1000.c
@@ -110,7 +110,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
if (first_cfg) {
/* reserve a wired entry for pci config accesses */
first_cfg = 0;
- pci_cfg_vm = get_vm_area(0x2000, 0);
+ pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
if (!pci_cfg_vm)
panic (KERN_ERR "PCI unable to get vm area\n");
pci_cfg_wired_entry = read_c0_wired();
diff --git a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c
deleted file mode 100644
index 9e4ea6627e2..00000000000
--- a/arch/mips/pci/ops-gt96100.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * Galileo EV96100 board specific pci support.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/pci.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
-
-#define PCI_ACCESS_READ 0
-#define PCI_ACCESS_WRITE 1
-
-static int static gt96100_config_access(unsigned char access_type,
- struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
-{
- unsigned char bus = bus->number;
- u32 intr;
-
- /*
- * Because of a bug in the galileo (for slot 31).
- */
- if (bus == 0 && devfn >= PCI_DEVFN(31, 0))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Clear cause register bits */
- GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
- GT_INTRCAUSE_TARABORT0_BIT));
-
- /* Setup address */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
- udelay(2);
-
-
- if (access_type == PCI_ACCESS_WRITE) {
- if (devfn != 0)
- *data = le32_to_cpu(*data);
- GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
- } else {
- *data = GT_READ(GT_PCI0_CFGDATA_OFS);
- if (devfn != 0)
- *data = le32_to_cpu(*data);
- }
-
- udelay(2);
-
- /* Check for master or target abort */
- intr = GT_READ(GT_INTRCAUSE_OFS);
-
- if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
- /* Error occured */
-
- /* Clear bits */
- GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
- GT_INTRCAUSE_TARABORT0_BIT));
- return -1;
- }
- return 0;
-}
-
-/*
- * We can't address 8 and 16 bit words directly. Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 * val)
-{
- u32 data = 0;
-
- if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- switch (size) {
- case 1:
- *val = (data >> ((where & 3) << 3)) & 0xff;
- break;
-
- case 2:
- *val = (data >> ((where & 3) << 3)) & 0xffff;
- break;
-
- case 4:
- *val = data;
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- u32 data = 0;
-
- switch (size) {
- case 1:
- if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
- return -1;
-
- data = (data & ~(0xff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
-
- if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
- return -1;
-
- return PCIBIOS_SUCCESSFUL;
-
- case 2:
- if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
- return -1;
-
- data = (data & ~(0xffff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
-
- if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
- return -1;
-
-
- return PCIBIOS_SUCCESSFUL;
-
- case 4:
- if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
- return -1;
-
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-struct pci_ops gt96100_pci_ops = {
- .read = gt96100_pcibios_read,
- .write = gt96100_pcibios_write
-};
diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c
deleted file mode 100644
index f9457ea00de..00000000000
--- a/arch/mips/pci/pci-ev96100.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-static struct resource pci_io_resource = {
- .name = "io pci IO space",
- .start = 0x10000000,
- .end = 0x11ffffff,
- .flags = IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
- .name = "ext pci memory space",
- .start = 0x12000000,
- .end = 0x13ffffff,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops gt96100_pci_ops;
-
-struct pci_controller ev96100_controller = {
- .pci_ops = &gt96100_pci_ops,
- .io_resource = &pci_io_resource,
- .mem_resource = &pci_mem_resource,
-};
-
-static void ev96100_pci_init(void)
-{
- register_pci_controller(&ev96100_controller);
-}
-
-arch_initcall(ev96100_pci_init);
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 80eb9af9ecd..405ce015273 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -16,8 +16,6 @@
#include <asm/sn/intr.h>
#include <asm/sn/sn0/hub.h>
-extern unsigned int allocate_irqno(void);
-
/*
* Max #PCI busses we can handle; ie, max #PCI bridges.
*/
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index efe6971fc80..16e5682b01f 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -19,6 +19,7 @@
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/pfn.h>
+#include <linux/highmem.h>
#include <asm/page.h>
#include <asm/sections.h>
@@ -508,7 +509,7 @@ extern unsigned long setup_zero_pages(void);
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
unsigned node;
pagetable_init();
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index ed325f0ab28..a0222fa4416 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -469,21 +469,6 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
#endif /* CONFIG_KGDB */
-static inline int dclz(unsigned long long x)
-{
- int lz;
-
- __asm__ (
- " .set push \n"
- " .set mips64 \n"
- " dclz %0, %1 \n"
- " .set pop \n"
- : "=r" (lz)
- : "r" (x));
-
- return lz;
-}
-
extern void bcm1480_timer_interrupt(struct pt_regs *regs);
extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
@@ -536,9 +521,9 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
if (mask_h) {
if (mask_h ^ 1)
- do_IRQ(63 - dclz(mask_h), regs);
+ do_IRQ(fls64(mask_h) - 1, regs);
else
- do_IRQ(127 - dclz(mask_l), regs);
+ do_IRQ(63 + fls64(mask_l), regs);
}
}
}
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 1de71adec6c..a451b4c7732 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -419,21 +419,6 @@ static void sb1250_kgdb_interrupt(struct pt_regs *regs)
#endif /* CONFIG_KGDB */
-static inline int dclz(unsigned long long x)
-{
- int lz;
-
- __asm__ (
- " .set push \n"
- " .set mips64 \n"
- " dclz %0, %1 \n"
- " .set pop \n"
- : "=r" (lz)
- : "r" (x));
-
- return lz;
-}
-
extern void sb1250_timer_interrupt(struct pt_regs *regs);
extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
@@ -490,6 +475,6 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
R_IMR_INTERRUPT_STATUS_BASE)));
if (mask)
- do_IRQ(63 - dclz(mask), regs);
+ do_IRQ(fls64(mask) - 1, regs);
}
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index f2b96f1e0da..25ad28d63e8 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -551,7 +551,7 @@ void show_mem(void)
printk("Zone list for zone %d on node %d: ", j, i);
for (k = 0; zl->zones[k] != NULL; k++)
- printk("[%d/%s] ", zl->zones[k]->zone_pgdat->node_id, zl->zones[k]->name);
+ printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
printk("\n");
}
}
@@ -809,7 +809,7 @@ void __init paging_init(void)
flush_tlb_all_local(NULL);
for (i = 0; i < npmem_ranges; i++) {
- unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 };
+ unsigned long zones_size[MAX_NR_ZONES] = { 0, };
/* We have an IOMMU, so all memory can go into a single
ZONE_DMA zone. */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index de1ef2fa1a2..a0dd1b0ee48 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -731,11 +731,10 @@ config ARCH_SPARSEMEM_DEFAULT
def_bool y
depends on SMP && PPC_PSERIES
-source "mm/Kconfig"
-
-config HAVE_ARCH_EARLY_PFN_TO_NID
+config ARCH_POPULATES_NODE_MAP
def_bool y
- depends on NEED_MULTIPLE_NODES
+
+source "mm/Kconfig"
config ARCH_MEMORY_PROBE
def_bool y
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
index 7369f9a6ad2..69e8f86aa4f 100644
--- a/arch/powerpc/kernel/swsusp_32.S
+++ b/arch/powerpc/kernel/swsusp_32.S
@@ -159,8 +159,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
isync
/* Load ptr the list of pages to copy in r3 */
- lis r11,(pagedir_nosave - KERNELBASE)@h
- ori r11,r11,pagedir_nosave@l
+ lis r11,(restore_pblist - KERNELBASE)@h
+ ori r11,r11,restore_pblist@l
lwz r10,0(r11)
/* Copy the pages. This is a very basic implementation, to
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 2e292863e98..5e391fc2534 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -740,7 +740,7 @@ asmlinkage long compat_sys_umask(u32 mask)
return sys_umask((int)mask);
}
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
struct __sysctl_args32 {
u32 name;
int nlen;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index eebd8b83a6b..16fe027bbc1 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -256,20 +256,22 @@ void __init do_init_bootmem(void)
boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
+ /* Add active regions with valid PFNs */
+ for (i = 0; i < lmb.memory.cnt; i++) {
+ unsigned long start_pfn, end_pfn;
+ start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+ end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+ add_active_range(0, start_pfn, end_pfn);
+ }
+
/* Add all physical memory to the bootmem map, mark each area
* present.
*/
- for (i = 0; i < lmb.memory.cnt; i++) {
- unsigned long base = lmb.memory.region[i].base;
- unsigned long size = lmb_size_bytes(&lmb.memory, i);
#ifdef CONFIG_HIGHMEM
- if (base >= total_lowmem)
- continue;
- if (base + size > total_lowmem)
- size = total_lowmem - base;
+ free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
+#else
+ free_bootmem_with_active_regions(0, max_pfn);
#endif
- free_bootmem(base, size);
- }
/* reserve the sections we're already using */
for (i = 0; i < lmb.reserved.cnt; i++)
@@ -277,9 +279,8 @@ void __init do_init_bootmem(void)
lmb_size_bytes(&lmb.reserved, i));
/* XXX need to clip this if using highmem? */
- for (i = 0; i < lmb.memory.cnt; i++)
- memory_present(0, lmb_start_pfn(&lmb.memory, i),
- lmb_end_pfn(&lmb.memory, i));
+ sparse_memory_present_with_active_regions(0);
+
init_bootmem_done = 1;
}
@@ -288,10 +289,9 @@ void __init do_init_bootmem(void)
*/
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES];
- unsigned long zholes_size[MAX_NR_ZONES];
unsigned long total_ram = lmb_phys_mem_size();
unsigned long top_of_ram = lmb_end_of_DRAM();
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
#ifdef CONFIG_HIGHMEM
map_page(PKMAP_BASE, 0, 0); /* XXX gross */
@@ -307,26 +307,13 @@ void __init paging_init(void)
top_of_ram, total_ram);
printk(KERN_DEBUG "Memory hole size: %ldMB\n",
(top_of_ram - total_ram) >> 20);
- /*
- * All pages are DMA-able so we put them all in the DMA zone.
- */
- memset(zones_size, 0, sizeof(zones_size));
- memset(zholes_size, 0, sizeof(zholes_size));
-
- zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
- zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-
#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
- zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
- zholes_size[ZONE_HIGHMEM] = (top_of_ram - total_ram) >> PAGE_SHIFT;
+ max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+ max_zone_pfns[1] = top_of_ram >> PAGE_SHIFT;
#else
- zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
- zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-#endif /* CONFIG_HIGHMEM */
-
- free_area_init_node(0, NODE_DATA(0), zones_size,
- __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+ max_zone_pfns[0] = top_of_ram >> PAGE_SHIFT;
+#endif
+ free_area_init_nodes(max_zone_pfns);
}
#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 6c0f1c7d83e..43c272075e1 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -39,96 +39,6 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
static int min_common_depth;
static int n_mem_addr_cells, n_mem_size_cells;
-/*
- * We need somewhere to store start/end/node for each region until we have
- * allocated the real node_data structures.
- */
-#define MAX_REGIONS (MAX_LMB_REGIONS*2)
-static struct {
- unsigned long start_pfn;
- unsigned long end_pfn;
- int nid;
-} init_node_data[MAX_REGIONS] __initdata;
-
-int __init early_pfn_to_nid(unsigned long pfn)
-{
- unsigned int i;
-
- for (i = 0; init_node_data[i].end_pfn; i++) {
- unsigned long start_pfn = init_node_data[i].start_pfn;
- unsigned long end_pfn = init_node_data[i].end_pfn;
-
- if ((start_pfn <= pfn) && (pfn < end_pfn))
- return init_node_data[i].nid;
- }
-
- return -1;
-}
-
-void __init add_region(unsigned int nid, unsigned long start_pfn,
- unsigned long pages)
-{
- unsigned int i;
-
- dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n",
- nid, start_pfn, pages);
-
- for (i = 0; init_node_data[i].end_pfn; i++) {
- if (init_node_data[i].nid != nid)
- continue;
- if (init_node_data[i].end_pfn == start_pfn) {
- init_node_data[i].end_pfn += pages;
- return;
- }
- if (init_node_data[i].start_pfn == (start_pfn + pages)) {
- init_node_data[i].start_pfn -= pages;
- return;
- }
- }
-
- /*
- * Leave last entry NULL so we dont iterate off the end (we use
- * entry.end_pfn to terminate the walk).
- */
- if (i >= (MAX_REGIONS - 1)) {
- printk(KERN_ERR "WARNING: too many memory regions in "
- "numa code, truncating\n");
- return;
- }
-
- init_node_data[i].start_pfn = start_pfn;
- init_node_data[i].end_pfn = start_pfn + pages;
- init_node_data[i].nid = nid;
-}
-
-/* We assume init_node_data has no overlapping regions */
-void __init get_region(unsigned int nid, unsigned long *start_pfn,
- unsigned long *end_pfn, unsigned long *pages_present)
-{
- unsigned int i;
-
- *start_pfn = -1UL;
- *end_pfn = *pages_present = 0;
-
- for (i = 0; init_node_data[i].end_pfn; i++) {
- if (init_node_data[i].nid != nid)
- continue;
-
- *pages_present += init_node_data[i].end_pfn -
- init_node_data[i].start_pfn;
-
- if (init_node_data[i].start_pfn < *start_pfn)
- *start_pfn = init_node_data[i].start_pfn;
-
- if (init_node_data[i].end_pfn > *end_pfn)
- *end_pfn = init_node_data[i].end_pfn;
- }
-
- /* We didnt find a matching region, return start/end as 0 */
- if (*start_pfn == -1UL)
- *start_pfn = 0;
-}
-
static void __cpuinit map_cpu_to_node(int cpu, int node)
{
numa_cpu_lookup_table[cpu] = node;
@@ -468,8 +378,8 @@ new_range:
continue;
}
- add_region(nid, start >> PAGE_SHIFT,
- size >> PAGE_SHIFT);
+ add_active_range(nid, start >> PAGE_SHIFT,
+ (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
if (--ranges)
goto new_range;
@@ -482,6 +392,7 @@ static void __init setup_nonnuma(void)
{
unsigned long top_of_ram = lmb_end_of_DRAM();
unsigned long total_ram = lmb_phys_mem_size();
+ unsigned long start_pfn, end_pfn;
unsigned int i;
printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
@@ -489,9 +400,11 @@ static void __init setup_nonnuma(void)
printk(KERN_DEBUG "Memory hole size: %ldMB\n",
(top_of_ram - total_ram) >> 20);
- for (i = 0; i < lmb.memory.cnt; ++i)
- add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT,
- lmb_size_pages(&lmb.memory, i));
+ for (i = 0; i < lmb.memory.cnt; ++i) {
+ start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+ end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+ add_active_range(0, start_pfn, end_pfn);
+ }
node_set_online(0);
}
@@ -630,11 +543,11 @@ void __init do_init_bootmem(void)
(void *)(unsigned long)boot_cpuid);
for_each_online_node(nid) {
- unsigned long start_pfn, end_pfn, pages_present;
+ unsigned long start_pfn, end_pfn;
unsigned long bootmem_paddr;
unsigned long bootmap_pages;
- get_region(nid, &start_pfn, &end_pfn, &pages_present);
+ get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
/* Allocate the node structure node local if possible */
NODE_DATA(nid) = careful_allocation(nid,
@@ -667,19 +580,7 @@ void __init do_init_bootmem(void)
init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
start_pfn, end_pfn);
- /* Add free regions on this node */
- for (i = 0; init_node_data[i].end_pfn; i++) {
- unsigned long start, end;
-
- if (init_node_data[i].nid != nid)
- continue;
-
- start = init_node_data[i].start_pfn << PAGE_SHIFT;
- end = init_node_data[i].end_pfn << PAGE_SHIFT;
-
- dbg("free_bootmem %lx %lx\n", start, end - start);
- free_bootmem_node(NODE_DATA(nid), start, end - start);
- }
+ free_bootmem_with_active_regions(nid, end_pfn);
/* Mark reserved regions on this node */
for (i = 0; i < lmb.reserved.cnt; i++) {
@@ -710,44 +611,16 @@ void __init do_init_bootmem(void)
}
}
- /* Add regions into sparsemem */
- for (i = 0; init_node_data[i].end_pfn; i++) {
- unsigned long start, end;
-
- if (init_node_data[i].nid != nid)
- continue;
-
- start = init_node_data[i].start_pfn;
- end = init_node_data[i].end_pfn;
-
- memory_present(nid, start, end);
- }
+ sparse_memory_present_with_active_regions(nid);
}
}
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES];
- unsigned long zholes_size[MAX_NR_ZONES];
- int nid;
-
- memset(zones_size, 0, sizeof(zones_size));
- memset(zholes_size, 0, sizeof(zholes_size));
-
- for_each_online_node(nid) {
- unsigned long start_pfn, end_pfn, pages_present;
-
- get_region(nid, &start_pfn, &end_pfn, &pages_present);
-
- zones_size[ZONE_DMA] = end_pfn - start_pfn;
- zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present;
-
- dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
- zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
-
- free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn,
- zholes_size);
- }
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+ lmb_end_of_DRAM() >> PAGE_SHIFT
+ };
+ free_area_init_nodes(max_zone_pfns);
}
static int __init early_numa(char *p)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 7b4572805db..3950ddccb2c 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -82,7 +82,6 @@ spufs_new_inode(struct super_block *sb, int mode)
inode->i_mode = mode;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
- inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
out:
@@ -120,7 +119,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
ret = 0;
inode->i_op = &spufs_file_iops;
inode->i_fop = fops;
- inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
+ inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
d_add(dentry, inode);
out:
return ret;
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 641e6511cf0..446e17d162a 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
rc = seq_open(file, &hcall_inst_seq_ops);
seq = file->private_data;
- seq->private = file->f_dentry->d_inode->u.generic_ip;
+ seq->private = file->f_dentry->d_inode->i_private;
return rc;
}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index b604926401f..723972bb5bd 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -339,7 +339,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
- if (id == PCI_CAP_ID_HT_IRQCONF) {
+ if (id == PCI_CAP_ID_HT) {
id = readb(devbase + pos + 3);
if (id == 0x80)
break;
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 8fa10cf661a..fdd9e7b6624 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -953,6 +953,9 @@ config NR_CPUS
config HIGHMEM
bool "High memory support"
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
source "mm/Kconfig"
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 523392d460f..410200046af 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -358,8 +358,8 @@ void __init do_init_bootmem(void)
*/
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES], i;
-
+ unsigned long start_pfn, end_pfn;
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
#ifdef CONFIG_HIGHMEM
map_page(PKMAP_BASE, 0, 0); /* XXX gross */
pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
@@ -369,19 +369,18 @@ void __init paging_init(void)
(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
kmap_prot = PAGE_KERNEL;
#endif /* CONFIG_HIGHMEM */
-
- /*
- * All pages are DMA-able so we put them all in the DMA zone.
- */
- zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
- for (i = 1; i < MAX_NR_ZONES; i++)
- zones_size[i] = 0;
+ /* All pages are DMA-able so we put them all in the DMA zone. */
+ start_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
+ end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
+ add_active_range(0, start_pfn, end_pfn);
#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+ max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+ max_zone_pfns[1] = total_memory >> PAGE_SHIFT;
+#else
+ max_zone_pfns[0] = total_memory >> PAGE_SHIFT;
#endif /* CONFIG_HIGHMEM */
-
- free_area_init(zones_size);
+ free_area_init_nodes(max_zone_pfns);
}
void __init mem_init(void)
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index ab3b0765a64..8aea3698a77 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -117,8 +117,7 @@ static void appldata_get_mem_data(void *data)
mem_data->pgpgout = ev[PGPGOUT] >> 1;
mem_data->pswpin = ev[PSWPIN];
mem_data->pswpout = ev[PSWPOUT];
- mem_data->pgalloc = ev[PGALLOC_HIGH] + ev[PGALLOC_NORMAL] +
- ev[PGALLOC_DMA];
+ mem_data->pgalloc = ev[PGALLOC_NORMAL] + ev[PGALLOC_DMA];
mem_data->pgfault = ev[PGFAULT];
mem_data->pgmajfault = ev[PGMAJFAULT];
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index bdade5f2e32..813fc21358f 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -91,7 +91,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_mode = mode;
ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid;
- ret->i_blksize = PAGE_CACHE_SIZE;
ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
@@ -104,13 +103,13 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
static void hypfs_drop_inode(struct inode *inode)
{
- kfree(inode->u.generic_ip);
+ kfree(inode->i_private);
generic_delete_inode(inode);
}
static int hypfs_open(struct inode *inode, struct file *filp)
{
- char *data = filp->f_dentry->d_inode->u.generic_ip;
+ char *data = filp->f_dentry->d_inode->i_private;
struct hypfs_sb_info *fs_info;
if (filp->f_mode & FMODE_WRITE) {
@@ -352,7 +351,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
parent->d_inode->i_nlink++;
} else
BUG();
- inode->u.generic_ip = data;
+ inode->i_private = data;
d_instantiate(dentry, inode);
dget(dentry);
return dentry;
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 785c9f70ac9..91b2884fa5c 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -708,7 +708,7 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
return ret;
}
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
struct __sysctl_args32 {
u32 name;
int nlen;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 7ba20922a53..43f3d0c7e13 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -603,7 +603,7 @@ debug_open(struct inode *inode, struct file *file)
debug_info_t *debug_info, *debug_info_snapshot;
down(&debug_lock);
- debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
+ debug_info = file->f_dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
if (!debug_info->views[i])
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index de83f38288d..d9428a0fc8f 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -59,9 +59,7 @@ static inline unsigned long save_context_stack(struct stack_trace *trace,
}
}
-void save_stack_trace(struct stack_trace *trace,
- struct task_struct *task, int all_contexts,
- unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
register unsigned long sp asm ("15");
unsigned long orig_sp;
@@ -69,22 +67,23 @@ void save_stack_trace(struct stack_trace *trace,
sp &= PSW_ADDR_INSN;
orig_sp = sp;
- sp = save_context_stack(trace, &skip, sp,
+ sp = save_context_stack(trace, &trace->skip, sp,
S390_lowcore.panic_stack - PAGE_SIZE,
S390_lowcore.panic_stack);
- if ((sp != orig_sp) && !all_contexts)
+ if ((sp != orig_sp) && !trace->all_contexts)
return;
- sp = save_context_stack(trace, &skip, sp,
+ sp = save_context_stack(trace, &trace->skip, sp,
S390_lowcore.async_stack - ASYNC_SIZE,
S390_lowcore.async_stack);
- if ((sp != orig_sp) && !all_contexts)
+ if ((sp != orig_sp) && !trace->all_contexts)
return;
if (task)
- save_context_stack(trace, &skip, sp,
+ save_context_stack(trace, &trace->skip, sp,
(unsigned long) task_stack_page(task),
(unsigned long) task_stack_page(task) + THREAD_SIZE);
else
- save_context_stack(trace, &skip, sp, S390_lowcore.thread_info,
+ save_context_stack(trace, &trace->skip, sp,
+ S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE);
return;
}
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 786a44dba5b..607f50ead1f 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -15,6 +15,8 @@
#include <linux/sched.h>
#include <linux/sysctl.h>
#include <linux/ctype.h>
+#include <linux/swap.h>
+#include <linux/kthread.h>
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
@@ -34,18 +36,18 @@ struct cmm_page_array {
unsigned long pages[CMM_NR_PAGES];
};
-static long cmm_pages = 0;
-static long cmm_timed_pages = 0;
-static volatile long cmm_pages_target = 0;
-static volatile long cmm_timed_pages_target = 0;
-static long cmm_timeout_pages = 0;
-static long cmm_timeout_seconds = 0;
+static long cmm_pages;
+static long cmm_timed_pages;
+static volatile long cmm_pages_target;
+static volatile long cmm_timed_pages_target;
+static long cmm_timeout_pages;
+static long cmm_timeout_seconds;
-static struct cmm_page_array *cmm_page_list = NULL;
-static struct cmm_page_array *cmm_timed_page_list = NULL;
+static struct cmm_page_array *cmm_page_list;
+static struct cmm_page_array *cmm_timed_page_list;
+static DEFINE_SPINLOCK(cmm_lock);
-static unsigned long cmm_thread_active = 0;
-static struct work_struct cmm_thread_starter;
+static struct task_struct *cmm_thread_ptr;
static wait_queue_head_t cmm_thread_wait;
static struct timer_list cmm_timer;
@@ -53,71 +55,100 @@ static void cmm_timer_fn(unsigned long);
static void cmm_set_timer(void);
static long
-cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list)
+cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list)
{
- struct cmm_page_array *pa;
- unsigned long page;
+ struct cmm_page_array *pa, *npa;
+ unsigned long addr;
- pa = *list;
- while (pages) {
- page = __get_free_page(GFP_NOIO);
- if (!page)
+ while (nr) {
+ addr = __get_free_page(GFP_NOIO);
+ if (!addr)
break;
+ spin_lock(&cmm_lock);
+ pa = *list;
if (!pa || pa->index >= CMM_NR_PAGES) {
/* Need a new page for the page list. */
- pa = (struct cmm_page_array *)
+ spin_unlock(&cmm_lock);
+ npa = (struct cmm_page_array *)
__get_free_page(GFP_NOIO);
- if (!pa) {
- free_page(page);
+ if (!npa) {
+ free_page(addr);
break;
}
- pa->next = *list;
- pa->index = 0;
- *list = pa;
+ spin_lock(&cmm_lock);
+ pa = *list;
+ if (!pa || pa->index >= CMM_NR_PAGES) {
+ npa->next = pa;
+ npa->index = 0;
+ pa = npa;
+ *list = pa;
+ } else
+ free_page((unsigned long) npa);
}
- diag10(page);
- pa->pages[pa->index++] = page;
+ diag10(addr);
+ pa->pages[pa->index++] = addr;
(*counter)++;
- pages--;
+ spin_unlock(&cmm_lock);
+ nr--;
}
- return pages;
+ return nr;
}
-static void
-cmm_free_pages(long pages, long *counter, struct cmm_page_array **list)
+static long
+cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{
struct cmm_page_array *pa;
- unsigned long page;
+ unsigned long addr;
+ spin_lock(&cmm_lock);
pa = *list;
- while (pages) {
+ while (nr) {
if (!pa || pa->index <= 0)
break;
- page = pa->pages[--pa->index];
+ addr = pa->pages[--pa->index];
if (pa->index == 0) {
pa = pa->next;
free_page((unsigned long) *list);
*list = pa;
}
- free_page(page);
+ free_page(addr);
(*counter)--;
- pages--;
+ nr--;
}
+ spin_unlock(&cmm_lock);
+ return nr;
}
+static int cmm_oom_notify(struct notifier_block *self,
+ unsigned long dummy, void *parm)
+{
+ unsigned long *freed = parm;
+ long nr = 256;
+
+ nr = cmm_free_pages(nr, &cmm_timed_pages, &cmm_timed_page_list);
+ if (nr > 0)
+ nr = cmm_free_pages(nr, &cmm_pages, &cmm_page_list);
+ cmm_pages_target = cmm_pages;
+ cmm_timed_pages_target = cmm_timed_pages;
+ *freed += 256 - nr;
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cmm_oom_nb = {
+ .notifier_call = cmm_oom_notify
+};
+
static int
cmm_thread(void *dummy)
{
int rc;
- daemonize("cmmthread");
while (1) {
rc = wait_event_interruptible(cmm_thread_wait,
(cmm_pages != cmm_pages_target ||
- cmm_timed_pages != cmm_timed_pages_target));
- if (rc == -ERESTARTSYS) {
- /* Got kill signal. End thread. */
- clear_bit(0, &cmm_thread_active);
+ cmm_timed_pages != cmm_timed_pages_target ||
+ kthread_should_stop()));
+ if (kthread_should_stop() || rc == -ERESTARTSYS) {
cmm_pages_target = cmm_pages;
cmm_timed_pages_target = cmm_timed_pages;
break;
@@ -143,16 +174,8 @@ cmm_thread(void *dummy)
}
static void
-cmm_start_thread(void)
-{
- kernel_thread(cmm_thread, NULL, 0);
-}
-
-static void
cmm_kick_thread(void)
{
- if (!test_and_set_bit(0, &cmm_thread_active))
- schedule_work(&cmm_thread_starter);
wake_up(&cmm_thread_wait);
}
@@ -177,21 +200,21 @@ cmm_set_timer(void)
static void
cmm_timer_fn(unsigned long ignored)
{
- long pages;
+ long nr;
- pages = cmm_timed_pages_target - cmm_timeout_pages;
- if (pages < 0)
+ nr = cmm_timed_pages_target - cmm_timeout_pages;
+ if (nr < 0)
cmm_timed_pages_target = 0;
else
- cmm_timed_pages_target = pages;
+ cmm_timed_pages_target = nr;
cmm_kick_thread();
cmm_set_timer();
}
void
-cmm_set_pages(long pages)
+cmm_set_pages(long nr)
{
- cmm_pages_target = pages;
+ cmm_pages_target = nr;
cmm_kick_thread();
}
@@ -202,9 +225,9 @@ cmm_get_pages(void)
}
void
-cmm_add_timed_pages(long pages)
+cmm_add_timed_pages(long nr)
{
- cmm_timed_pages_target += pages;
+ cmm_timed_pages_target += nr;
cmm_kick_thread();
}
@@ -215,9 +238,9 @@ cmm_get_timed_pages(void)
}
void
-cmm_set_timeout(long pages, long seconds)
+cmm_set_timeout(long nr, long seconds)
{
- cmm_timeout_pages = pages;
+ cmm_timeout_pages = nr;
cmm_timeout_seconds = seconds;
cmm_set_timer();
}
@@ -245,7 +268,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[16], *p;
- long pages;
+ long nr;
int len;
if (!*lenp || (*ppos && !write)) {
@@ -260,17 +283,17 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
cmm_skip_blanks(buf, &p);
- pages = simple_strtoul(p, &p, 0);
+ nr = simple_strtoul(p, &p, 0);
if (ctl == &cmm_table[0])
- cmm_set_pages(pages);
+ cmm_set_pages(nr);
else
- cmm_add_timed_pages(pages);
+ cmm_add_timed_pages(nr);
} else {
if (ctl == &cmm_table[0])
- pages = cmm_get_pages();
+ nr = cmm_get_pages();
else
- pages = cmm_get_timed_pages();
- len = sprintf(buf, "%ld\n", pages);
+ nr = cmm_get_timed_pages();
+ len = sprintf(buf, "%ld\n", nr);
if (len > *lenp)
len = *lenp;
if (copy_to_user(buffer, buf, len))
@@ -286,7 +309,7 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[64], *p;
- long pages, seconds;
+ long nr, seconds;
int len;
if (!*lenp || (*ppos && !write)) {
@@ -301,10 +324,10 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
cmm_skip_blanks(buf, &p);
- pages = simple_strtoul(p, &p, 0);
+ nr = simple_strtoul(p, &p, 0);
cmm_skip_blanks(p, &p);
seconds = simple_strtoul(p, &p, 0);
- cmm_set_timeout(pages, seconds);
+ cmm_set_timeout(nr, seconds);
} else {
len = sprintf(buf, "%ld %ld\n",
cmm_timeout_pages, cmm_timeout_seconds);
@@ -357,7 +380,7 @@ static struct ctl_table cmm_dir_table[] = {
static void
cmm_smsg_target(char *from, char *msg)
{
- long pages, seconds;
+ long nr, seconds;
if (strlen(sender) > 0 && strcmp(from, sender) != 0)
return;
@@ -366,27 +389,27 @@ cmm_smsg_target(char *from, char *msg)
if (strncmp(msg, "SHRINK", 6) == 0) {
if (!cmm_skip_blanks(msg + 6, &msg))
return;
- pages = simple_strtoul(msg, &msg, 0);
+ nr = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_set_pages(pages);
+ cmm_set_pages(nr);
} else if (strncmp(msg, "RELEASE", 7) == 0) {
if (!cmm_skip_blanks(msg + 7, &msg))
return;
- pages = simple_strtoul(msg, &msg, 0);
+ nr = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_add_timed_pages(pages);
+ cmm_add_timed_pages(nr);
} else if (strncmp(msg, "REUSE", 5) == 0) {
if (!cmm_skip_blanks(msg + 5, &msg))
return;
- pages = simple_strtoul(msg, &msg, 0);
+ nr = simple_strtoul(msg, &msg, 0);
if (!cmm_skip_blanks(msg, &msg))
return;
seconds = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_set_timeout(pages, seconds);
+ cmm_set_timeout(nr, seconds);
}
}
#endif
@@ -396,21 +419,49 @@ struct ctl_table_header *cmm_sysctl_header;
static int
cmm_init (void)
{
+ int rc = -ENOMEM;
+
#ifdef CONFIG_CMM_PROC
cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
+ if (!cmm_sysctl_header)
+ goto out;
#endif
#ifdef CONFIG_CMM_IUCV
- smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
+ rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
+ if (rc < 0)
+ goto out_smsg;
#endif
- INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL);
+ rc = register_oom_notifier(&cmm_oom_nb);
+ if (rc < 0)
+ goto out_oom_notify;
init_waitqueue_head(&cmm_thread_wait);
init_timer(&cmm_timer);
- return 0;
+ cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+ rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
+ if (!rc)
+ goto out;
+ /*
+ * kthread_create failed. undo all the stuff from above again.
+ */
+ unregister_oom_notifier(&cmm_oom_nb);
+
+out_oom_notify:
+#ifdef CONFIG_CMM_IUCV
+ smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
+out_smsg:
+#endif
+#ifdef CONFIG_CMM_PROC
+ unregister_sysctl_table(cmm_sysctl_header);
+#endif
+out:
+ return rc;
}
static void
cmm_exit(void)
{
+ kthread_stop(cmm_thread_ptr);
+ unregister_oom_notifier(&cmm_oom_nb);
cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
#ifdef CONFIG_CMM_PROC
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 1a0db1d4c95..1cc5c9b27bf 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
config SUPERH
bool
default y
+ select EMBEDDED
help
The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast
@@ -51,18 +52,23 @@ source "init/Kconfig"
menu "System type"
+config SOLUTION_ENGINE
+ bool
+
choice
prompt "SuperH system type"
default SH_UNKNOWN
config SH_SOLUTION_ENGINE
bool "SolutionEngine"
+ select SOLUTION_ENGINE
help
Select SolutionEngine if configuring for a Hitachi SH7709
or SH7750 evaluation board.
config SH_7751_SOLUTION_ENGINE
bool "SolutionEngine7751"
+ select SOLUTION_ENGINE
select CPU_SUBTYPE_SH7751
help
Select 7751 SolutionEngine if configuring for a Hitachi SH7751
@@ -70,17 +76,27 @@ config SH_7751_SOLUTION_ENGINE
config SH_7300_SOLUTION_ENGINE
bool "SolutionEngine7300"
+ select SOLUTION_ENGINE
select CPU_SUBTYPE_SH7300
help
- Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
- evaluation board.
+ Select 7300 SolutionEngine if configuring for a Hitachi
+ SH7300(SH-Mobile V) evaluation board.
+
+config SH_7343_SOLUTION_ENGINE
+ bool "SolutionEngine7343"
+ select SOLUTION_ENGINE
+ select CPU_SUBTYPE_SH7343
+ help
+ Select 7343 SolutionEngine if configuring for a Hitachi
+ SH7343 (SH-Mobile 3AS) evaluation board.
config SH_73180_SOLUTION_ENGINE
bool "SolutionEngine73180"
- select CPU_SUBTYPE_SH73180
- help
- Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
- evaluation board.
+ select SOLUTION_ENGINE
+ select CPU_SUBTYPE_SH73180
+ help
+ Select 73180 SolutionEngine if configuring for a Hitachi
+ SH73180(SH-Mobile 3) evaluation board.
config SH_7751_SYSTEMH
bool "SystemH7751R"
@@ -89,12 +105,6 @@ config SH_7751_SYSTEMH
Select SystemH if you are configuring for a Renesas SystemH
7751R evaluation board.
-config SH_STB1_HARP
- bool "STB1_Harp"
-
-config SH_STB1_OVERDRIVE
- bool "STB1_Overdrive"
-
config SH_HP6XX
bool "HP6XX"
help
@@ -102,19 +112,6 @@ config SH_HP6XX
More information (hardware only) at
<http://www.hp.com/jornada/>.
-config SH_CQREEK
- bool "CqREEK"
- help
- Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
- More information at
- <http://sources.redhat.com/ecos/hardware.html#SuperH>.
-
-config SH_DMIDA
- bool "DMIDA"
- help
- Select DMIDA if configuring for a DataMyte 4000 Industrial
- Digital Assistant. More information at <http://www.dmida.com/>.
-
config SH_EC3104
bool "EC3104"
help
@@ -136,25 +133,9 @@ config SH_DREAMCAST
<http://www.m17n.org/linux-sh/dreamcast/>. There is a
Dreamcast project is at <http://linuxdc.sourceforge.net/>.
-config SH_CAT68701
- bool "CAT68701"
-
config SH_BIGSUR
bool "BigSur"
-config SH_SH2000
- bool "SH2000"
- select CPU_SUBTYPE_SH7709
- help
- SH-2000 is a single-board computer based around SH7709A chip
- intended for embedded applications.
- It has an Ethernet interface (CS8900A), direct connected
- Compact Flash socket, three serial ports and PC-104 bus.
- More information at <http://sh2000.sh-linux.org>.
-
-config SH_ADX
- bool "ADX"
-
config SH_MPC1211
bool "Interface MPC1211"
help
@@ -184,6 +165,13 @@ config SH_HS7751RVOIP
Select HS7751RVOIP if configuring for a Renesas Technology
Sales VoIP board.
+config SH_7710VOIPGW
+ bool "SH7710-VOIP-GW"
+ select CPU_SUBTYPE_SH7710
+ help
+ Select this option to build a kernel for the SH7710 based
+ VOIP GW.
+
config SH_RTS7751R2D
bool "RTS7751R2D"
select CPU_SUBTYPE_SH7751R
@@ -222,6 +210,12 @@ config SH_TITAN
Select Titan if you are configuring for a Nimble Microsystems
NetEngine NP51R.
+config SH_SHMIN
+ bool "SHMIN"
+ select CPU_SUBTYPE_SH7706
+ help
+ Select SHMIN if configureing for the SHMIN board
+
config SH_UNKNOWN
bool "BareCPU"
help
@@ -238,35 +232,9 @@ endchoice
source "arch/sh/mm/Kconfig"
-config MEMORY_START
- hex "Physical memory start address"
- default "0x08000000"
- ---help---
- Computers built with Hitachi SuperH processors always
- map the ROM starting at address zero. But the processor
- does not specify the range that RAM takes.
-
- The physical memory (RAM) start address will be automatically
- set to 08000000. Other platforms, such as the Solution Engine
- boards typically map RAM at 0C000000.
-
- Tweak this only when porting to a new machine which does not
- already have a defconfig. Changing it from the known correct
- value on any of the known systems will only lead to disaster.
-
-config MEMORY_SIZE
- hex "Physical memory size"
- default "0x00400000"
- help
- This sets the default memory size assumed by your SH kernel. It can
- be overridden as normal by the 'mem=' argument on the kernel command
- line. If unsure, consult your board specifications or just leave it
- as 0x00400000 which was the default value before this became
- configurable.
-
config CF_ENABLER
bool "Compact Flash Enabler support"
- depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
+ depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
---help---
Compact Flash is a small, removable mass storage device introduced
in 1994 originally as a PCMCIA device. If you say `Y' here, you
@@ -294,7 +262,7 @@ config CF_AREA5
- "Area5" if CompactFlash is connected to Area 5 (0x14000000)
- "Area6" if it is connected to Area 6 (0x18000000)
- "Area6" will work for most boards. For ADX, select "Area5".
+ "Area6" will work for most boards.
config CF_AREA6
bool "Area6"
@@ -316,19 +284,6 @@ config CPU_LITTLE_ENDIAN
endian byte order. These modes require different kernels. Say Y if
your machine is little endian, N if it's a big endian machine.
-# The SH7750 RTC module is disabled in the Dreamcast
-config SH_RTC
- bool
- depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \
- !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \
- !SH_R7780RP
- default y
- help
- Selecting this option will allow the Linux kernel to emulate
- PC's RTC.
-
- If unsure, say N.
-
config SH_FPU
bool "FPU support"
depends on !CPU_SH3
@@ -339,14 +294,22 @@ config SH_FPU
This option must be set in order to enable the FPU.
+config SH_FPU_EMU
+ bool "FPU emulation support"
+ depends on !SH_FPU && EXPERIMENTAL
+ default n
+ help
+ Selecting this option will enable support for software FPU emulation.
+ Most SH-3 users will want to say Y here, whereas most SH-4 users will
+ want to say N.
+
config SH_DSP
bool "DSP support"
- depends on !CPU_SH4
- default y
+ default y if SH4AL_DSP || !CPU_SH4
+ default n
help
Selecting this option will enable support for SH processors that
- have DSP units (ie, SH2-DSP and SH3-DSP). It is safe to say Y here
- by default, as the existance of the DSP will be probed at runtime.
+ have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP).
This option must be set in order to enable the DSP.
@@ -373,6 +336,9 @@ config CPU_HAS_INTEVT
config CPU_HAS_PINT_IRQ
bool
+config CPU_HAS_MASKREG_IRQ
+ bool
+
config CPU_HAS_INTC2_IRQ
bool
@@ -400,16 +366,19 @@ config SH_TMU
endmenu
-#source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
-#source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
config SH_PCLK_FREQ
int "Peripheral clock frequency (in Hz)"
default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
default "60000000" if CPU_SUBTYPE_SH7751
- default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
- default "27000000" if CPU_SUBTYPE_SH73180
+ default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
+ CPU_SUBTYPE_SH7760
+ default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
default "66000000" if CPU_SUBTYPE_SH4_202
help
This option is used to specify the peripheral clock frequency.
@@ -440,10 +409,8 @@ source "arch/sh/cchips/Kconfig"
config HEARTBEAT
bool "Heartbeat LED"
- depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \
- SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \
- SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
- SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
+ depends on SH_MPC1211 || SH_SH03 || \
+ SH_BIGSUR || SOLUTION_ENGINE || \
SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
help
Use the power-on LED on your machine as a load meter. The exact
@@ -459,6 +426,8 @@ config ISA_DMA_API
menu "Kernel features"
+source kernel/Kconfig.hz
+
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on EXPERIMENTAL
@@ -476,10 +445,6 @@ config KEXEC
support. As of this writing the exact hardware interface is
strongly in flux, so no good recommendation can be made.
-config PREEMPT
- bool "Preemptible Kernel (EXPERIMENTAL)"
- depends on EXPERIMENTAL
-
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -515,6 +480,8 @@ config NR_CPUS
This is purely to save memory - each supported CPU adds
approximately eight kilobytes to the kernel image.
+source "kernel/Kconfig.preempt"
+
config CPU_HAS_SR_RB
bool "CPU has SR.RB"
depends on CPU_SH3 || CPU_SH4
@@ -636,6 +603,16 @@ source "fs/Kconfig.binfmt"
endmenu
+menu "Power management options (EXPERIMENTAL)"
+depends on EXPERIMENTAL
+
+source kernel/power/Kconfig
+
+config APM
+ bool "Advanced Power Management Emulation"
+ depends on PM
+endmenu
+
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 8fb31ab2c02..48479e014da 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -30,8 +30,35 @@ config EARLY_PRINTK
when the kernel may crash or hang before the serial console is
initialised. If unsure, say N.
+config DEBUG_STACKOVERFLOW
+ bool "Check for stack overflows"
+ depends on DEBUG_KERNEL
+ help
+ This option will cause messages to be printed if free stack space
+ drops below a certain limit.
+
+config DEBUG_STACK_USAGE
+ bool "Stack utilization instrumentation"
+ depends on DEBUG_KERNEL
+ help
+ Enables the display of the minimum amount of free stack which each
+ task has ever had available in the sysrq-T and sysrq-P debug output.
+
+ This option will slow down process creation somewhat.
+
+config 4KSTACKS
+ bool "Use 4Kb for kernel stacks instead of 8Kb"
+ depends on DEBUG_KERNEL
+ help
+ If you say Y here the kernel will use a 4Kb stacksize for the
+ kernel stack attached to each process/thread. This facilitates
+ running more threads on a system and also reduces the pressure
+ on the VM subsystem for higher order allocations. This option
+ will also use IRQ stacks to compensate for the reduced stackspace.
+
config KGDB
bool "Include KGDB kernel debugger"
+ select FRAME_POINTER
help
Include in-kernel hooks for kgdb, the Linux kernel source level
debugger. See <http://kgdb.sourceforge.net/> for more information.
@@ -112,13 +139,4 @@ endchoice
endmenu
-config FRAME_POINTER
- bool "Compile the kernel with frame pointers"
- default y if KGDB
- help
- If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
-
endmenu
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index e467a450662..26d62ff51a6 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -18,11 +18,13 @@ cflags-y := -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
isa-y := any
+isa-$(CONFIG_SH_DSP) := sh
isa-$(CONFIG_CPU_SH2) := sh2
+isa-$(CONFIG_CPU_SH2A) := sh2a
isa-$(CONFIG_CPU_SH3) := sh3
isa-$(CONFIG_CPU_SH4) := sh4
isa-$(CONFIG_CPU_SH4A) := sh4a
-isa-$(CONFIG_CPU_SH2A) := sh2a
+isa-$(CONFIG_CPU_SH4AL_DSP) := sh4al
isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp
@@ -30,9 +32,11 @@ ifndef CONFIG_MMU
isa-y := $(isa-y)-nommu
endif
+ifndef CONFIG_SH_DSP
ifndef CONFIG_SH_FPU
isa-y := $(isa-y)-nofpu
endif
+endif
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
@@ -79,24 +83,19 @@ head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
core-y += arch/sh/kernel/ arch/sh/mm/
+core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
# Boards
machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x
machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751
machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300
+machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) := se/7343
machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180
-machdir-$(CONFIG_SH_STB1_HARP) := harp
-machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive
machdir-$(CONFIG_SH_HP6XX) := hp6xx
-machdir-$(CONFIG_SH_CQREEK) := cqreek
-machdir-$(CONFIG_SH_DMIDA) := dmida
machdir-$(CONFIG_SH_EC3104) := ec3104
machdir-$(CONFIG_SH_SATURN) := saturn
machdir-$(CONFIG_SH_DREAMCAST) := dreamcast
-machdir-$(CONFIG_SH_CAT68701) := cat68701
machdir-$(CONFIG_SH_BIGSUR) := bigsur
-machdir-$(CONFIG_SH_SH2000) := sh2000
-machdir-$(CONFIG_SH_ADX) := adx
machdir-$(CONFIG_SH_MPC1211) := mpc1211
machdir-$(CONFIG_SH_SH03) := sh03
machdir-$(CONFIG_SH_SECUREEDGE5410) := snapgear
@@ -104,16 +103,16 @@ machdir-$(CONFIG_SH_HS7751RVOIP) := renesas/hs7751rvoip
machdir-$(CONFIG_SH_RTS7751R2D) := renesas/rts7751r2d
machdir-$(CONFIG_SH_7751_SYSTEMH) := renesas/systemh
machdir-$(CONFIG_SH_EDOSK7705) := renesas/edosk7705
+machdir-$(CONFIG_SH_R7780RP) := renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW) := renesas/sh7710voipgw
machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
+machdir-$(CONFIG_SH_LANDISK) := landisk
+machdir-$(CONFIG_SH_TITAN) := titan
+machdir-$(CONFIG_SH_SHMIN) := shmin
machdir-$(CONFIG_SH_UNKNOWN) := unknown
incdir-y := $(notdir $(machdir-y))
-
-incdir-$(CONFIG_SH_SOLUTION_ENGINE) := se
-incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se7751
-incdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se7300
-incdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se73180
-incdir-$(CONFIG_SH_HP600) := hp6xx
+incdir-$(CONFIG_SH_HP6XX) := hp6xx
ifneq ($(machdir-y),)
core-y += arch/sh/boards/$(machdir-y)/
@@ -137,17 +136,14 @@ boot := arch/sh/boot
CPPFLAGS_vmlinux.lds := -traditional
-ifneq ($(KBUILD_SRC),)
incdir-prefix := $(srctree)/include/asm-sh/
-else
-incdir-prefix :=
-endif
# Update machine arch and proc symlinks if something which affects
# them changed. We use .arch and .mach to indicate when they were
# updated last, otherwise make uses the target directory mtime.
-include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) \
+ include/config/auto.conf FORCE
@echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
$(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@@ -157,7 +153,8 @@ include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
# don't, just reference the parent directory so the semantics are
# kept roughly the same.
-include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
+ include/config/auto.conf FORCE
@echo -n ' SYMLINK include/asm-sh/mach -> '
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
$(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
@@ -170,7 +167,7 @@ include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
fi
@touch $@
-archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
PHONY += maketools FORCE
maketools: include/linux/version.h FORCE
@@ -191,4 +188,3 @@ CLEAN_FILES += include/asm-sh/machtypes.h
define archhelp
@echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)'
endef
-
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile
deleted file mode 100644
index 5b1c531b399..00000000000
--- a/arch/sh/boards/adx/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for ADX boards
-#
-
-obj-y := setup.o irq.o irq_maskreq.o
-
diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c
deleted file mode 100644
index c6ca409dff9..00000000000
--- a/arch/sh/boards/adx/irq.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/arch/sh/boards/adx/irq.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <asm/irq.h>
-
-void init_adx_IRQ(void)
-{
- int i;
-
-/* printk("init_adx_IRQ()\n");*/
- /* setup irq_mask_register */
- irq_mask_register = (unsigned short *)0xa6000008;
-
- /* cover all external interrupt area by maskreg_irq_type
- * (Actually, irq15 doesn't exist)
- */
- for (i = 0; i < 16; i++) {
- make_maskreg_irq(i);
- disable_irq(i);
- }
-}
diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c
deleted file mode 100644
index 4938d959234..00000000000
--- a/arch/sh/boards/adx/setup.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/arch/sh/board/adx/setup.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <asm/machvec.h>
-#include <linux/module.h>
-
-extern void init_adx_IRQ(void);
-extern void *cf_io_base;
-
-const char *get_system_type(void)
-{
- return "A&D ADX";
-}
-
-unsigned long adx_isa_port2addr(unsigned long offset)
-{
- /* CompactFlash (IDE) */
- if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) {
- return (unsigned long)cf_io_base + offset;
- }
-
- /* eth0 */
- if ((offset >= 0x300) && (offset <= 0x30f)) {
- return 0xa5000000 + offset; /* COMM BOARD (AREA1) */
- }
-
- return offset + 0xb0000000; /* IOBUS (AREA 4)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_adx __initmv = {
- .mv_nr_irqs = 48,
- .mv_isa_port2addr = adx_isa_port2addr,
- .mv_init_irq = init_adx_IRQ,
-};
-ALIAS_MV(adx)
-
-int __init platform_setup(void)
-{
- /* Nothing to see here .. */
- return 0;
-}
-
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
index ac946a2201c..1ab04da3638 100644
--- a/arch/sh/boards/bigsur/irq.c
+++ b/arch/sh/boards/bigsur/irq.c
@@ -19,6 +19,7 @@
* IRQ functions for a Hitachi Big Sur Evaluation Board.
*
*/
+#undef DEBUG
#include <linux/sched.h>
#include <linux/module.h>
@@ -41,10 +42,8 @@
#undef BIGSUR_DEBUG
#ifdef BIGSUR_DEBUG
-#define DPRINTK(args...) printk(args)
#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args)
#else
-#define DPRINTK(args...)
#define DIPRINTK(n, args...)
#endif /* BIGSUR_DEBUG */
@@ -60,45 +59,39 @@ extern int hd64465_irq_demux(int irq);
/* Level 1 IRQ routines */
static void disable_bigsur_l1irq(unsigned int irq)
{
- unsigned long flags;
unsigned char mask;
unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
- DPRINTK("Disable L1 IRQ %d\n", irq);
+ pr_debug("Disable L1 IRQ %d\n", irq);
DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
mask_port, bit);
- local_irq_save(flags);
/* Disable IRQ - set mask bit */
mask = inb(mask_port) | bit;
outb(mask, mask_port);
- local_irq_restore(flags);
return;
}
- DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+ pr_debug("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
}
static void enable_bigsur_l1irq(unsigned int irq)
{
- unsigned long flags;
unsigned char mask;
unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
- DPRINTK("Enable L1 IRQ %d\n", irq);
+ pr_debug("Enable L1 IRQ %d\n", irq);
DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
mask_port, bit);
- local_irq_save(flags);
/* Enable L1 IRQ - clear mask bit */
mask = inb(mask_port) & ~bit;
outb(mask, mask_port);
- local_irq_restore(flags);
return;
}
- DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+ pr_debug("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
}
@@ -126,51 +119,45 @@ static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
/* Level 2 IRQ routines */
static void disable_bigsur_l2irq(unsigned int irq)
{
- unsigned long flags;
unsigned char mask;
unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
- if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
- DPRINTK("Disable L2 IRQ %d\n", irq);
+ if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+ pr_debug("Disable L2 IRQ %d\n", irq);
DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
mask_port, bit);
- local_irq_save(flags);
/* Disable L2 IRQ - set mask bit */
mask = inb(mask_port) | bit;
outb(mask, mask_port);
- local_irq_restore(flags);
return;
}
- DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+ pr_debug("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
}
static void enable_bigsur_l2irq(unsigned int irq)
{
- unsigned long flags;
unsigned char mask;
unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
- if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
- DPRINTK("Enable L2 IRQ %d\n", irq);
+ if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+ pr_debug("Enable L2 IRQ %d\n", irq);
DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
mask_port, bit);
- local_irq_save(flags);
/* Enable L2 IRQ - clear mask bit */
mask = inb(mask_port) & ~bit;
outb(mask, mask_port);
- local_irq_restore(flags);
return;
}
- DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+ pr_debug("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
}
static void mask_and_ack_bigsur(unsigned int irq)
{
- DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq);
+ pr_debug("mask_and_ack_bigsur IRQ %d\n", irq);
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
disable_bigsur_l1irq(irq);
else
@@ -179,7 +166,7 @@ static void mask_and_ack_bigsur(unsigned int irq)
static void end_bigsur_irq(unsigned int irq)
{
- DPRINTK("end_bigsur_irq IRQ %d\n", irq);
+ pr_debug("end_bigsur_irq IRQ %d\n", irq);
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
enable_bigsur_l1irq(irq);
@@ -193,7 +180,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
u8 mask;
u32 reg;
- DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
+ pr_debug("startup_bigsur_irq IRQ %d\n", irq);
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
/* Enable the L1 IRQ */
@@ -218,7 +205,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
static void shutdown_bigsur_irq(unsigned int irq)
{
- DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
+ pr_debug("shutdown_bigsur_irq IRQ %d\n", irq);
if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
disable_bigsur_l1irq(irq);
else
@@ -260,7 +247,7 @@ static void make_bigsur_l1isr(unsigned int irq) {
disable_bigsur_l1irq(irq);
return;
}
- DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
+ pr_debug("make_bigsur_l1isr: bad irq, %d\n", irq);
return;
}
@@ -277,7 +264,7 @@ static void make_bigsur_l2isr(unsigned int irq) {
disable_bigsur_l2irq(irq);
return;
}
- DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
+ pr_debug("make_bigsur_l2isr: bad irq, %d\n", irq);
return;
}
diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c
index dfeede9da50..9711c20fc9e 100644
--- a/arch/sh/boards/bigsur/setup.c
+++ b/arch/sh/boards/bigsur/setup.c
@@ -41,31 +41,7 @@
// Big Sur Init Routines
/*===========================================================*/
-const char *get_system_type(void)
-{
- return "Big Sur";
-}
-
-/*
- * The Machine Vector
- */
-extern void heartbeat_bigsur(void);
-extern void init_bigsur_IRQ(void);
-
-struct sh_machine_vector mv_bigsur __initmv = {
- .mv_nr_irqs = NR_IRQS, // Defined in <asm/irq.h>
-
- .mv_isa_port2addr = bigsur_isa_port2addr,
- .mv_irq_demux = bigsur_irq_demux,
-
- .mv_init_irq = init_bigsur_IRQ,
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_bigsur,
-#endif
-};
-ALIAS_MV(bigsur)
-
-int __init platform_setup(void)
+static void __init bigsur_setup(char **cmdline_p)
{
/* Mask all 2nd level IRQ's */
outb(-1,BIGSUR_IMR0);
@@ -89,7 +65,24 @@ int __init platform_setup(void)
outw(1, BIGSUR_ETHR+0xe);
/* set the IO port to BIGSUR_ETHER_IOPORT */
outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
-
- return 0;
}
+/*
+ * The Machine Vector
+ */
+extern void heartbeat_bigsur(void);
+extern void init_bigsur_IRQ(void);
+
+struct sh_machine_vector mv_bigsur __initmv = {
+ .mv_name = "Big Sur",
+ .mv_setup = bigsur_setup,
+
+ .mv_isa_port2addr = bigsur_isa_port2addr,
+ .mv_irq_demux = bigsur_irq_demux,
+
+ .mv_init_irq = init_bigsur_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_bigsur,
+#endif
+};
+ALIAS_MV(bigsur)
diff --git a/arch/sh/boards/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile
deleted file mode 100644
index 52c1de0a6df..00000000000
--- a/arch/sh/boards/cat68701/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CAT-68701 specific parts of the kernel
-#
-
-obj-y := setup.o irq.o
-
diff --git a/arch/sh/boards/cat68701/irq.c b/arch/sh/boards/cat68701/irq.c
deleted file mode 100644
index f9a6d185fb8..00000000000
--- a/arch/sh/boards/cat68701/irq.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/sh/boards/cat68701/irq.c
- *
- * Copyright (C) 2000 Niibe Yutaka
- * 2001 Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <asm/irq.h>
-
-int cat68701_irq_demux(int irq)
-{
- if(irq==13) return 14;
- if(irq==7) return 10;
- return irq;
-}
-
-void init_cat68701_IRQ()
-{
- make_imask_irq(10);
- make_imask_irq(14);
-}
diff --git a/arch/sh/boards/cat68701/setup.c b/arch/sh/boards/cat68701/setup.c
deleted file mode 100644
index 90e5175df22..00000000000
--- a/arch/sh/boards/cat68701/setup.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * linux/arch/sh/boards/cat68701/setup.c
- *
- * Copyright (C) 2000 Niibe Yutaka
- * 2001 Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-const char *get_system_type(void)
-{
- return "CAT-68701";
-}
-
-#ifdef CONFIG_HEARTBEAT
-void heartbeat_cat68701()
-{
- static unsigned int cnt = 0, period = 0 , bit = 0;
- cnt += 1;
- if (cnt < period) {
- return;
- }
- cnt = 0;
-
- /* Go through the points (roughly!):
- * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
- */
- period = 110 - ( (300<<FSHIFT)/
- ((avenrun[0]/5) + (3<<FSHIFT)) );
-
- if(bit){ bit=0; }else{ bit=1; }
- outw(bit<<15,0x3fe);
-}
-#endif /* CONFIG_HEARTBEAT */
-
-unsigned long cat68701_isa_port2addr(unsigned long offset)
-{
- /* CompactFlash (IDE) */
- if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
- return 0xba000000 + offset;
-
- /* INPUT PORT */
- if ((offset >= 0x3fc) && (offset <= 0x3fd))
- return 0xb4007000 + offset;
-
- /* OUTPUT PORT */
- if ((offset >= 0x3fe) && (offset <= 0x3ff))
- return 0xb4007400 + offset;
-
- return offset + 0xb4000000; /* other I/O (EREA 5)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_cat68701 __initmv = {
- .mv_nr_irqs = 32,
- .mv_isa_port2addr = cat68701_isa_port2addr,
- .mv_irq_demux = cat68701_irq_demux,
-
- .mv_init_irq = init_cat68701_IRQ,
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_cat68701,
-#endif
-};
-ALIAS_MV(cat68701)
-
-int __init platform_setup(void)
-{
- /* dummy read erea5 (CS8900A) */
-}
-
diff --git a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile
deleted file mode 100644
index 1a788a85eba..00000000000
--- a/arch/sh/boards/cqreek/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CqREEK specific parts of the kernel
-#
-
-obj-y := setup.o irq.o
-
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
deleted file mode 100644
index 2955adc5231..00000000000
--- a/arch/sh/boards/cqreek/irq.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id: irq.c,v 1.1.2.4 2002/11/04 20:33:56 lethal Exp $
- *
- * arch/sh/boards/cqreek/irq.c
- *
- * Copyright (C) 2000 Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/irq.h>
-#include <linux/init.h>
-
-#include <asm/cqreek/cqreek.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/rtc.h>
-
-struct cqreek_irq_data {
- unsigned short mask_port; /* Port of Interrupt Mask Register */
- unsigned short stat_port; /* Port of Interrupt Status Register */
- unsigned short bit; /* Value of the bit */
-};
-static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
-
-static void disable_cqreek_irq(unsigned int irq)
-{
- unsigned long flags;
- unsigned short mask;
- unsigned short mask_port = cqreek_irq_data[irq].mask_port;
- unsigned short bit = cqreek_irq_data[irq].bit;
-
- local_irq_save(flags);
- /* Disable IRQ */
- mask = inw(mask_port) & ~bit;
- outw_p(mask, mask_port);
- local_irq_restore(flags);
-}
-
-static void enable_cqreek_irq(unsigned int irq)
-{
- unsigned long flags;
- unsigned short mask;
- unsigned short mask_port = cqreek_irq_data[irq].mask_port;
- unsigned short bit = cqreek_irq_data[irq].bit;
-
- local_irq_save(flags);
- /* Enable IRQ */
- mask = inw(mask_port) | bit;
- outw_p(mask, mask_port);
- local_irq_restore(flags);
-}
-
-static void mask_and_ack_cqreek(unsigned int irq)
-{
- unsigned short stat_port = cqreek_irq_data[irq].stat_port;
- unsigned short bit = cqreek_irq_data[irq].bit;
-
- disable_cqreek_irq(irq);
- /* Clear IRQ (it might be edge IRQ) */
- inw(stat_port);
- outw_p(bit, stat_port);
-}
-
-static void end_cqreek_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_cqreek_irq(irq);
-}
-
-static unsigned int startup_cqreek_irq(unsigned int irq)
-{
- enable_cqreek_irq(irq);
- return 0;
-}
-
-static void shutdown_cqreek_irq(unsigned int irq)
-{
- disable_cqreek_irq(irq);
-}
-
-static struct hw_interrupt_type cqreek_irq_type = {
- .typename = "CqREEK-IRQ",
- .startup = startup_cqreek_irq,
- .shutdown = shutdown_cqreek_irq,
- .enable = enable_cqreek_irq,
- .disable = disable_cqreek_irq,
- .ack = mask_and_ack_cqreek,
- .end = end_cqreek_irq
-};
-
-int cqreek_has_ide, cqreek_has_isa;
-
-/* XXX: This is just for test for my NE2000 ISA board
- What we really need is virtualized IRQ and demultiplexer like HP600 port */
-void __init init_cqreek_IRQ(void)
-{
- if (cqreek_has_ide) {
- cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK;
- cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT;
- cqreek_irq_data[14].bit = 1;
-
- irq_desc[14].chip = &cqreek_irq_type;
- irq_desc[14].status = IRQ_DISABLED;
- irq_desc[14].action = 0;
- irq_desc[14].depth = 1;
-
- disable_cqreek_irq(14);
- }
-
- if (cqreek_has_isa) {
- cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK;
- cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT;
- cqreek_irq_data[10].bit = (1 << 10);
-
- /* XXX: Err... we may need demultiplexer for ISA irq... */
- irq_desc[10].chip = &cqreek_irq_type;
- irq_desc[10].status = IRQ_DISABLED;
- irq_desc[10].action = 0;
- irq_desc[10].depth = 1;
-
- disable_cqreek_irq(10);
- }
-}
-
diff --git a/arch/sh/boards/cqreek/setup.c b/arch/sh/boards/cqreek/setup.c
deleted file mode 100644
index eff4ed93599..00000000000
--- a/arch/sh/boards/cqreek/setup.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $
- *
- * arch/sh/kernel/setup_cqreek.c
- *
- * Copyright (C) 2000 Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/mach/cqreek.h>
-#include <asm/machvec.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/rtc.h>
-
-#define IDE_OFFSET 0xA4000000UL
-#define ISA_OFFSET 0xA4A00000UL
-
-const char *get_system_type(void)
-{
- return "CqREEK";
-}
-
-static unsigned long cqreek_port2addr(unsigned long port)
-{
- if (0x0000<=port && port<=0x0040)
- return IDE_OFFSET + port;
- if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
- return IDE_OFFSET + port;
-
- return ISA_OFFSET + port;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_cqreek __initmv = {
-#if defined(CONFIG_CPU_SH4)
- .mv_nr_irqs = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
- .mv_nr_irqs = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
- .mv_nr_irqs = 61,
-#endif
-
- .mv_init_irq = init_cqreek_IRQ,
-
- .mv_isa_port2addr = cqreek_port2addr,
-};
-ALIAS_MV(cqreek)
-
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
-{
- int i;
-/* udelay is not available at setup time yet... */
-#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
-
- if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
- outw_p(0, BRIDGE_IDE_INTR_LVL);
- outw_p(0, BRIDGE_IDE_INTR_MASK);
-
- outw_p(0, BRIDGE_IDE_CTRL);
- DELAY();
-
- outw_p(0x8000, BRIDGE_IDE_CTRL);
- DELAY();
-
- outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
- outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
- outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
- cqreek_has_ide=1;
- }
-
- if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
- outw_p(0, BRIDGE_ISA_INTR_LVL);
- outw_p(0, BRIDGE_ISA_INTR_MASK);
-
- outw_p(0, BRIDGE_ISA_CTRL);
- DELAY();
- outw_p(0x8000, BRIDGE_ISA_CTRL);
- DELAY();
-
- outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
- outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
- outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
- cqreek_has_isa=1;
- }
-
- printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa);
-}
-
diff --git a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile
deleted file mode 100644
index 75999aa0a2d..00000000000
--- a/arch/sh/boards/dmida/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
-# of the kernel
-#
-
-obj-y := mach.o
-
diff --git a/arch/sh/boards/dmida/mach.c b/arch/sh/boards/dmida/mach.c
deleted file mode 100644
index d03a25f989c..00000000000
--- a/arch/sh/boards/dmida/mach.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * linux/arch/sh/boards/dmida/mach.c
- *
- * by Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc
- *
- * Derived from mach_hp600.c, which bore the message:
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the DataMyte Industrial Digital Assistant(tm).
- * See http://www.dmida.com
- *
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/irq.h>
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_dmida __initmv = {
- .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM,
-
- .mv_inb = hd64465_inb,
- .mv_inw = hd64465_inw,
- .mv_inl = hd64465_inl,
- .mv_outb = hd64465_outb,
- .mv_outw = hd64465_outw,
- .mv_outl = hd64465_outl,
-
- .mv_inb_p = hd64465_inb_p,
- .mv_inw_p = hd64465_inw,
- .mv_inl_p = hd64465_inl,
- .mv_outb_p = hd64465_outb_p,
- .mv_outw_p = hd64465_outw,
- .mv_outl_p = hd64465_outl,
-
- .mv_insb = hd64465_insb,
- .mv_insw = hd64465_insw,
- .mv_insl = hd64465_insl,
- .mv_outsb = hd64465_outsb,
- .mv_outsw = hd64465_outsw,
- .mv_outsl = hd64465_outsl,
-
- .mv_irq_demux = hd64465_irq_demux,
-};
-ALIAS_MV(dmida)
-
diff --git a/arch/sh/boards/dreamcast/irq.c b/arch/sh/boards/dreamcast/irq.c
index b10a6b11c03..5bf01f86c20 100644
--- a/arch/sh/boards/dreamcast/irq.c
+++ b/arch/sh/boards/dreamcast/irq.c
@@ -10,7 +10,6 @@
*/
#include <linux/irq.h>
-
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dreamcast/sysasic.h>
@@ -26,10 +25,10 @@
event.
There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event
- types can be found in include/asm-sh/dc_sysasic.h. There are three groups
- of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so
- 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
- IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
+ types can be found in include/asm-sh/dreamcast/sysasic.h. There are three
+ groups of EMRs that parallel the ESRs. Each EMR group corresponds to an
+ IRQ, so 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928
+ triggers IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
In the kernel, these events are mapped to virtual IRQs so that drivers can
respond to them as they would a normal interrupt. In order to keep this
@@ -57,29 +56,23 @@
/* Disable the hardware event by masking its bit in its EMR */
static inline void disable_systemasic_irq(unsigned int irq)
{
- unsigned long flags;
__u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
__u32 mask;
- local_irq_save(flags);
mask = inl(emr);
mask &= ~(1 << EVENT_BIT(irq));
outl(mask, emr);
- local_irq_restore(flags);
}
/* Enable the hardware event by setting its bit in its EMR */
static inline void enable_systemasic_irq(unsigned int irq)
{
- unsigned long flags;
__u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
__u32 mask;
- local_irq_save(flags);
mask = inl(emr);
mask |= (1 << EVENT_BIT(irq));
outl(mask, emr);
- local_irq_restore(flags);
}
/* Acknowledge a hardware event by writing its bit back to its ESR */
diff --git a/arch/sh/boards/dreamcast/rtc.c b/arch/sh/boards/dreamcast/rtc.c
index 379de162913..b3a876a3b85 100644
--- a/arch/sh/boards/dreamcast/rtc.c
+++ b/arch/sh/boards/dreamcast/rtc.c
@@ -1,4 +1,5 @@
-/* arch/sh/kernel/rtc-aica.c
+/*
+ * arch/sh/boards/dreamcast/rtc.c
*
* Dreamcast AICA RTC routines.
*
@@ -10,15 +11,12 @@
*/
#include <linux/time.h>
-
+#include <asm/rtc.h>
#include <asm/io.h>
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
-
/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
- seconds to get the standard Unix Epoch when getting the time, and add 20
- years when setting the time. */
+ seconds) to get the standard Unix Epoch when getting the time, and add
+ 20 years when setting the time. */
#define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
@@ -32,7 +30,8 @@ extern int (*rtc_set_time)(const time_t);
*
* Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
*/
-void aica_rtc_gettimeofday(struct timespec *ts) {
+void aica_rtc_gettimeofday(struct timespec *ts)
+{
unsigned long val1, val2;
do {
@@ -55,7 +54,8 @@ void aica_rtc_gettimeofday(struct timespec *ts) {
*
* Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
*/
-int aica_rtc_settimeofday(const time_t secs) {
+int aica_rtc_settimeofday(const time_t secs)
+{
unsigned long val1, val2;
unsigned long adj = secs + TWENTY_YEARS;
@@ -75,7 +75,7 @@ int aica_rtc_settimeofday(const time_t secs) {
void aica_time_init(void)
{
- rtc_get_time = aica_rtc_gettimeofday;
- rtc_set_time = aica_rtc_settimeofday;
+ rtc_sh_get_time = aica_rtc_gettimeofday;
+ rtc_sh_set_time = aica_rtc_settimeofday;
}
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
index 0027b80a234..f13017eeeb2 100644
--- a/arch/sh/boards/dreamcast/setup.c
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -22,41 +22,21 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/device.h>
-
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/rtc.h>
#include <asm/machvec.h>
-#include <asm/machvec_init.h>
#include <asm/mach/sysasic.h>
extern struct hw_interrupt_type systemasic_int;
-/* XXX: Move this into it's proper header. */
-extern void (*board_time_init)(void);
extern void aica_time_init(void);
extern int gapspci_init(void);
extern int systemasic_irq_demux(int);
-void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
-const char *get_system_type(void)
-{
- return "Sega Dreamcast";
-}
-
-struct sh_machine_vector mv_dreamcast __initmv = {
- .mv_nr_irqs = NR_IRQS,
-
- .mv_irq_demux = systemasic_irq_demux,
-
-#ifdef CONFIG_PCI
- .mv_consistent_alloc = dreamcast_consistent_alloc,
- .mv_consistent_free = dreamcast_consistent_free,
-#endif
-};
-ALIAS_MV(dreamcast)
-
-int __init platform_setup(void)
+static void __init dreamcast_setup(char **cmdline_p)
{
int i;
@@ -78,6 +58,16 @@ int __init platform_setup(void)
if (gapspci_init() < 0)
printk(KERN_WARNING "GAPSPCI was not detected.\n");
#endif
-
- return 0;
}
+
+struct sh_machine_vector mv_dreamcast __initmv = {
+ .mv_name = "Sega Dreamcast",
+ .mv_setup = dreamcast_setup,
+ .mv_irq_demux = systemasic_irq_demux,
+
+#ifdef CONFIG_PCI
+ .mv_consistent_alloc = dreamcast_consistent_alloc,
+ .mv_consistent_free = dreamcast_consistent_free,
+#endif
+};
+ALIAS_MV(dreamcast)
diff --git a/arch/sh/boards/ec3104/setup.c b/arch/sh/boards/ec3104/setup.c
index 4b3ef16a0e9..902bc975a13 100644
--- a/arch/sh/boards/ec3104/setup.c
+++ b/arch/sh/boards/ec3104/setup.c
@@ -21,22 +21,36 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
-
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/machvec.h>
#include <asm/mach/ec3104.h>
-const char *get_system_type(void)
+static void __init ec3104_setup(char **cmdline_p)
{
- return "EC3104";
+ char str[8];
+ int i;
+
+ for (i=0; i<8; i++)
+ str[i] = ctrl_readb(EC3104_BASE + i);
+
+ for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
+ irq_desc[i].handler = &ec3104_int;
+
+ printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
+ str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
+
+ /* mask all interrupts. this should have been done by the boot
+ * loader for us but we want to be sure ... */
+ ctrl_writel(0xffffffff, EC3104_IMR);
}
/*
* The Machine Vector
*/
-
struct sh_machine_vector mv_ec3104 __initmv = {
+ .mv_name = "EC3104",
+ .mv_setup = ec3104_setup,
.mv_nr_irqs = 96,
.mv_inb = ec3104_inb,
@@ -48,31 +62,4 @@ struct sh_machine_vector mv_ec3104 __initmv = {
.mv_irq_demux = ec3104_irq_demux,
};
-
ALIAS_MV(ec3104)
-
-int __init platform_setup(void)
-{
- char str[8];
- int i;
-
- if (0)
- return 0;
-
- for (i=0; i<8; i++)
- str[i] = ctrl_readb(EC3104_BASE + i);
-
- for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
- irq_desc[i].chip = &ec3104_int;
-
- printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
- str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
-
-
- /* mask all interrupts. this should have been done by the boot
- * loader for us but we want to be sure ... */
- ctrl_writel(0xffffffff, EC3104_IMR);
-
- return 0;
-}
-
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile
deleted file mode 100644
index eb753d31812..00000000000
--- a/arch/sh/boards/harp/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for STMicroelectronics board specific parts of the kernel
-#
-
-obj-y := irq.o setup.o mach.o led.o
-
-obj-$(CONFIG_PCI) += pcidma.o
-
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
deleted file mode 100644
index 96bb41c9fc5..00000000000
--- a/arch/sh/boards/harp/irq.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Looks after interrupts on the HARP board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-
-#define NUM_EXTERNAL_IRQS 16
-
-// Early versions of the STB1 Overdrive required this nasty frig
-//#define INVERT_INTMASK_WRITES
-
-static void enable_harp_irq(unsigned int irq);
-static void disable_harp_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_harp_irq disable_harp_irq
-
-static void mask_and_ack_harp(unsigned int);
-static void end_harp_irq(unsigned int irq);
-
-static unsigned int startup_harp_irq(unsigned int irq)
-{
- enable_harp_irq(irq);
- return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type harp_irq_type = {
- .typename = "Harp-IRQ",
- .startup = startup_harp_irq,
- .shutdown = shutdown_harp_irq,
- .enable = enable_harp_irq,
- .disable = disable_harp_irq,
- .ack = mask_and_ack_harp,
- .end = end_harp_irq
-};
-
-static void disable_harp_irq(unsigned int irq)
-{
- unsigned val, flags;
- unsigned maskReg;
- unsigned mask;
- int pri;
-
- if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
- return;
-
- pri = 15 - irq;
-
- if (pri < 8) {
- maskReg = EPLD_INTMASK0;
- } else {
- maskReg = EPLD_INTMASK1;
- pri -= 8;
- }
-
- local_irq_save(flags);
- mask = ctrl_inl(maskReg);
- mask &= (~(1 << pri));
-#if defined(INVERT_INTMASK_WRITES)
- mask ^= 0xff;
-#endif
- ctrl_outl(mask, maskReg);
- local_irq_restore(flags);
-}
-
-static void enable_harp_irq(unsigned int irq)
-{
- unsigned flags;
- unsigned maskReg;
- unsigned mask;
- int pri;
-
- if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
- return;
-
- pri = 15 - irq;
-
- if (pri < 8) {
- maskReg = EPLD_INTMASK0;
- } else {
- maskReg = EPLD_INTMASK1;
- pri -= 8;
- }
-
- local_irq_save(flags);
- mask = ctrl_inl(maskReg);
-
-
- mask |= (1 << pri);
-
-#if defined(INVERT_INTMASK_WRITES)
- mask ^= 0xff;
-#endif
- ctrl_outl(mask, maskReg);
-
- local_irq_restore(flags);
-}
-
-/* This functions sets the desired irq handler to be an overdrive type */
-static void __init make_harp_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &harp_irq_type;
- disable_harp_irq(irq);
-}
-
-static void mask_and_ack_harp(unsigned int irq)
-{
- disable_harp_irq(irq);
-}
-
-static void end_harp_irq(unsigned int irq)
-{
- enable_harp_irq(irq);
-}
-
-void __init init_harp_irq(void)
-{
- int i;
-
-#if !defined(INVERT_INTMASK_WRITES)
- // On the harp these are set to enable an interrupt
- ctrl_outl(0x00, EPLD_INTMASK0);
- ctrl_outl(0x00, EPLD_INTMASK1);
-#else
- // On the Overdrive the data is inverted before being stored in the reg
- ctrl_outl(0xff, EPLD_INTMASK0);
- ctrl_outl(0xff, EPLD_INTMASK1);
-#endif
-
- for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
- make_harp_irq(i);
- }
-}
diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c
deleted file mode 100644
index aeb7b392b19..00000000000
--- a/arch/sh/boards/harp/led.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/sh/stboards/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file contains ST40STB1 HARP and compatible code.
- */
-
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
-/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
-/* Works for HARP and overdrive */
-static void mach_led(int position, int value)
-{
- if (value) {
- ctrl_outl(EPLD_LED_ON, EPLD_LED);
- } else {
- ctrl_outl(EPLD_LED_OFF, EPLD_LED);
- }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_harp(void)
-{
- static unsigned cnt = 0, period = 0, dist = 0;
-
- if (cnt == 0 || cnt == dist)
- mach_led( -1, 1);
- else if (cnt == 7 || cnt == dist+7)
- mach_led( -1, 0);
-
- if (++cnt > period) {
- cnt = 0;
- /* The hyperbolic function below modifies the heartbeat period
- * length in dependency of the current (5min) load. It goes
- * through the points f(0)=126, f(1)=86, f(5)=51,
- * f(inf)->30. */
- period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
- dist = period / 4;
- }
-}
-#endif
diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c
deleted file mode 100644
index a946dd1674c..00000000000
--- a/arch/sh/boards/harp/mach.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/boards/harp/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the STMicroelectronics STB1 HARP and compatible boards
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-#include <asm/hd64465/io.h>
-#include <asm/hd64465/hd64465.h>
-
-void setup_harp(void);
-void init_harp_irq(void);
-void heartbeat_harp(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_harp __initmv = {
- .mv_nr_irqs = 89 + HD64465_IRQ_NUM,
-
- .mv_inb = hd64465_inb,
- .mv_inw = hd64465_inw,
- .mv_inl = hd64465_inl,
- .mv_outb = hd64465_outb,
- .mv_outw = hd64465_outw,
- .mv_outl = hd64465_outl,
-
- .mv_inb_p = hd64465_inb_p,
- .mv_inw_p = hd64465_inw,
- .mv_inl_p = hd64465_inl,
- .mv_outb_p = hd64465_outb_p,
- .mv_outw_p = hd64465_outw,
- .mv_outl_p = hd64465_outl,
-
- .mv_insb = hd64465_insb,
- .mv_insw = hd64465_insw,
- .mv_insl = hd64465_insl,
- .mv_outsb = hd64465_outsb,
- .mv_outsw = hd64465_outsw,
- .mv_outsl = hd64465_outsl,
-
- .mv_isa_port2addr = hd64465_isa_port2addr,
-
-#ifdef CONFIG_PCI
- .mv_init_irq = init_harp_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_harp,
-#endif
-};
-
-ALIAS_MV(harp)
diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c
deleted file mode 100644
index 475311390fd..00000000000
--- a/arch/sh/boards/harp/pcidma.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Dynamic DMA mapping support.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t * dma_handle)
-{
- void *ret;
- int gfp = GFP_ATOMIC;
-
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- /* Is it neccessary to do the memset? */
- memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
- }
- /* We must flush the cache before we pass it on to the device */
- flush_cache_all();
- return P2SEGADDR(ret);
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
-
- free_pages(p1addr, get_order(size));
-}
diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c
deleted file mode 100644
index 886e450ab63..00000000000
--- a/arch/sh/boards/harp/setup.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * arch/sh/stboard/setup.c
- *
- * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * STMicroelectronics ST40STB1 HARP and compatible support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-const char *get_system_type(void)
-{
- return "STB1 Harp";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_SH_STB1_HARP
- unsigned long ic8_version, ic36_version;
-
- ic8_version = ctrl_inl(EPLD_REVID2);
- ic36_version = ctrl_inl(EPLD_REVID1);
-
- printk("STMicroelectronics STB1 HARP initialisaton\n");
- printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
- (ic8_version >> 4) & 0xf, ic8_version & 0xf,
- (ic36_version >> 4) & 0xf, ic36_version & 0xf);
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
- unsigned long version;
-
- version = ctrl_inl(EPLD_REVID);
-
- printk("STMicroelectronics STB1 Overdrive initialisaton\n");
- printk("EPLD version: %d.%02d\n",
- (version >> 4) & 0xf, version & 0xf);
-#else
-#error Undefined machine
-#endif
-
- /* Currently all STB1 chips have problems with the sleep instruction,
- * so disable it here.
- */
- disable_hlt();
-
- return 0;
-}
-
-/*
- * pcibios_map_platform_irq
- *
- * This is board specific and returns the IRQ for a given PCI device.
- * It is used by the PCI code (arch/sh/kernel/st40_pci*)
- *
- */
-
-#define HARP_PCI_IRQ 1
-#define HARP_BRIDGE_IRQ 2
-#define OVERDRIVE_SLOT0_IRQ 0
-
-
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- switch (slot) {
-#ifdef CONFIG_SH_STB1_HARP
- case 2: /*This is the PCI slot on the */
- return HARP_PCI_IRQ;
- case 1: /* this is the bridge */
- return HARP_BRIDGE_IRQ;
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
- case 1:
- case 2:
- case 3:
- return slot - 1;
-#else
-#error Unknown board
-#endif
- default:
- return -1;
- }
-}
-
diff --git a/arch/sh/boards/hp6xx/Makefile b/arch/sh/boards/hp6xx/Makefile
index 927fe0aa5df..ff1b7f5b4e9 100644
--- a/arch/sh/boards/hp6xx/Makefile
+++ b/arch/sh/boards/hp6xx/Makefile
@@ -2,5 +2,6 @@
# Makefile for the HP6xx specific parts of the kernel
#
-obj-y := mach.o setup.o
-
+obj-y := setup.o
+obj-$(CONFIG_PM) += pm.o pm_wakeup.o
+obj-$(CONFIG_APM) += hp6xx_apm.o
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
new file mode 100644
index 00000000000..ad0e712c29f
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp6xx_apm.c
@@ -0,0 +1,123 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/apm_bios.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/apm.h>
+#include <asm/adc.h>
+#include <asm/hp6xx/hp6xx.h>
+
+#define SH7709_PGDR 0xa400012c
+
+#define APM_CRITICAL 10
+#define APM_LOW 30
+
+#define HP680_BATTERY_MAX 875
+#define HP680_BATTERY_MIN 600
+#define HP680_BATTERY_AC_ON 900
+
+#define MODNAME "hp6x0_apm"
+
+static int hp6x0_apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+ u8 pgdr;
+ char *p;
+ int battery_status;
+ int battery_flag;
+ int ac_line_status;
+ int time_units = APM_BATTERY_LIFE_UNKNOWN;
+
+ int battery = adc_single(ADC_CHANNEL_BATTERY);
+ int backup = adc_single(ADC_CHANNEL_BACKUP);
+ int charging = adc_single(ADC_CHANNEL_CHARGE);
+ int percentage;
+
+ percentage = 100 * (battery - HP680_BATTERY_MIN) /
+ (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
+
+ ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
+ APM_AC_ONLINE : APM_AC_OFFLINE;
+
+ p = buf;
+
+ pgdr = ctrl_inb(SH7709_PGDR);
+ if (pgdr & PGDR_MAIN_BATTERY_OUT) {
+ battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
+ battery_flag = 0x80;
+ percentage = -1;
+ } else if (charging < 8 ) {
+ battery_status = APM_BATTERY_STATUS_CHARGING;
+ battery_flag = 0x08;
+ ac_line_status = 0xff;
+ } else if (percentage <= APM_CRITICAL) {
+ battery_status = APM_BATTERY_STATUS_CRITICAL;
+ battery_flag = 0x04;
+ } else if (percentage <= APM_LOW) {
+ battery_status = APM_BATTERY_STATUS_LOW;
+ battery_flag = 0x02;
+ } else {
+ battery_status = APM_BATTERY_STATUS_HIGH;
+ battery_flag = 0x01;
+ }
+
+ p += sprintf(p, "1.0 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+ APM_32_BIT_SUPPORT,
+ ac_line_status,
+ battery_status,
+ battery_flag,
+ percentage,
+ time_units,
+ "min");
+ p += sprintf(p, "bat=%d backup=%d charge=%d\n",
+ battery, backup, charging);
+
+ return p - buf;
+}
+
+static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ if (!apm_suspended)
+ apm_queue_event(APM_USER_SUSPEND);
+
+ return IRQ_HANDLED;
+}
+
+static int __init hp6x0_apm_init(void)
+{
+ int ret;
+
+ ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
+ SA_INTERRUPT, MODNAME, 0);
+ if (unlikely(ret < 0)) {
+ printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
+ HP680_BTN_IRQ);
+ return ret;
+ }
+
+ apm_get_info = hp6x0_apm_get_info;
+
+ return ret;
+}
+
+static void __exit hp6x0_apm_exit(void)
+{
+ free_irq(HP680_BTN_IRQ, 0);
+ apm_get_info = 0;
+}
+
+module_init(hp6x0_apm_init);
+module_exit(hp6x0_apm_exit);
+
+MODULE_AUTHOR("Adriy Skulysh");
+MODULE_DESCRIPTION("hp6xx Advanced Power Management");
+MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c
new file mode 100644
index 00000000000..0e501bcbd7a
--- /dev/null
+++ b/arch/sh/boards/hp6xx/pm.c
@@ -0,0 +1,88 @@
+/*
+ * hp6x0 Power Management Routines
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/hd64461.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+#include <asm/pm.h>
+
+#define STBCR 0xffffff82
+#define STBCR2 0xffffff88
+
+static int hp6x0_pm_enter(suspend_state_t state)
+{
+ u8 stbcr, stbcr2;
+#ifdef CONFIG_HD64461_ENABLER
+ u8 scr;
+ u16 hd64461_stbcr;
+#endif
+
+ if (state != PM_SUSPEND_MEM)
+ return -EINVAL;
+
+#ifdef CONFIG_HD64461_ENABLER
+ outb(0, HD64461_PCC1CSCIER);
+
+ scr = inb(HD64461_PCC1SCR);
+ scr |= HD64461_PCCSCR_VCC1;
+ outb(scr, HD64461_PCC1SCR);
+
+ hd64461_stbcr = inw(HD64461_STBCR);
+ hd64461_stbcr |= HD64461_STBCR_SPC1ST;
+ outw(hd64461_stbcr, HD64461_STBCR);
+#endif
+
+ ctrl_outb(0x1f, DACR);
+
+ stbcr = ctrl_inb(STBCR);
+ ctrl_outb(0x01, STBCR);
+
+ stbcr2 = ctrl_inb(STBCR2);
+ ctrl_outb(0x7f , STBCR2);
+
+ outw(0xf07f, HD64461_SCPUCR);
+
+ pm_enter();
+
+ outw(0, HD64461_SCPUCR);
+ ctrl_outb(stbcr, STBCR);
+ ctrl_outb(stbcr2, STBCR2);
+
+#ifdef CONFIG_HD64461_ENABLER
+ hd64461_stbcr = inw(HD64461_STBCR);
+ hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
+ outw(hd64461_stbcr, HD64461_STBCR);
+
+ outb(0x4c, HD64461_PCC1CSCIER);
+ outb(0x00, HD64461_PCC1CSCR);
+#endif
+
+ return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops hp6x0_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .enter = hp6x0_pm_enter,
+};
+
+static int __init hp6x0_pm_init(void)
+{
+ pm_set_ops(&hp6x0_pm_ops);
+ return 0;
+}
+
+late_initcall(hp6x0_pm_init);
diff --git a/arch/sh/boards/hp6xx/pm_wakeup.S b/arch/sh/boards/hp6xx/pm_wakeup.S
new file mode 100644
index 00000000000..45e9bf0b911
--- /dev/null
+++ b/arch/sh/boards/hp6xx/pm_wakeup.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/cpu/mmu_context.h>
+
+#define k0 r0
+#define k1 r1
+#define k2 r2
+#define k3 r3
+#define k4 r4
+
+/*
+ * Kernel mode register usage:
+ * k0 scratch
+ * k1 scratch
+ * k2 scratch (Exception code)
+ * k3 scratch (Return address)
+ * k4 scratch
+ * k5 reserved
+ * k6 Global Interrupt Mask (0--15 << 4)
+ * k7 CURRENT_THREAD_INFO (pointer to current thread info)
+ */
+
+ENTRY(wakeup_start)
+! clear STBY bit
+ mov #-126, k2
+ and #127, k0
+ mov.b k0, @k2
+! enable refresh
+ mov.l 5f, k1
+ mov.w 6f, k0
+ mov.w k0, @k1
+! jump to handler
+ mov.l 2f, k2
+ mov.l 3f, k3
+ mov.l @k2, k2
+
+ mov.l 4f, k1
+ jmp @k1
+ nop
+
+ .align 2
+1: .long EXPEVT
+2: .long INTEVT
+3: .long ret_from_irq
+4: .long handle_exception
+5: .long 0xffffff68
+6: .word 0x0524
+
+ENTRY(wakeup_end)
+ nop
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 71f315663cc..60ab17ad605 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -8,22 +8,22 @@
*
* Setup code for an HP680 (internal peripherials only)
*/
-
+#include <linux/types.h>
#include <linux/init.h>
-#include <asm/io.h>
#include <asm/hd64461.h>
+#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/hp6xx/hp6xx.h>
#include <asm/cpu/dac.h>
-const char *get_system_type(void)
-{
- return "HP6xx";
-}
+#define SCPCR 0xa4000116
+#define SCPDR 0xa4000136
-int __init platform_setup(void)
+static void __init hp6xx_setup(char **cmdline_p)
{
u8 v8;
u16 v;
+
v = inw(HD64461_STBCR);
v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
@@ -50,5 +50,51 @@ int __init platform_setup(void)
v8 &= ~DACR_DAE;
ctrl_outb(v8,DACR);
- return 0;
+ v8 = ctrl_inb(SCPDR);
+ v8 |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
+ v8 &= ~SCPDR_TS_SCAN_ENABLE;
+ ctrl_outb(v8, SCPDR);
+
+ v = ctrl_inw(SCPCR);
+ v &= ~SCPCR_TS_MASK;
+ v |= SCPCR_TS_ENABLE;
+ ctrl_outw(v, SCPCR);
}
+
+/*
+ * XXX: This is stupid, we should have a generic machine vector for the cchips
+ * and just wrap the platform setup code in to this, as it's the only thing
+ * that ends up being different.
+ */
+struct sh_machine_vector mv_hp6xx __initmv = {
+ .mv_name = "hp6xx",
+ .mv_setup = hp6xx_setup,
+ .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
+
+ .mv_inb = hd64461_inb,
+ .mv_inw = hd64461_inw,
+ .mv_inl = hd64461_inl,
+ .mv_outb = hd64461_outb,
+ .mv_outw = hd64461_outw,
+ .mv_outl = hd64461_outl,
+
+ .mv_inb_p = hd64461_inb_p,
+ .mv_inw_p = hd64461_inw,
+ .mv_inl_p = hd64461_inl,
+ .mv_outb_p = hd64461_outb_p,
+ .mv_outw_p = hd64461_outw,
+ .mv_outl_p = hd64461_outl,
+
+ .mv_insb = hd64461_insb,
+ .mv_insw = hd64461_insw,
+ .mv_insl = hd64461_insl,
+ .mv_outsb = hd64461_outsb,
+ .mv_outsw = hd64461_outsw,
+ .mv_outsl = hd64461_outsl,
+
+ .mv_readw = hd64461_readw,
+ .mv_writew = hd64461_writew,
+
+ .mv_irq_demux = hd64461_irq_demux,
+};
+ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/Makefile b/arch/sh/boards/landisk/Makefile
new file mode 100644
index 00000000000..89e4beb2ad4
--- /dev/null
+++ b/arch/sh/boards/landisk/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
+#
+
+obj-y := setup.o io.o irq.o rtc.o landisk_pwb.o
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
new file mode 100644
index 00000000000..92498b4947d
--- /dev/null
+++ b/arch/sh/boards/landisk/io.c
@@ -0,0 +1,250 @@
+/*
+ * arch/sh/boards/landisk/io.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modifed by kogiidena
+ * 2005.03.03
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+extern void *area5_io_base; /* Area 5 I/O Base address */
+extern void *area6_io_base; /* Area 6 I/O Base address */
+
+static inline unsigned long port2adr(unsigned int port)
+{
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ if (port == 0x3f6)
+ return ((unsigned long)area5_io_base + 0x2c);
+ else
+ return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
+ ((port - 0x1f0) << 1));
+ else if ((0x170 <= port && port < 0x178) || port == 0x376)
+ if (port == 0x376)
+ return ((unsigned long)area6_io_base + 0x2c);
+ else
+ return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
+ ((port - 0x170) << 1));
+ else
+ maybebadio((unsigned long)port);
+
+ return port;
+}
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+u8 landisk_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inb(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inb(pci_ioaddr(port));
+
+ return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 landisk_inb_p(unsigned long port)
+{
+ u8 v;
+
+ if (PXSEG(port))
+ v = ctrl_inb(port);
+ else if (is_pci_ioaddr(port))
+ v = ctrl_inb(pci_ioaddr(port));
+ else
+ v = ctrl_inw(port2adr(port)) & 0xff;
+
+ ctrl_delay();
+
+ return v;
+}
+
+u16 landisk_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inw(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inw(pci_ioaddr(port));
+ else
+ maybebadio(port);
+
+ return 0;
+}
+
+u32 landisk_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inl(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inl(pci_ioaddr(port));
+ else
+ maybebadio(port);
+
+ return 0;
+}
+
+void landisk_outb(u8 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+}
+
+void landisk_outb_p(u8 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+ ctrl_delay();
+}
+
+void landisk_outw(u16 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outw(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outw(value, pci_ioaddr(port));
+ else
+ maybebadio(port);
+}
+
+void landisk_outl(u32 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outl(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outl(value, pci_ioaddr(port));
+ else
+ maybebadio(port);
+}
+
+void landisk_insb(unsigned long port, void *dst, unsigned long count)
+{
+ volatile u16 *p;
+ u8 *buf = dst;
+
+ if (PXSEG(port)) {
+ while (count--)
+ *buf++ = *(volatile u8 *)port;
+ } else if (is_pci_ioaddr(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+ while (count--)
+ *buf++ = *bp;
+ } else {
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *buf++ = *p & 0xff;
+ }
+}
+
+void landisk_insw(unsigned long port, void *dst, unsigned long count)
+{
+ volatile u16 *p;
+ u16 *buf = dst;
+
+ if (PXSEG(port))
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port))
+ p = (volatile u16 *)pci_ioaddr(port);
+ else
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *buf++ = *p;
+}
+
+void landisk_insl(unsigned long port, void *dst, unsigned long count)
+{
+ u32 *buf = dst;
+
+ if (is_pci_ioaddr(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+ while (count--)
+ *buf++ = *p;
+ } else
+ maybebadio(port);
+}
+
+void landisk_outsb(unsigned long port, const void *src, unsigned long count)
+{
+ volatile u16 *p;
+ const u8 *buf = src;
+
+ if (PXSEG(port))
+ while (count--)
+ ctrl_outb(*buf++, port);
+ else if (is_pci_ioaddr(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+ while (count--)
+ *bp = *buf++;
+ } else {
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *p = *buf++;
+ }
+}
+
+void landisk_outsw(unsigned long port, const void *src, unsigned long count)
+{
+ volatile u16 *p;
+ const u16 *buf = src;
+
+ if (PXSEG(port))
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port))
+ p = (volatile u16 *)pci_ioaddr(port);
+ else
+ p = (volatile u16 *)port2adr(port);
+
+ while (count--)
+ *p = *buf++;
+}
+
+void landisk_outsl(unsigned long port, const void *src, unsigned long count)
+{
+ const u32 *buf = src;
+
+ if (is_pci_ioaddr(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+ while (count--)
+ *p = *buf++;
+ } else
+ maybebadio(port);
+}
+
+void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
+{
+ if (PXSEG(port))
+ return (void __iomem *)port;
+ else if (is_pci_ioaddr(port))
+ return (void __iomem *)pci_ioaddr(port);
+
+ return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
new file mode 100644
index 00000000000..a006d644322
--- /dev/null
+++ b/arch/sh/boards/landisk/irq.c
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/boards/landisk/irq.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modified by kogiidena
+ * 2005.03.03
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/landisk/iodata_landisk.h>
+
+static void enable_landisk_irq(unsigned int irq);
+static void disable_landisk_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_landisk_irq disable_landisk_irq
+
+static void ack_landisk_irq(unsigned int irq);
+static void end_landisk_irq(unsigned int irq);
+
+static unsigned int startup_landisk_irq(unsigned int irq)
+{
+ enable_landisk_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void disable_landisk_irq(unsigned int irq)
+{
+ unsigned char val;
+ unsigned char mask = 0xff ^ (0x01 << (irq - 5));
+
+ /* Set the priority in IPR to 0 */
+ val = ctrl_inb(PA_IMASK);
+ val &= mask;
+ ctrl_outb(val, PA_IMASK);
+}
+
+static void enable_landisk_irq(unsigned int irq)
+{
+ unsigned char val;
+ unsigned char value = (0x01 << (irq - 5));
+
+ /* Set priority in IPR back to original value */
+ val = ctrl_inb(PA_IMASK);
+ val |= value;
+ ctrl_outb(val, PA_IMASK);
+}
+
+static void ack_landisk_irq(unsigned int irq)
+{
+ disable_landisk_irq(irq);
+}
+
+static void end_landisk_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_landisk_irq(irq);
+}
+
+static struct hw_interrupt_type landisk_irq_type = {
+ .typename = "LANDISK IRQ",
+ .startup = startup_landisk_irq,
+ .shutdown = shutdown_landisk_irq,
+ .enable = enable_landisk_irq,
+ .disable = disable_landisk_irq,
+ .ack = ack_landisk_irq,
+ .end = end_landisk_irq
+};
+
+static void make_landisk_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &landisk_irq_type;
+ disable_landisk_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_landisk_IRQ(void)
+{
+ int i;
+
+ for (i = 5; i < 14; i++)
+ make_landisk_irq(i);
+}
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
new file mode 100644
index 00000000000..e75cb578a28
--- /dev/null
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -0,0 +1,348 @@
+/*
+ * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
+ *
+ * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
+ *
+ * LED control drive function added by kogiidena
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/major.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/landisk/iodata_landisk.h>
+
+#define SHUTDOWN_BTN_MINOR 1 /* Shutdown button device minor no. */
+#define LED_MINOR 21 /* LED minor no. */
+#define BTN_MINOR 22 /* BUTTON minor no. */
+#define GIO_MINOR 40 /* GIO minor no. */
+
+static int openCnt;
+static int openCntLED;
+static int openCntGio;
+static int openCntBtn;
+static int landisk_btn;
+static int landisk_btnctrlpid;
+/*
+ * Functions prototypes
+ */
+
+static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+static int swdrv_open(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = MINOR(inode->i_rdev);
+ filp->private_data = (void *)minor;
+
+ if (minor == SHUTDOWN_BTN_MINOR) {
+ if (openCnt > 0) {
+ return -EALREADY;
+ } else {
+ openCnt++;
+ return 0;
+ }
+ } else if (minor == LED_MINOR) {
+ if (openCntLED > 0) {
+ return -EALREADY;
+ } else {
+ openCntLED++;
+ return 0;
+ }
+ } else if (minor == BTN_MINOR) {
+ if (openCntBtn > 0) {
+ return -EALREADY;
+ } else {
+ openCntBtn++;
+ return 0;
+ }
+ } else if (minor == GIO_MINOR) {
+ if (openCntGio > 0) {
+ return -EALREADY;
+ } else {
+ openCntGio++;
+ return 0;
+ }
+ }
+ return -ENOENT;
+
+}
+
+static int swdrv_close(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = MINOR(inode->i_rdev);
+ if (minor == SHUTDOWN_BTN_MINOR) {
+ openCnt--;
+ } else if (minor == LED_MINOR) {
+ openCntLED--;
+ } else if (minor == BTN_MINOR) {
+ openCntBtn--;
+ } else if (minor == GIO_MINOR) {
+ openCntGio--;
+ }
+ return 0;
+}
+
+static int swdrv_read(struct file *filp, char *buff, size_t count,
+ loff_t * ppos)
+{
+ int minor;
+ minor = (int)(filp->private_data);
+
+ if (!access_ok(VERIFY_WRITE, (void *)buff, count))
+ return -EFAULT;
+
+ if (minor == SHUTDOWN_BTN_MINOR) {
+ if (landisk_btn & 0x10) {
+ put_user(1, buff);
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int swdrv_write(struct file *filp, const char *buff, size_t count,
+ loff_t * ppos)
+{
+ int minor;
+ minor = (int)(filp->private_data);
+
+ if (minor == SHUTDOWN_BTN_MINOR) {
+ return count;
+ }
+ return count;
+}
+
+static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
+ disable_irq(IRQ_BUTTON);
+ disable_irq(IRQ_POWER);
+ ctrl_outb(0x00, PA_PWRINT_CLR);
+
+ if (landisk_btnctrlpid != 0) {
+ kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
+ landisk_btnctrlpid = 0;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct file_operations swdrv_fops = {
+ .read = swdrv_read, /* read */
+ .write = swdrv_write, /* write */
+ .open = swdrv_open, /* open */
+ .release = swdrv_close, /* release */
+ .ioctl = gio_ioctl, /* ioctl */
+
+};
+
+static char banner[] __initdata =
+ KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
+
+int __init swdrv_init(void)
+{
+ int error;
+
+ printk("%s", banner);
+
+ openCnt = 0;
+ openCntLED = 0;
+ openCntBtn = 0;
+ openCntGio = 0;
+ landisk_btn = 0;
+ landisk_btnctrlpid = 0;
+
+ if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
+ printk(KERN_ERR
+ "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
+ error);
+ return 1;
+ }
+
+ if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
+ printk(KERN_ERR "Unable to get IRQ 11.\n");
+ return 1;
+ }
+ if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
+ printk(KERN_ERR "Unable to get IRQ 12.\n");
+ return 1;
+ }
+ ctrl_outb(0x00, PA_PWRINT_CLR);
+
+ return 0;
+}
+
+module_init(swdrv_init);
+
+/*
+ * gio driver
+ *
+ */
+
+#include <asm/landisk/gio.h>
+
+static int gio_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int minor;
+ unsigned int data, mask;
+ static unsigned int addr = 0;
+
+ minor = (int)(filp->private_data);
+
+ /* access control */
+ if (minor == GIO_MINOR) {
+ ;
+ } else if (minor == LED_MINOR) {
+ if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
+ ;
+ } else {
+ return -EINVAL;
+ }
+ } else if (minor == BTN_MINOR) {
+ if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
+ ;
+ } else {
+ return -EINVAL;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ if (cmd & 0x01) { /* write */
+ if (copy_from_user(&data, (int *)arg, sizeof(int))) {
+ return -EFAULT;
+ }
+ }
+
+ switch (cmd) {
+ case GIODRV_IOCSGIOSETADDR: /* addres set */
+ addr = data;
+ break;
+
+ case GIODRV_IOCSGIODATA1: /* write byte */
+ ctrl_outb((unsigned char)(0x0ff & data), addr);
+ break;
+
+ case GIODRV_IOCSGIODATA2: /* write word */
+ if (addr & 0x01) {
+ return -EFAULT;
+ }
+ ctrl_outw((unsigned short int)(0x0ffff & data), addr);
+ break;
+
+ case GIODRV_IOCSGIODATA4: /* write long */
+ if (addr & 0x03) {
+ return -EFAULT;
+ }
+ ctrl_outl(data, addr);
+ break;
+
+ case GIODRV_IOCGGIODATA1: /* read byte */
+ data = ctrl_inb(addr);
+ break;
+
+ case GIODRV_IOCGGIODATA2: /* read word */
+ if (addr & 0x01) {
+ return -EFAULT;
+ }
+ data = ctrl_inw(addr);
+ break;
+
+ case GIODRV_IOCGGIODATA4: /* read long */
+ if (addr & 0x03) {
+ return -EFAULT;
+ }
+ data = ctrl_inl(addr);
+ break;
+ case GIODRV_IOCSGIO_LED: /* write */
+ mask = ((data & 0x00ffffff) << 8)
+ | ((data & 0x0000ffff) << 16)
+ | ((data & 0x000000ff) << 24);
+ landisk_ledparam = data & (~mask);
+ if (landisk_arch == 0) { /* arch == landisk */
+ landisk_ledparam &= 0x03030303;
+ mask = (~(landisk_ledparam >> 22)) & 0x000c;
+ landisk_ledparam |= mask;
+ } else { /* arch == usl-5p */
+ mask = (landisk_ledparam >> 24) & 0x0001;
+ landisk_ledparam |= mask;
+ landisk_ledparam &= 0x007f7f7f;
+ }
+ landisk_ledparam |= 0x80;
+ break;
+ case GIODRV_IOCGGIO_LED: /* read */
+ data = landisk_ledparam;
+ if (landisk_arch == 0) { /* arch == landisk */
+ data &= 0x03030303;
+ } else { /* arch == usl-5p */
+ ;
+ }
+ data &= (~0x080);
+ break;
+ case GIODRV_IOCSGIO_BUZZER: /* write */
+ landisk_buzzerparam = data;
+ landisk_ledparam |= 0x80;
+ break;
+ case GIODRV_IOCGGIO_LANDISK: /* read */
+ data = landisk_arch & 0x01;
+ break;
+ case GIODRV_IOCGGIO_BTN: /* read */
+ data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
+ data <<= 8;
+ data |= (0x0ff & ctrl_inb(PA_IMASK));
+ data <<= 8;
+ data |= (0x0ff & landisk_btn);
+ data <<= 8;
+ data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
+ break;
+ case GIODRV_IOCSGIO_BTNPID: /* write */
+ landisk_btnctrlpid = data;
+ landisk_btn = 0;
+ if (irq_desc[IRQ_BUTTON].depth) {
+ enable_irq(IRQ_BUTTON);
+ }
+ if (irq_desc[IRQ_POWER].depth) {
+ enable_irq(IRQ_POWER);
+ }
+ break;
+ case GIODRV_IOCGGIO_BTNPID: /* read */
+ data = landisk_btnctrlpid;
+ break;
+ default:
+ return -EFAULT;
+ break;
+ }
+
+ if ((cmd & 0x01) == 0) { /* read */
+ if (copy_to_user((int *)arg, &data, sizeof(int))) {
+ return -EFAULT;
+ }
+ }
+ return 0;
+}
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
new file mode 100644
index 00000000000..35ba726a097
--- /dev/null
+++ b/arch/sh/boards/landisk/rtc.c
@@ -0,0 +1,93 @@
+/*
+ * arch/sh/boards/landisk/rtc.c -- RTC support
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ */
+/*
+ * modifed by kogiidena
+ * 2005.09.16
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/bcd.h>
+#include <asm/rtc.h>
+
+extern spinlock_t rtc_lock;
+
+extern void
+rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
+ unsigned int BCD_day, unsigned int BCD_hr,
+ unsigned int BCD_min, unsigned int BCD_sec);
+
+extern unsigned long
+rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
+ unsigned int *BCD_day, unsigned int *BCD_hr,
+ unsigned int *BCD_min, unsigned int *BCD_sec);
+
+void landisk_rtc_gettimeofday(struct timespec *tv)
+{
+ unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ tv->tv_sec = rs5c313_get_cmos_time
+ (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+ tv->tv_nsec = 0;
+ spin_unlock_irqrestore(&rtc_lock, flags);
+}
+
+int landisk_rtc_settimeofday(const time_t secs)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned long flags;
+ unsigned long nowtime = secs;
+ unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+
+ rs5c313_get_cmos_time
+ (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+ cmos_minutes = BCD_min;
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
+ real_minutes, real_seconds);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_time: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return retval;
+}
+
+void landisk_time_init(void)
+{
+ rtc_sh_get_time = landisk_rtc_gettimeofday;
+ rtc_sh_set_time = landisk_rtc_settimeofday;
+}
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
new file mode 100644
index 00000000000..127b9e020e0
--- /dev/null
+++ b/arch/sh/boards/landisk/setup.c
@@ -0,0 +1,177 @@
+/*
+ * arch/sh/boards/landisk/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * I-O DATA Device, Inc. LANDISK Support.
+ *
+ * Modified for LANDISK by
+ * Atom Create Engineering Co., Ltd. 2002.
+ *
+ * modifed by kogiidena
+ * 2005.09.16
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/mm.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/io.h>
+
+void landisk_time_init(void);
+void init_landisk_IRQ(void);
+
+int landisk_ledparam;
+int landisk_buzzerparam;
+int landisk_arch;
+
+/* cycle the led's in the clasic knightrider/sun pattern */
+static void heartbeat_landisk(void)
+{
+ static unsigned int cnt = 0, blink = 0x00, period = 25;
+ volatile u8 *p = (volatile u8 *)PA_LED;
+ char data;
+
+ if ((landisk_ledparam & 0x080) == 0)
+ return;
+
+ cnt += 1;
+
+ if (cnt < period)
+ return;
+
+ cnt = 0;
+ blink++;
+
+ data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
+ data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
+ data |= landisk_ledparam;
+
+ /* buzzer */
+ if (landisk_buzzerparam & 0x1) {
+ data |= 0x80;
+ } else {
+ data &= 0x7f;
+ }
+ *p = data;
+
+ if (((landisk_ledparam & 0x007f7f00) == 0) &&
+ (landisk_buzzerparam == 0))
+ landisk_ledparam &= (~0x0080);
+
+ landisk_buzzerparam >>= 1;
+}
+
+static void landisk_power_off(void)
+{
+ ctrl_outb(0x01, PA_SHUTDOWN);
+}
+
+static void check_usl5p(void)
+{
+ volatile u8 *p = (volatile u8 *)PA_LED;
+ u8 tmp1, tmp2;
+
+ tmp1 = *p;
+ *p = 0x40;
+ tmp2 = *p;
+ *p = tmp1;
+
+ landisk_arch = (tmp2 == 0x40);
+ if (landisk_arch == 1) {
+ /* arch == usl-5p */
+ landisk_ledparam = 0x00000380;
+ landisk_ledparam |= (tmp1 & 0x07c);
+ } else {
+ /* arch == landisk */
+ landisk_ledparam = 0x02000180;
+ landisk_ledparam |= 0x04;
+ }
+}
+
+void *area5_io_base;
+void *area6_io_base;
+
+static int __init landisk_cf_init(void)
+{
+ pgprot_t prot;
+ unsigned long paddrbase, psize;
+
+ /* open I/O area window */
+ paddrbase = virt_to_phys((void *)PA_AREA5_IO);
+ psize = PAGE_SIZE;
+ prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
+ area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!area5_io_base) {
+ printk("allocate_cf_area : can't open CF I/O window!\n");
+ return -ENOMEM;
+ }
+
+ paddrbase = virt_to_phys((void *)PA_AREA6_IO);
+ psize = PAGE_SIZE;
+ prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
+ area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!area6_io_base) {
+ printk("allocate_cf_area : can't open HDD I/O window!\n");
+ return -ENOMEM;
+ }
+
+ printk(KERN_INFO "Allocate Area5/6 success.\n");
+
+ /* XXX : do we need attribute and common-memory area also? */
+
+ return 0;
+}
+
+static void __init landisk_setup(char **cmdline_p)
+{
+ device_initcall(landisk_cf_init);
+
+ landisk_buzzerparam = 0;
+ check_usl5p();
+
+ printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
+
+ board_time_init = landisk_time_init;
+ pm_power_off = landisk_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_landisk __initmv = {
+ .mv_name = "LANDISK",
+ .mv_setup = landisk_setup,
+ .mv_nr_irqs = 72,
+ .mv_inb = landisk_inb,
+ .mv_inw = landisk_inw,
+ .mv_inl = landisk_inl,
+ .mv_outb = landisk_outb,
+ .mv_outw = landisk_outw,
+ .mv_outl = landisk_outl,
+ .mv_inb_p = landisk_inb_p,
+ .mv_inw_p = landisk_inw,
+ .mv_inl_p = landisk_inl,
+ .mv_outb_p = landisk_outb_p,
+ .mv_outw_p = landisk_outw,
+ .mv_outl_p = landisk_outl,
+ .mv_insb = landisk_insb,
+ .mv_insw = landisk_insw,
+ .mv_insl = landisk_insl,
+ .mv_outsb = landisk_outsb,
+ .mv_outsw = landisk_outsw,
+ .mv_outsl = landisk_outsl,
+ .mv_ioport_map = landisk_ioport_map,
+ .mv_init_irq = init_landisk_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_landisk,
+#endif
+};
+ALIAS_MV(landisk)
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
index a76c655dcee..03b123a4bba 100644
--- a/arch/sh/boards/mpc1211/rtc.c
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -130,7 +130,7 @@ int mpc1211_rtc_settimeofday(const struct timeval *tv)
void mpc1211_time_init(void)
{
- rtc_get_time = mpc1211_rtc_gettimeofday;
- rtc_set_time = mpc1211_rtc_settimeofday;
+ rtc_sh_get_time = mpc1211_rtc_gettimeofday;
+ rtc_sh_set_time = mpc1211_rtc_settimeofday;
}
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 2bfb221cc35..8eb5d430397 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -10,14 +10,12 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/interrupt.h>
-
#include <asm/io.h>
#include <asm/machvec.h>
#include <asm/mpc1211/mpc1211.h>
#include <asm/mpc1211/pci.h>
#include <asm/mpc1211/m1543c.h>
-
/* ALI15X3 SMBus address offsets */
#define SMBHSTSTS (0 + 0x3100)
#define SMBHSTCNT (1 + 0x3100)
@@ -50,11 +48,6 @@
#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
-const char *get_system_type(void)
-{
- return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
-}
-
static void __init pci_write_config(unsigned long busNo,
unsigned long devNo,
unsigned long fncNo,
@@ -80,9 +73,6 @@ volatile unsigned long irq_err_count;
static void disable_mpc1211_irq(unsigned int irq)
{
- unsigned long flags;
-
- save_and_cli(flags);
if( irq < 8) {
m_irq_mask |= (1 << irq);
outb(m_irq_mask,I8259_M_MR);
@@ -90,16 +80,11 @@ static void disable_mpc1211_irq(unsigned int irq)
s_irq_mask |= (1 << (irq - 8));
outb(s_irq_mask,I8259_S_MR);
}
- restore_flags(flags);
}
static void enable_mpc1211_irq(unsigned int irq)
{
- unsigned long flags;
-
- save_and_cli(flags);
-
if( irq < 8) {
m_irq_mask &= ~(1 << irq);
outb(m_irq_mask,I8259_M_MR);
@@ -107,7 +92,6 @@ static void enable_mpc1211_irq(unsigned int irq)
s_irq_mask &= ~(1 << (irq - 8));
outb(s_irq_mask,I8259_S_MR);
}
- restore_flags(flags);
}
static inline int mpc1211_irq_real(unsigned int irq)
@@ -131,10 +115,6 @@ static inline int mpc1211_irq_real(unsigned int irq)
static void mask_and_ack_mpc1211(unsigned int irq)
{
- unsigned long flags;
-
- save_and_cli(flags);
-
if(irq < 8) {
if(m_irq_mask & (1<<irq)){
if(!mpc1211_irq_real(irq)){
@@ -162,7 +142,6 @@ static void mask_and_ack_mpc1211(unsigned int irq)
outb(0x60+(irq-8),I8259_S_CR); /* EOI */
outb(0x60+2,I8259_M_CR);
}
- restore_flags(flags);
}
static void end_mpc1211_irq(unsigned int irq)
@@ -219,7 +198,7 @@ int mpc1211_irq_demux(int irq)
return irq;
}
-void __init init_mpc1211_IRQ(void)
+static void __init init_mpc1211_IRQ(void)
{
int i;
/*
@@ -255,23 +234,12 @@ void __init init_mpc1211_IRQ(void)
}
}
-/*
- Initialize the board
-*/
-
-
-static void delay (void)
-{
- volatile unsigned short tmp;
- tmp = *(volatile unsigned short *) 0xa0000000;
-}
-
-static void delay1000 (void)
+static void delay1000(void)
{
int i;
for (i=0; i<1000; i++)
- delay ();
+ ctrl_delay();
}
static int put_smb_blk(unsigned char *p, int address, int command, int no)
@@ -314,26 +282,10 @@ static int put_smb_blk(unsigned char *p, int address, int command, int no)
return 0;
}
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_mpc1211 __initmv = {
- .mv_nr_irqs = 48,
- .mv_irq_demux = mpc1211_irq_demux,
- .mv_init_irq = init_mpc1211_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_mpc1211,
-#endif
-};
-
-ALIAS_MV(mpc1211)
-
/* arch/sh/boards/mpc1211/rtc.c */
void mpc1211_time_init(void);
-int __init platform_setup(void)
+static void __init mpc1211_setup(char **cmdline_p)
{
unsigned char spd_buf[128];
@@ -357,3 +309,18 @@ int __init platform_setup(void)
return 0;
}
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_mpc1211 __initmv = {
+ .mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)",
+ .mv_setup = mpc1211_setup,
+ .mv_nr_irqs = 48,
+ .mv_irq_demux = mpc1211_irq_demux,
+ .mv_init_irq = init_mpc1211_IRQ,
+
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_mpc1211,
+#endif
+};
+ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
deleted file mode 100644
index 245f03baf76..00000000000
--- a/arch/sh/boards/overdrive/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
-#
-
-obj-y := mach.o setup.o io.o irq.o led.o
-
-obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
-
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c
deleted file mode 100644
index 956c2390122..00000000000
--- a/arch/sh/boards/overdrive/fpga.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file handles programming up the Altera Flex10K that interfaces to
- * the Galileo, and does the PS/2 keyboard and mouse
- *
- */
-
-
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-
-#include <asm/overdriver/gt64111.h>
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-#define FPGA_NotConfigHigh() (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
-#define FPGA_NotConfigLow() (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
-
-/* I need to find out what (if any) the real delay factor here is */
-/* The delay is definately not critical */
-#define long_delay() {int i;for(i=0;i<10000;i++);}
-#define short_delay() {int i;for(i=0;i<100;i++);}
-
-static void __init program_overdrive_fpga(const unsigned char *fpgacode,
- int size)
-{
- int timeout = 0;
- int i, j;
- unsigned char b;
- static volatile unsigned char *FPGA_ControlReg =
- (volatile unsigned char *) (OVERDRIVE_CTRL);
- static volatile unsigned char *FPGA_ProgramReg =
- (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
-
- printk("FPGA: Commencing FPGA Programming\n");
-
- /* The PCI reset but MUST be low when programming the FPGA !!! */
- b = (*FPGA_ControlReg) & RESET_PCI_MASK;
-
- (*FPGA_ControlReg) = b;
-
- /* Prepare FPGA to program */
-
- FPGA_NotConfigHigh();
- long_delay();
-
- FPGA_NotConfigLow();
- short_delay();
-
- while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
- printk("FPGA: Waiting for NotStatus to go Low ... \n");
- }
-
- FPGA_NotConfigHigh();
-
- /* Wait for FPGA "ready to be programmed" signal */
- printk("FPGA: Waiting for NotStatus to go high (FPGA ready)... \n");
-
- for (timeout = 0;
- (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
- && (timeout < FPGA_TIMEOUT)); timeout++);
-
- /* Check if timeout condition occured - i.e. an error */
-
- if (timeout == FPGA_TIMEOUT) {
- printk
- ("FPGA: Failed to program - Timeout waiting for notSTATUS to go high\n");
- return;
- }
-
- printk("FPGA: Copying data to FPGA ... %d bytes\n", size);
-
- /* Copy array to FPGA - bit at a time */
-
- for (i = 0; i < size; i++) {
- volatile unsigned w = 0;
-
- for (j = 0; j < 8; j++) {
- *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
- short_delay();
- }
- if ((i & 0x3ff) == 0) {
- printk(".");
- }
- }
-
- /* Waiting for CONFDONE to go high - means the program is complete */
-
- for (timeout = 0;
- (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
- && (timeout < FPGA_TIMEOUT)); timeout++) {
-
- *FPGA_ProgramReg = 0x0;
- long_delay();
- }
-
- if (timeout == FPGA_TIMEOUT) {
- printk
- ("FPGA: Failed to program - Timeout waiting for CONFDONE to go high\n");
- return;
- } else { /* Clock another 10 times - gets the device into a working state */
- for (i = 0; i < 10; i++) {
- *FPGA_ProgramReg = 0x0;
- short_delay();
- }
- }
-
- printk("FPGA: Programming complete\n");
-}
-
-
-static const unsigned char __init fpgacode[] = {
-#include "./overdrive.ttf" /* Code from maxplus2 compiler */
- , 0, 0
-};
-
-
-int __init init_overdrive_fpga(void)
-{
- program_overdrive_fpga(fpgacode, sizeof(fpgacode));
-
- return 0;
-}
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
deleted file mode 100644
index 29e48971bba..00000000000
--- a/arch/sh/boards/overdrive/galileo.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file contains the PCI routines required for the Galileo GT6411
- * PCI bridge as used on the Orion and Overdrive boards.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/gt64111.h>
-
-
-/* After boot, we shift the Galileo registers so that they appear
- * in BANK6, along with IO space. This means we can have one contingous
- * lump of PCI address space without these registers appearing in the
- * middle of them
- */
-
-#define GT64111_BASE_ADDRESS 0xbb000000
-#define GT64111_IO_BASE_ADDRESS 0x1000
-/* The GT64111 registers appear at this address to the SH4 after reset */
-#define RESET_GT64111_BASE_ADDRESS 0xb4000000
-
-/* Macros used to access the Galileo registers */
-#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
-#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
-
-#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
-
-#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
-
-#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
-#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
-#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
-
-#define GT_READ(x) readl(GT64111_REG(x))
-#define GT_READ_BYTE(x) readb(GT64111_REG(x))
-#define GT_READ_SHORT(x) readw(GT64111_REG(x))
-
-
-/* Where the various SH banks start at */
-#define SH_BANK4_ADR 0xb0000000
-#define SH_BANK5_ADR 0xb4000000
-#define SH_BANK6_ADR 0xb8000000
-
-/* Masks out everything but lines 28,27,26 */
-#define BANK_SELECT_MASK 0x1c000000
-
-#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
-
-/*
- * Masks used for address conversaion. Bank 6 is used for IO and
- * has all the address bits zeroed by the FPGA. Special case this
- */
-#define MEMORY_BANK_MASK 0x1fffffff
-#define IO_BANK_MASK 0x03ffffff
-
-/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
- * if you want
- */
-#define IO_BANK_ADR PCI_GTIO_BASE
-
-/* Will select the correct mask to apply depending on the SH$ address */
-#define SELECT_BANK_MASK(x) \
- ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
-
-/* Converts between PCI space and P2 region */
-#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
-
-/* Various macros for figuring out what to stick in the Galileo registers.
- * You *really* don't want to figure this stuff out by hand, you always get
- * it wrong
- */
-#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
-#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
-#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
-
-#define PROGRAM_HI_LO(block,a,s) \
- GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
- GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
-
-#define PROGRAM_SUB_HI_LO(block,a,s) \
- GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
- GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
-
-/* We need to set the size, and the offset register */
-
-#define GT_BAR_MASK(x) ((x)&~0xfff)
-
-/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
-#define PROGRAM_GT_BAR(block,a,s) \
- GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
- write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
- GT_BAR_MASK(a))
-
-#define DISABLE_GT_BAR(block) \
- GT_WRITE(PCI_##block##_BANK_SIZE,0),\
- GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
- 0x80000000)
-
-/* Macros to disable things we are not going to use */
-#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
- GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
- GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-static void __init reset_pci(void)
-{
- /* Set RESET_PCI bit high */
- writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
- udelay(250);
-
- /* Set RESET_PCI bit low */
- writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
- udelay(250);
-
- writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
- udelay(250);
-}
-
-static int write_config_to_galileo(int where, u32 val);
-#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
-
-#define ENABLE_PCI_DRAM
-
-
-#ifdef TEST_DRAM
-/* Test function to check out if the PCI DRAM is working OK */
-static int /* __init */ test_dram(unsigned *base, unsigned size)
-{
- unsigned *p = base;
- unsigned *end = (unsigned *) (((unsigned) base) + size);
- unsigned w;
-
- for (p = base; p < end; p++) {
- *p = 0xffffffff;
- if (*p != 0xffffffff) {
- printk("AAARGH -write failed!!! at %p is %x\n", p,
- *p);
- return 0;
- }
- *p = 0x0;
- if (*p != 0x0) {
- printk("AAARGH -write failed!!!\n");
- return 0;
- }
- }
-
- for (p = base; p < end; p++) {
- *p = (unsigned) p;
- if (*p != (unsigned) p) {
- printk("Failed at 0x%p, actually is 0x%x\n", p,
- *p);
- return 0;
- }
- }
-
- for (p = base; p < end; p++) {
- w = ((unsigned) p & 0xffff0000);
- *p = w | (w >> 16);
- }
-
- for (p = base; p < end; p++) {
- w = ((unsigned) p & 0xffff0000);
- w |= (w >> 16);
- if (*p != w) {
- printk
- ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
- p, w, *p);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-
-/* Function to set up and initialise the galileo. This sets up the BARS,
- * maps the DRAM into the address space etc,etc
- */
-int __init galileo_init(void)
-{
- reset_pci();
-
- /* Now shift the galileo regs into this block */
- RESET_GT_WRITE(INTERNAL_SPACE_DEC,
- GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
-
- /* Should have a sanity check here, that you can read back at the new
- * address what you just wrote
- */
-
- /* Disable decode for all regions */
- DISABLE_DECODE(RAS10);
- DISABLE_DECODE(RAS32);
- DISABLE_DECODE(CS20);
- DISABLE_DECODE(CS3);
- DISABLE_DECODE(PCI_IO);
- DISABLE_DECODE(PCI_MEM0);
- DISABLE_DECODE(PCI_MEM1);
-
- /* Disable all BARS */
- GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
- DISABLE_GT_BAR(RAS10);
- DISABLE_GT_BAR(RAS32);
- DISABLE_GT_BAR(CS20);
- DISABLE_GT_BAR(CS3);
-
- /* Tell the BAR where the IO registers now are */
- GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
- (GT64111_IO_BASE_ADDRESS &
- IO_BANK_MASK)));
- /* set up a 112 Mb decode */
- PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
-
- /* Set up a 32 MB io space decode */
- PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
-
-#ifdef ENABLE_PCI_DRAM
- /* Program up the DRAM configuration - there is DRAM only in bank 0 */
- /* Now set up the DRAM decode */
- PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
- /* And the sub decode */
- PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
-
- DISABLE_SUB_DECODE(RAS1);
-
- /* Set refresh rate */
- GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
- GT_WRITE(DRAM_CFG, 0x100);
-
- /* we have to lob off the top bits rememeber!! */
- PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
-
-#endif
-
- /* We are only interested in decoding RAS10 and the Galileo's internal
- * registers (as IO) on the PCI bus
- */
-#ifdef ENABLE_PCI_DRAM
- GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
-#else
- GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
-#endif
-
- /* Change the class code to host bridge, it actually powers up
- * as a memory controller
- */
- GT_CONFIG_WRITE(8, 0x06000011);
-
- /* Allow the galileo to master the PCI bus */
- GT_CONFIG_WRITE(PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- PCI_COMMAND_IO);
-
-
-#if 0
- printk("Testing PCI DRAM - ");
- if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
- printk("Passed\n");
- }else {
- printk("FAILED\n");
- }
-#endif
- return 0;
-
-}
-
-
-#define SET_CONFIG_BITS(bus,devfn,where)\
- ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
-
-#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
-
-/* This write to the galileo config registers, unlike the functions below, can
- * be used before the PCI subsystem has started up
- */
-static int __init write_config_to_galileo(int where, u32 val)
-{
- GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
-
- GT_WRITE(PCI_CFG_DATA, val);
- return 0;
-}
-
-/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
- * the setup code shagging up the setup I have done on it, and 31 because the whole
- * thing locks up if you try to access that slot (which doesn't exist of course anyway
- */
-
-#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
-
-static int galileo_read_config_byte(struct pci_dev *dev, int where,
- u8 * val)
-{
-
-
- /* I suspect this doesn't work because this drives a special cycle ? */
- if (EXCLUDED_DEV(dev)) {
- *val = 0xff;
- return PCIBIOS_SUCCESSFUL;
- }
- /* Start the config cycle */
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
- /* Read back the result */
- *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_word(struct pci_dev *dev, int where,
- u16 * val)
-{
-
- if (EXCLUDED_DEV(dev)) {
- *val = 0xffff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
- *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_dword(struct pci_dev *dev, int where,
- u32 * val)
-{
- if (EXCLUDED_DEV(dev)) {
- *val = 0xffffffff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
- *val = GT_READ(PCI_CFG_DATA);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_byte(struct pci_dev *dev, int where,
- u8 val)
-{
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
- GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_write_config_word(struct pci_dev *dev, int where,
- u16 val)
-{
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
- GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_dword(struct pci_dev *dev, int where,
- u32 val)
-{
- GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
- GT_WRITE(PCI_CFG_DATA, val);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_config_ops = {
- galileo_read_config_byte,
- galileo_read_config_word,
- galileo_read_config_dword,
- galileo_write_config_byte,
- galileo_write_config_word,
- galileo_write_config_dword
-};
-
-
-/* Everything hangs off this */
-static struct pci_bus *pci_root_bus;
-
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
- return PCI_SLOT(dev->devfn);
-}
-
-static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- /* Slot 1: Galileo
- * Slot 2: PCI Slot 1
- * Slot 3: PCI Slot 2
- * Slot 4: ESS
- */
- switch (slot) {
- case 2:
- return OVERDRIVE_PCI_IRQ1;
- case 3:
- /* Note this assumes you have a hacked card in slot 2 */
- return OVERDRIVE_PCI_IRQ2;
- case 4:
- return OVERDRIVE_ESS_IRQ;
- default:
- /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
- return -1;
- }
-}
-
-
-
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
- ranges->io_start -= bus->resource[0]->start;
- ranges->io_end -= bus->resource[0]->start;
- ranges->mem_start -= bus->resource[1]->start;
- ranges->mem_end -= bus->resource[1]->start;
-}
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
-
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- printk("PCI: IDE base address fixup for %s\n", pci_name(d));
- for(i=0; i<4; i++) {
- struct resource *r = &d->resource[i];
- if ((r->start & ~0x80) == 0x374) {
- r->start |= 2;
- r->end = r->start;
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-void __init pcibios_init(void)
-{
- static struct resource galio,galmem;
-
- /* Allocate the registers used by the Galileo */
- galio.flags = IORESOURCE_IO;
- galio.name = "Galileo GT64011";
- galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
- galmem.name = "Galileo GT64011 DRAM";
-
- allocate_resource(&ioport_resource, &galio, 256,
- GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
- allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
- PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE,
- PCI_DRAM_SIZE, NULL, NULL);
-
- /* ok, do the scan man */
- pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
-
- pci_assign_unassigned_resources();
- pci_fixup_irqs(no_swizzle, map_od_irq);
-
-#ifdef TEST_DRAM
- printk("Testing PCI DRAM - ");
- if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
- printk("Passed\n");
- }else {
- printk("FAILED\n");
- }
-#endif
-
-}
-
-char * __init pcibios_setup(char *str)
-{
- return str;
-}
-
-
-
-int pcibios_enable_device(struct pci_dev *dev)
-{
-
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for (idx = 0; idx < 6; idx++) {
- r = dev->resource + idx;
- if (!r->start && r->end) {
- printk(KERN_ERR
- "PCI: Device %s not available because"
- " of resource collisions\n",
- pci_name(dev));
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (cmd != old_cmd) {
- printk("PCI: enabling device %s (%04x -> %04x)\n",
- pci_name(dev), old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
-
-}
-
-/* We should do some optimisation work here I think. Ok for now though */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size)
-{
-}
-
-void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
-
- unsigned long where, size;
- u32 reg;
-
-
- printk("PCI: Assigning %3s %08lx to %s\n",
- res->flags & IORESOURCE_IO ? "IO" : "MEM",
- res->start, dev->name);
-
- where = PCI_BASE_ADDRESS_0 + resource * 4;
- size = res->end - res->start;
-
- pci_read_config_dword(dev, where, &reg);
- reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
-
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
- printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-/*
- * If we set up a device for bus mastering, we need to check the latency
- * timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
- u8 lat;
- pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat < 16)
- lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
- else if (lat > pcibios_max_latency)
- lat = pcibios_max_latency;
- else
- return;
- printk("PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
diff --git a/arch/sh/boards/overdrive/io.c b/arch/sh/boards/overdrive/io.c
deleted file mode 100644
index 4671b6b047b..00000000000
--- a/arch/sh/boards/overdrive/io.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file contains the I/O routines for use on the overdrive board
- *
- */
-
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-#include <asm/overdrive/overdrive.h>
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the SuperH architecture, we just read/write the
- * memory location directly.
- */
-
-#define dprintk(x...)
-
-/* Translates an IO address to where it is mapped in memory */
-
-#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
-
-unsigned char od_inb(unsigned long port)
-{
-dprintk("od_inb(%x)\n", port);
- return readb(io_addr(port)) & 0xff;
-}
-
-
-unsigned short od_inw(unsigned long port)
-{
-dprintk("od_inw(%x)\n", port);
- return readw(io_addr(port)) & 0xffff;
-}
-
-unsigned int od_inl(unsigned long port)
-{
-dprintk("od_inl(%x)\n", port);
- return readl(io_addr(port));
-}
-
-void od_outb(unsigned char value, unsigned long port)
-{
-dprintk("od_outb(%x, %x)\n", value, port);
- writeb(value, io_addr(port));
-}
-
-void od_outw(unsigned short value, unsigned long port)
-{
-dprintk("od_outw(%x, %x)\n", value, port);
- writew(value, io_addr(port));
-}
-
-void od_outl(unsigned int value, unsigned long port)
-{
-dprintk("od_outl(%x, %x)\n", value, port);
- writel(value, io_addr(port));
-}
-
-/* This is horrible at the moment - needs more work to do something sensible */
-#define IO_DELAY() udelay(10)
-
-#define OUT_DELAY(x,type) \
-void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
-
-#define IN_DELAY(x,type) \
-unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
-
-
-OUT_DELAY(b,char)
-OUT_DELAY(w,short)
-OUT_DELAY(l,int)
-
-IN_DELAY(b,char)
-IN_DELAY(w,short)
-IN_DELAY(l,int)
-
-
-/* Now for the string version of these functions */
-void od_outsb(unsigned long port, const void *addr, unsigned long count)
-{
- int i;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p++) {
- outb(*p, port);
- }
-}
-
-
-void od_insb(unsigned long port, void *addr, unsigned long count)
-{
- int i;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p++) {
- *p = inb(port);
- }
-}
-
-/* For the 16 and 32 bit string functions, we have to worry about alignment.
- * The SH does not do unaligned accesses, so we have to read as bytes and
- * then write as a word or dword.
- * This can be optimised a lot more, especially in the case where the data
- * is aligned
- */
-
-void od_outsw(unsigned long port, const void *addr, unsigned long count)
-{
- int i;
- unsigned short tmp;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p += 2) {
- tmp = (*p) | ((*(p + 1)) << 8);
- outw(tmp, port);
- }
-}
-
-
-void od_insw(unsigned long port, void *addr, unsigned long count)
-{
- int i;
- unsigned short tmp;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p += 2) {
- tmp = inw(port);
- p[0] = tmp & 0xff;
- p[1] = (tmp >> 8) & 0xff;
- }
-}
-
-
-void od_outsl(unsigned long port, const void *addr, unsigned long count)
-{
- int i;
- unsigned tmp;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p += 4) {
- tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
- ((*(p + 3)) << 24);
- outl(tmp, port);
- }
-}
-
-
-void od_insl(unsigned long port, void *addr, unsigned long count)
-{
- int i;
- unsigned tmp;
- unsigned char *p = (unsigned char *) addr;
-
- for (i = 0; i < count; i++, p += 4) {
- tmp = inl(port);
- p[0] = tmp & 0xff;
- p[1] = (tmp >> 8) & 0xff;
- p[2] = (tmp >> 16) & 0xff;
- p[3] = (tmp >> 24) & 0xff;
-
- }
-}
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
deleted file mode 100644
index 5d730c70389..00000000000
--- a/arch/sh/boards/overdrive/irq.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Looks after interrupts on the overdrive board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-
-struct od_data {
- int overdrive_irq;
- int irq_mask;
-};
-
-#define NUM_EXTERNAL_IRQS 16
-#define EXTERNAL_IRQ_NOT_IN_USE (-1)
-#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
-
-/*
- * This table is used to determine what to program into the FPGA's CT register
- * for the specified Linux IRQ.
- *
- * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
- * but is one greater than that because the because the FPGA treats 0
- * as disabled, a value of 1 asserts PCI_Int0, and so on.
- *
- * The overdrive_irq specifies which of the eight interrupt sources generates
- * that interrupt, and but is multiplied by four to give the bit offset into
- * the CT register.
- *
- * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
- * by the EPLD. The assignments here of which PCI interrupt generates each
- * level is arbitary.
- */
-static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
- /* overdrive_irq , irq_mask */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 0 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 3 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 5 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 6 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 8 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 9 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 12 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 14 */
- {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE} /* 15 */
-};
-
-static void set_od_data(int overdrive_irq, int irq)
-{
- if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
- return;
- od_data_table[irq].overdrive_irq = overdrive_irq << 2;
-}
-
-static void enable_od_irq(unsigned int irq);
-void disable_od_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_od_irq disable_od_irq
-
-static void mask_and_ack_od(unsigned int);
-static void end_od_irq(unsigned int irq);
-
-static unsigned int startup_od_irq(unsigned int irq)
-{
- enable_od_irq(irq);
- return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type od_irq_type = {
- .typename = "Overdrive-IRQ",
- .startup = startup_od_irq,
- .shutdown = shutdown_od_irq,
- .enable = enable_od_irq,
- .disable = disable_od_irq,
- .ack = mask_and_ack_od,
- .end = end_od_irq
-};
-
-static void disable_od_irq(unsigned int irq)
-{
- unsigned val, flags;
- int overdrive_irq;
- unsigned mask;
-
- /* Not a valid interrupt */
- if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
- return;
-
- /* Is is necessary to use a cli here? Would a spinlock not be
- * mroe efficient?
- */
- local_irq_save(flags);
- overdrive_irq = od_data_table[irq].overdrive_irq;
- if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
- mask = ~(0x7 << overdrive_irq);
- val = ctrl_inl(OVERDRIVE_INT_CT);
- val &= mask;
- ctrl_outl(val, OVERDRIVE_INT_CT);
- }
- local_irq_restore(flags);
-}
-
-static void enable_od_irq(unsigned int irq)
-{
- unsigned val, flags;
- int overdrive_irq;
- unsigned mask;
-
- /* Not a valid interrupt */
- if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
- return;
-
- /* Set priority in OD back to original value */
- local_irq_save(flags);
- /* This one is not in use currently */
- overdrive_irq = od_data_table[irq].overdrive_irq;
- if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
- val = ctrl_inl(OVERDRIVE_INT_CT);
- mask = ~(0x7 << overdrive_irq);
- val &= mask;
- mask = od_data_table[irq].irq_mask << overdrive_irq;
- val |= mask;
- ctrl_outl(val, OVERDRIVE_INT_CT);
- }
- local_irq_restore(flags);
-}
-
-
-
-/* this functions sets the desired irq handler to be an overdrive type */
-static void __init make_od_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &od_irq_type;
- disable_od_irq(irq);
-}
-
-
-static void mask_and_ack_od(unsigned int irq)
-{
- disable_od_irq(irq);
-}
-
-static void end_od_irq(unsigned int irq)
-{
- enable_od_irq(irq);
-}
-
-void __init init_overdrive_irq(void)
-{
- int i;
-
- /* Disable all interrupts */
- ctrl_outl(0, OVERDRIVE_INT_CT);
-
- /* Update interrupt pin mode to use encoded interrupts */
- i = ctrl_inw(INTC_ICR);
- i &= ~INTC_ICR_IRLM;
- ctrl_outw(i, INTC_ICR);
-
- for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
- if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
- make_od_irq(i);
- } else if (i != 15) { // Cannot use imask on level 15
- make_imask_irq(i);
- }
- }
-
- /* Set up the interrupts */
- set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
- set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
- set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
-}
diff --git a/arch/sh/boards/overdrive/led.c b/arch/sh/boards/overdrive/led.c
deleted file mode 100644
index 860d7f204a4..00000000000
--- a/arch/sh/boards/overdrive/led.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * linux/arch/sh/overdrive/led.c
- *
- * Copyright (C) 1999 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file contains an Overdrive specific LED feature.
- */
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/overdrive/overdrive.h>
-
-static void mach_led(int position, int value)
-{
- unsigned long flags;
- unsigned long reg;
-
- local_irq_save(flags);
-
- reg = readl(OVERDRIVE_CTRL);
- if (value) {
- reg |= (1<<3);
- } else {
- reg &= ~(1<<3);
- }
- writel(reg, OVERDRIVE_CTRL);
-
- local_irq_restore(flags);
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_od(void)
-{
- static unsigned cnt = 0, period = 0, dist = 0;
-
- if (cnt == 0 || cnt == dist)
- mach_led( -1, 1);
- else if (cnt == 7 || cnt == dist+7)
- mach_led( -1, 0);
-
- if (++cnt > period) {
- cnt = 0;
- /* The hyperbolic function below modifies the heartbeat period
- * length in dependency of the current (5min) load. It goes
- * through the points f(0)=126, f(1)=86, f(5)=51,
- * f(inf)->30. */
- period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
- dist = period / 4;
- }
-}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/overdrive/mach.c b/arch/sh/boards/overdrive/mach.c
deleted file mode 100644
index 2834a03ae47..00000000000
--- a/arch/sh/boards/overdrive/mach.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/overdrive/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the STMicroelectronics Overdrive
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io_unknown.h>
-#include <asm/io_generic.h>
-#include <asm/overdrive/io.h>
-
-void heartbeat_od(void);
-void init_overdrive_irq(void);
-void galileo_pcibios_init(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_od __initmv = {
- .mv_nr_irqs = 48,
-
- .mv_inb = od_inb,
- .mv_inw = od_inw,
- .mv_inl = od_inl,
- .mv_outb = od_outb,
- .mv_outw = od_outw,
- .mv_outl = od_outl,
-
- .mv_inb_p = od_inb_p,
- .mv_inw_p = od_inw_p,
- .mv_inl_p = od_inl_p,
- .mv_outb_p = od_outb_p,
- .mv_outw_p = od_outw_p,
- .mv_outl_p = od_outl_p,
-
- .mv_insb = od_insb,
- .mv_insw = od_insw,
- .mv_insl = od_insl,
- .mv_outsb = od_outsb,
- .mv_outsw = od_outsw,
- .mv_outsl = od_outsl,
-
-#ifdef CONFIG_PCI
- .mv_init_irq = init_overdrive_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_od,
-#endif
-};
-
-ALIAS_MV(od)
diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c
deleted file mode 100644
index 1c9bfeda00b..00000000000
--- a/arch/sh/boards/overdrive/pcidma.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Dynamic DMA mapping support.
- *
- * On the overdrive, we can only DMA from memory behind the PCI bus!
- * this means that all DMA'able memory must come from there.
- * this restriction will not apply to later boards.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t * dma_handle)
-{
- void *ret;
- int gfp = GFP_ATOMIC;
-
- printk("BUG: pci_alloc_consistent() called - not yet supported\n");
- /* We ALWAYS need DMA memory on the overdrive hardware,
- * due to it's extreme weirdness
- * Need to flush the cache here as well, since the memory
- * can still be seen through the cache!
- */
- gfp |= GFP_DMA;
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
- }
- return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- free_pages((unsigned long) vaddr, get_order(size));
-}
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
deleted file mode 100644
index a3a7744c204..00000000000
--- a/arch/sh/boards/overdrive/setup.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/sh/overdrive/setup.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * STMicroelectronics Overdrive Support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-const char *get_system_type(void)
-{
- return "SH7750 Overdrive";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_PCI
- init_overdrive_fpga();
- galileo_init();
-#endif
-
- /* Enable RS232 receive buffers */
- writel(0x1e, OVERDRIVE_CTRL);
-}
diff --git a/arch/sh/boards/renesas/edosk7705/Makefile b/arch/sh/boards/renesas/edosk7705/Makefile
index 7fccbf2e4a1..14bdd531f11 100644
--- a/arch/sh/boards/renesas/edosk7705/Makefile
+++ b/arch/sh/boards/renesas/edosk7705/Makefile
@@ -1,10 +1,6 @@
#
# Makefile for the EDOSK7705 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
index ba143fa4afa..ec5be010771 100644
--- a/arch/sh/boards/renesas/edosk7705/setup.c
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -8,19 +8,21 @@
* Modified for edosk7705 development
* board by S. Dunn, 2003.
*/
-
#include <linux/init.h>
#include <asm/machvec.h>
-#include <asm/machvec_init.h>
#include <asm/edosk7705/io.h>
-static void init_edosk7705(void);
+static void __init sh_edosk7705_init_irq(void)
+{
+ /* This is the Ethernet interrupt */
+ make_imask_irq(0x09);
+}
/*
* The Machine Vector
*/
-
struct sh_machine_vector mv_edosk7705 __initmv = {
+ .mv_name = "EDOSK7705",
.mv_nr_irqs = 80,
.mv_inb = sh_edosk7705_inb,
@@ -37,23 +39,6 @@ struct sh_machine_vector mv_edosk7705 __initmv = {
.mv_outsl = sh_edosk7705_outsl,
.mv_isa_port2addr = sh_edosk7705_isa_port2addr,
- .mv_init_irq = init_edosk7705,
+ .mv_init_irq = sh_edosk7705_init_irq,
};
ALIAS_MV(edosk7705)
-
-static void __init init_edosk7705(void)
-{
- /* This is the Ethernet interrupt */
- make_imask_irq(0x09);
-}
-
-const char *get_system_type(void)
-{
- return "EDOSK7705";
-}
-
-void __init platform_setup(void)
-{
- /* Nothing .. */
-}
-
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Kconfig b/arch/sh/boards/renesas/hs7751rvoip/Kconfig
new file mode 100644
index 00000000000..1743be477be
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/Kconfig
@@ -0,0 +1,12 @@
+if SH_HS7751RVOIP
+
+menu "HS7751RVoIP options"
+
+config HS7751RVOIP_CODEC
+ bool "Support VoIP Codec section"
+ help
+ Selecting this option will support CODEC section.
+
+endmenu
+
+endif
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Makefile b/arch/sh/boards/renesas/hs7751rvoip/Makefile
index e8b4109ace1..e626377c55e 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/Makefile
+++ b/arch/sh/boards/renesas/hs7751rvoip/Makefile
@@ -1,12 +1,8 @@
#
# Makefile for the HS7751RVoIP specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-obj-y := mach.o setup.o io.o irq.o led.o
+obj-y := setup.o io.o irq.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c
index 3a1abfa2fef..9ea1136b219 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/io.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/io.c
@@ -10,21 +10,16 @@
* placeholder code from io_hs7751rvoip.c left in with the
* expectation of later SuperIO and PCMCIA access.
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
#include <asm/io.h>
#include <asm/hs7751rvoip/hs7751rvoip.h>
#include <asm/addrspace.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-extern void *area5_io8_base; /* Area 5 8bit I/O Base address */
extern void *area6_io8_base; /* Area 6 8bit I/O Base address */
extern void *area5_io16_base; /* Area 5 16bit I/O Base address */
-extern void *area6_io16_base; /* Area 6 16bit I/O Base address */
/*
* The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC)
@@ -33,25 +28,8 @@ extern void *area6_io16_base; /* Area 6 16bit I/O Base address */
* like the other Solution Engine boards.
*/
-#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#if defined(CONFIG_HS7751RVOIP_CODEC)
#define CODEC_IO_BASE 0x1000
-#endif
-
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
+#define CODEC_IOMAP(a) ((unsigned long)area6_io8_base + ((a) - CODEC_IO_BASE))
static inline unsigned long port2adr(unsigned int port)
{
@@ -59,9 +37,10 @@ static inline unsigned long port2adr(unsigned int port)
if (port == 0x3f6)
return ((unsigned long)area5_io16_base + 0x0c);
else
- return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1));
+ return ((unsigned long)area5_io16_base + 0x800 +
+ ((port-0x1f0) << 1));
else
- maybebadio(port2adr, (unsigned long)port);
+ maybebadio((unsigned long)port);
return port;
}
@@ -78,25 +57,10 @@ static inline int shifted_port(unsigned long port)
}
#if defined(CONFIG_HS7751RVOIP_CODEC)
-static inline int
-codec_port(unsigned long port)
-{
- if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20))
- return 1;
- else
- return 0;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
- ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#define codec_port(port) \
+ ((CODEC_IO_BASE <= (port)) && ((port) < (CODEC_IO_BASE + 0x20)))
#else
-#define CHECK_SH7751_PCIIO(port) (0)
+#define codec_port(port) (0)
#endif
/*
@@ -109,15 +73,13 @@ codec_port(unsigned long port)
unsigned char hs7751rvoip_inb(unsigned long port)
{
if (PXSEG(port))
- return *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ return ctrl_inb(port);
else if (codec_port(port))
- return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned char *)PCI_IOMAP(port);
+ return ctrl_inb(CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inb(pci_ioaddr(port));
else
- return (*(volatile unsigned short *)port2adr(port) & 0xff);
+ return ctrl_inw(port2adr(port)) & 0xff;
}
unsigned char hs7751rvoip_inb_p(unsigned long port)
@@ -125,38 +87,36 @@ unsigned char hs7751rvoip_inb_p(unsigned long port)
unsigned char v;
if (PXSEG(port))
- v = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ v = ctrl_inb(port);
else if (codec_port(port))
- v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- v = *(volatile unsigned char *)PCI_IOMAP(port);
+ v = ctrl_inb(CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ v = ctrl_inb(pci_ioaddr(port));
else
- v = (*(volatile unsigned short *)port2adr(port) & 0xff);
- delay();
+ v = ctrl_inw(port2adr(port)) & 0xff;
+ ctrl_delay();
return v;
}
unsigned short hs7751rvoip_inw(unsigned long port)
{
if (PXSEG(port))
- return *(volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned short *)PCI_IOMAP(port);
+ return ctrl_inw(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inw(pci_ioaddr(port));
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
unsigned int hs7751rvoip_inl(unsigned long port)
{
if (PXSEG(port))
- return *(volatile unsigned long *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned long *)PCI_IOMAP(port);
+ return ctrl_inl(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inl(pci_ioaddr(port));
else
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
@@ -164,146 +124,160 @@ void hs7751rvoip_outb(unsigned char value, unsigned long port)
{
if (PXSEG(port))
- *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ ctrl_outb(value, port);
else if (codec_port(port))
- *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(unsigned char *)PCI_IOMAP(port) = value;
+ ctrl_outb(value, CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outb(value, pci_ioaddr(port));
else
- *(volatile unsigned short *)port2adr(port) = value;
+ ctrl_outb(value, port2adr(port));
}
void hs7751rvoip_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
- *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ ctrl_outb(value, port);
else if (codec_port(port))
- *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(unsigned char *)PCI_IOMAP(port) = value;
+ ctrl_outb(value, CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outb(value, pci_ioaddr(port));
else
- *(volatile unsigned short *)port2adr(port) = value;
- delay();
+ ctrl_outw(value, port2adr(port));
+
+ ctrl_delay();
}
void hs7751rvoip_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
- *(volatile unsigned short *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(unsigned short *)PCI_IOMAP(port) = value;
+ ctrl_outw(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outw(value, pci_ioaddr(port));
else
- maybebadio(outw, port);
+ maybebadio(port);
}
void hs7751rvoip_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
- *(volatile unsigned long *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *((unsigned long *)PCI_IOMAP(port)) = value;
+ ctrl_outl(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outl(value, pci_ioaddr(port));
else
- maybebadio(outl, port);
+ maybebadio(port);
}
void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count)
{
+ u8 *buf = addr;
+
if (PXSEG(port))
- while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ while (count--)
+ *buf++ = ctrl_inb(port);
else if (codec_port(port))
- while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+ while (count--)
+ *buf++ = ctrl_inb(CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
- while (count--) *((volatile unsigned char *) addr)++ = *bp;
+ while (count--)
+ *buf++ = *bp;
} else {
- volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+ volatile u16 *p = (volatile u16 *)port2adr(port);
- while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+ while (count--)
+ *buf++ = *p & 0xff;
}
}
void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count)
{
- volatile __u16 *p;
+ volatile u16 *p;
+ u16 *buf = addr;
if (PXSEG(port))
- p = (volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- p = (volatile unsigned short *)PCI_IOMAP(port);
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile u16 *)pci_ioaddr(port);
else
- p = (volatile unsigned short *)port2adr(port);
- while (count--) *((__u16 *) addr)++ = *p;
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *buf++ = *p;
}
void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count)
{
- if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
- while (count--) *((__u32 *) addr)++ = *p;
+ if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+ u32 *buf = addr;
+
+ while (count--)
+ *buf++ = *p;
} else
- maybebadio(insl, port);
+ maybebadio(port);
}
void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count)
{
+ const u8 *buf = addr;
+
if (PXSEG(port))
- while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+ while (count--)
+ ctrl_outb(*buf++, port);
else if (codec_port(port))
- while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++;
-#endif
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+ while (count--)
+ ctrl_outb(*buf++, CODEC_IOMAP(port));
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
- while (count--) *bp = *((volatile unsigned char *) addr)++;
+ while (count--)
+ *bp = *buf++;
} else {
- volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+ volatile u16 *p = (volatile u16 *)port2adr(port);
- while (count--) *p = *((unsigned char *) addr)++;
+ while (count--)
+ *p = *buf++;
}
}
void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count)
{
- volatile __u16 *p;
+ volatile u16 *p;
+ const u16 *buf = addr;
if (PXSEG(port))
- p = (volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- p = (volatile unsigned short *)PCI_IOMAP(port);
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile u16 *)pci_ioaddr(port);
else
- p = (volatile unsigned short *)port2adr(port);
- while (count--) *p = *((__u16 *) addr)++;
+ p = (volatile u16 *)port2adr(port);
+
+ while (count--)
+ *p = *buf++;
}
void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count)
{
- if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+ const u32 *buf = addr;
- while (count--) *p = *((__u32 *) addr)++;
+ if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+ while (count--)
+ *p = *buf++;
} else
- maybebadio(outsl, port);
+ maybebadio(port);
}
-void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size)
+void __iomem *hs7751rvoip_ioport_map(unsigned long port, unsigned int size)
{
- if (offset >= 0xfd000000)
- return (void *)offset;
- else
- return (void *)P2SEGADDR(offset);
-}
-EXPORT_SYMBOL(hs7751rvoip_ioremap);
+ if (PXSEG(port))
+ return (void __iomem *)port;
+ else if (unlikely(codec_port(port) && (size == 1)))
+ return (void __iomem *)CODEC_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return (void __iomem *)pci_ioaddr(port);
-unsigned long hs7751rvoip_isa_port2addr(unsigned long offset)
-{
- return port2adr(offset);
+ return (void __iomem *)port2adr(port);
}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
index 705b7ddcb0d..c617b188258 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/irq.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -35,30 +35,24 @@ static unsigned int startup_hs7751rvoip_irq(unsigned int irq)
static void disable_hs7751rvoip_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short val;
unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
/* Set the priority in IPR to 0 */
- local_irq_save(flags);
val = ctrl_inw(IRLCNTR3);
val &= mask;
ctrl_outw(val, IRLCNTR3);
- local_irq_restore(flags);
}
static void enable_hs7751rvoip_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short val;
unsigned short value = (0x0001 << mask_pos[irq]);
/* Set priority in IPR back to original value */
- local_irq_save(flags);
val = ctrl_inw(IRLCNTR3);
val |= value;
ctrl_outw(val, IRLCNTR3);
- local_irq_restore(flags);
}
static void ack_hs7751rvoip_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/led.c b/arch/sh/boards/renesas/hs7751rvoip/led.c
deleted file mode 100644
index b6608fff9f3..00000000000
--- a/arch/sh/boards/renesas/hs7751rvoip/led.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
- *
- * Copyright (C) 2000 Kazumoto Kojima
- *
- * Renesas Technology Sales HS7751RVoIP Support.
- *
- * Modified for HS7751RVoIP by
- * Atom Create Engineering Co., Ltd. 2002.
- * Lineo uSolutions, Inc. 2003.
- */
-
-#include <asm/io.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-
-extern unsigned int debug_counter;
-
-void debug_led_disp(void)
-{
- unsigned short value;
-
- value = (unsigned char)debug_counter++;
- ctrl_outb((0xf0|value), PA_OUTPORTR);
- if (value == 0x0f)
- debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/mach.c b/arch/sh/boards/renesas/hs7751rvoip/mach.c
deleted file mode 100644
index caf967f77c6..00000000000
--- a/arch/sh/boards/renesas/hs7751rvoip/mach.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_hs7751rvoip.c
- *
- * Minor tweak of mach_se.c file to reference hs7751rvoip-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales HS7751RVoIP
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/hs7751rvoip/io.h>
-
-extern void init_hs7751rvoip_IRQ(void);
-extern void *hs7751rvoip_ioremap(unsigned long, unsigned long);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
- .mv_nr_irqs = 72,
-
- .mv_inb = hs7751rvoip_inb,
- .mv_inw = hs7751rvoip_inw,
- .mv_inl = hs7751rvoip_inl,
- .mv_outb = hs7751rvoip_outb,
- .mv_outw = hs7751rvoip_outw,
- .mv_outl = hs7751rvoip_outl,
-
- .mv_inb_p = hs7751rvoip_inb_p,
- .mv_inw_p = hs7751rvoip_inw,
- .mv_inl_p = hs7751rvoip_inl,
- .mv_outb_p = hs7751rvoip_outb_p,
- .mv_outw_p = hs7751rvoip_outw,
- .mv_outl_p = hs7751rvoip_outl,
-
- .mv_insb = hs7751rvoip_insb,
- .mv_insw = hs7751rvoip_insw,
- .mv_insl = hs7751rvoip_insl,
- .mv_outsb = hs7751rvoip_outsb,
- .mv_outsw = hs7751rvoip_outsw,
- .mv_outsl = hs7751rvoip_outsl,
-
- .mv_ioremap = hs7751rvoip_ioremap,
- .mv_isa_port2addr = hs7751rvoip_isa_port2addr,
- .mv_init_irq = init_hs7751rvoip_IRQ,
-};
-ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index 29fb5ff70fb..0414c15c345 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -1,44 +1,38 @@
/*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
+ * Renesas Technology Sales HS7751RVoIP Support.
*
* Copyright (C) 2000 Kazumoto Kojima
*
- * Renesas Technology Sales HS7751RVoIP Support.
- *
* Modified for HS7751RVoIP by
* Atom Create Engineering Co., Ltd. 2002.
* Lineo uSolutions, Inc. 2003.
*/
-
#include <linux/init.h>
#include <linux/irq.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/pm.h>
#include <asm/io.h>
#include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/irq.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
-unsigned int debug_counter;
-
-const char *get_system_type(void)
+static void __init hs7751rvoip_init_irq(void)
{
- return "HS7751RVoIP";
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+#endif
+
+ init_hs7751rvoip_IRQ();
}
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
+static void hs7751rvoip_power_off(void)
{
- printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
- ctrl_outb(0xf0, PA_OUTPORTR);
- debug_counter = 0;
+ ctrl_outw(ctrl_inw(PA_OUTPORTR) & 0xffdf, PA_OUTPORTR);
}
void *area5_io8_base;
@@ -46,16 +40,15 @@ void *area6_io8_base;
void *area5_io16_base;
void *area6_io16_base;
-int __init cf_init(void)
+static int __init hs7751rvoip_cf_init(void)
{
pgprot_t prot;
- unsigned long paddrbase, psize;
+ unsigned long paddrbase;
/* open I/O area window */
paddrbase = virt_to_phys((void *)(PA_AREA5_IO+0x00000800));
- psize = PAGE_SIZE;
prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_COM16);
- area5_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ area5_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
if (!area5_io16_base) {
printk("allocate_cf_area : can't open CF I/O window!\n");
return -ENOMEM;
@@ -64,19 +57,18 @@ int __init cf_init(void)
/* XXX : do we need attribute and common-memory area also? */
paddrbase = virt_to_phys((void *)PA_AREA6_IO);
- psize = PAGE_SIZE;
#if defined(CONFIG_HS7751RVOIP_CODEC)
prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_COM8);
#else
prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO8);
#endif
- area6_io8_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ area6_io8_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
if (!area6_io8_base) {
printk("allocate_cf_area : can't open CODEC I/O 8bit window!\n");
return -ENOMEM;
}
prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
- area6_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ area6_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
if (!area6_io16_base) {
printk("allocate_cf_area : can't open CODEC I/O 16bit window!\n");
return -ENOMEM;
@@ -85,4 +77,46 @@ int __init cf_init(void)
return 0;
}
-__initcall (cf_init);
+/*
+ * Initialize the board
+ */
+static void __init hs7751rvoip_setup(char **cmdline_p)
+{
+ device_initcall(hs7751rvoip_cf_init);
+
+ ctrl_outb(0xf0, PA_OUTPORTR);
+ pm_power_off = hs7751rvoip_power_off;
+
+ printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
+}
+
+struct sh_machine_vector mv_hs7751rvoip __initmv = {
+ .mv_name = "HS7751RVoIP",
+ .mv_setup = hs7751rvoip_setup,
+ .mv_nr_irqs = 72,
+
+ .mv_inb = hs7751rvoip_inb,
+ .mv_inw = hs7751rvoip_inw,
+ .mv_inl = hs7751rvoip_inl,
+ .mv_outb = hs7751rvoip_outb,
+ .mv_outw = hs7751rvoip_outw,
+ .mv_outl = hs7751rvoip_outl,
+
+ .mv_inb_p = hs7751rvoip_inb_p,
+ .mv_inw_p = hs7751rvoip_inw,
+ .mv_inl_p = hs7751rvoip_inl,
+ .mv_outb_p = hs7751rvoip_outb_p,
+ .mv_outw_p = hs7751rvoip_outw,
+ .mv_outl_p = hs7751rvoip_outl,
+
+ .mv_insb = hs7751rvoip_insb,
+ .mv_insw = hs7751rvoip_insw,
+ .mv_insl = hs7751rvoip_insl,
+ .mv_outsb = hs7751rvoip_outsb,
+ .mv_outsw = hs7751rvoip_outsw,
+ .mv_outsl = hs7751rvoip_outsl,
+
+ .mv_init_irq = hs7751rvoip_init_irq,
+ .mv_ioport_map = hs7751rvoip_ioport_map,
+};
+ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
new file mode 100644
index 00000000000..c26d9813d23
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/Kconfig
@@ -0,0 +1,14 @@
+if SH_R7780RP
+
+menu "R7780RP options"
+
+config SH_R7780MP
+ bool "R7780MP board support"
+ default y
+ help
+ Selecting this option will enable support for the mass-production
+ version of the R7780RP. If in doubt, say Y.
+
+endmenu
+
+endif
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
new file mode 100644
index 00000000000..f1776d02797
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the R7780RP-1 specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
new file mode 100644
index 00000000000..db92d6e6ae9
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/io.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Renesas Solutions Highlander R7780RP-1
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_r7780rp.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+static inline unsigned long port2adr(unsigned int port)
+{
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ if (port == 0x3f6)
+ return (PA_AREA5_IO + 0x80c);
+ else
+ return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
+ else
+ maybebadio((unsigned long)port);
+
+ return port;
+}
+
+static inline unsigned long port88796l(unsigned int port, int flag)
+{
+ unsigned long addr;
+
+ if (flag)
+ addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
+ else
+ addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
+
+ return addr;
+}
+
+/* The 7780 R7780RP-1 seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+static inline int shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
+#define CHECK_AX88796L_PORT(port) \
+ ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
+#else
+#define CHECK_AX88796L_PORT(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+u8 r7780rp_inb(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ return ctrl_inw(port88796l(port, 0)) & 0xff;
+ else if (PXSEG(port))
+ return ctrl_inb(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inb(pci_ioaddr(port));
+
+ return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 r7780rp_inb_p(unsigned long port)
+{
+ u8 v;
+
+ if (CHECK_AX88796L_PORT(port))
+ v = ctrl_inw(port88796l(port, 0)) & 0xff;
+ else if (PXSEG(port))
+ v = ctrl_inb(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ v = ctrl_inb(pci_ioaddr(port));
+ else
+ v = ctrl_inw(port2adr(port)) & 0xff;
+
+ ctrl_delay();
+
+ return v;
+}
+
+u16 r7780rp_inw(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (PXSEG(port))
+ return ctrl_inw(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inw(pci_ioaddr(port));
+ else
+ maybebadio(port);
+
+ return 0;
+}
+
+u32 r7780rp_inl(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (PXSEG(port))
+ return ctrl_inl(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return ctrl_inl(pci_ioaddr(port));
+ else
+ maybebadio(port);
+
+ return 0;
+}
+
+void r7780rp_outb(u8 value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ ctrl_outw(value, port88796l(port, 0));
+ else if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+}
+
+void r7780rp_outb_p(u8 value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ ctrl_outw(value, port88796l(port, 0));
+ else if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+
+ ctrl_delay();
+}
+
+void r7780rp_outw(u16 value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (PXSEG(port))
+ ctrl_outw(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outw(value, pci_ioaddr(port));
+ else
+ maybebadio(port);
+}
+
+void r7780rp_outl(u32 value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (PXSEG(port))
+ ctrl_outl(value, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ ctrl_outl(value, pci_ioaddr(port));
+ else
+ maybebadio(port);
+}
+
+void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
+{
+ volatile u16 *p;
+ u8 *buf = dst;
+
+ if (CHECK_AX88796L_PORT(port)) {
+ p = (volatile u16 *)port88796l(port, 0);
+ while (count--)
+ *buf++ = *p & 0xff;
+ } else if (PXSEG(port)) {
+ while (count--)
+ *buf++ = *(volatile u8 *)port;
+ } else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+ while (count--)
+ *buf++ = *bp;
+ } else {
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *buf++ = *p & 0xff;
+ }
+}
+
+void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
+{
+ volatile u16 *p;
+ u16 *buf = dst;
+
+ if (CHECK_AX88796L_PORT(port))
+ p = (volatile u16 *)port88796l(port, 1);
+ else if (PXSEG(port))
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile u16 *)pci_ioaddr(port);
+ else
+ p = (volatile u16 *)port2adr(port);
+
+ while (count--)
+ *buf++ = *p;
+}
+
+void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
+{
+ u32 *buf = dst;
+
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+ while (count--)
+ *buf++ = *p;
+ } else
+ maybebadio(port);
+}
+
+void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
+{
+ volatile u16 *p;
+ const u8 *buf = src;
+
+ if (CHECK_AX88796L_PORT(port)) {
+ p = (volatile u16 *)port88796l(port, 0);
+ while (count--)
+ *p = *buf++;
+ } else if (PXSEG(port))
+ while (count--)
+ ctrl_outb(*buf++, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+ while (count--)
+ *bp = *buf++;
+ } else {
+ p = (volatile u16 *)port2adr(port);
+ while (count--)
+ *p = *buf++;
+ }
+}
+
+void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
+{
+ volatile u16 *p;
+ const u16 *buf = src;
+
+ if (CHECK_AX88796L_PORT(port))
+ p = (volatile u16 *)port88796l(port, 1);
+ else if (PXSEG(port))
+ p = (volatile u16 *)port;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile u16 *)pci_ioaddr(port);
+ else
+ p = (volatile u16 *)port2adr(port);
+
+ while (count--)
+ *p = *buf++;
+}
+
+void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
+{
+ const u32 *buf = src;
+
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+ while (count--)
+ *p = *buf++;
+ } else
+ maybebadio(port);
+}
+
+void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
+{
+ if (CHECK_AX88796L_PORT(port))
+ return (void __iomem *)port88796l(port, size > 1);
+ else if (PXSEG(port))
+ return (void __iomem *)port;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return (void __iomem *)pci_ioaddr(port);
+
+ return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
new file mode 100644
index 00000000000..61d5e5d3c29
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/irq.c
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/sh/boards/renesas/r7780rp/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * Modified for R7780RP-1 by
+ * Atom Create Engineering Co., Ltd. 2002.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/r7780rp/r7780rp.h>
+
+#ifdef CONFIG_SH_R7780MP
+static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
+#else
+static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
+#endif
+
+static void enable_r7780rp_irq(unsigned int irq);
+static void disable_r7780rp_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_r7780rp_irq disable_r7780rp_irq
+
+static void ack_r7780rp_irq(unsigned int irq);
+static void end_r7780rp_irq(unsigned int irq);
+
+static unsigned int startup_r7780rp_irq(unsigned int irq)
+{
+ enable_r7780rp_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void disable_r7780rp_irq(unsigned int irq)
+{
+ unsigned short val;
+ unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
+
+ /* Set the priority in IPR to 0 */
+ val = ctrl_inw(IRLCNTR1);
+ val &= mask;
+ ctrl_outw(val, IRLCNTR1);
+}
+
+static void enable_r7780rp_irq(unsigned int irq)
+{
+ unsigned short val;
+ unsigned short value = (0x0001 << mask_pos[irq]);
+
+ /* Set priority in IPR back to original value */
+ val = ctrl_inw(IRLCNTR1);
+ val |= value;
+ ctrl_outw(val, IRLCNTR1);
+}
+
+static void ack_r7780rp_irq(unsigned int irq)
+{
+ disable_r7780rp_irq(irq);
+}
+
+static void end_r7780rp_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_r7780rp_irq(irq);
+}
+
+static struct hw_interrupt_type r7780rp_irq_type = {
+ .typename = "R7780RP-IRQ",
+ .startup = startup_r7780rp_irq,
+ .shutdown = shutdown_r7780rp_irq,
+ .enable = enable_r7780rp_irq,
+ .disable = disable_r7780rp_irq,
+ .ack = ack_r7780rp_irq,
+ .end = end_r7780rp_irq,
+};
+
+static void make_r7780rp_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &r7780rp_irq_type;
+ disable_r7780rp_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_r7780rp_IRQ(void)
+{
+ int i;
+
+ /* IRL0=PCI Slot #A
+ * IRL1=PCI Slot #B
+ * IRL2=PCI Slot #C
+ * IRL3=PCI Slot #D
+ * IRL4=CF Card
+ * IRL5=CF Card Insert
+ * IRL6=M66596
+ * IRL7=SD Card
+ * IRL8=Touch Panel
+ * IRL9=SCI
+ * IRL10=Serial
+ * IRL11=Extention #A
+ * IRL11=Extention #B
+ * IRL12=Debug LAN
+ * IRL13=Push Switch
+ * IRL14=ZiggBee IO
+ */
+
+ for (i=0; i<15; i++)
+ make_r7780rp_irq(i);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/led.c b/arch/sh/boards/renesas/r7780rp/led.c
new file mode 100644
index 00000000000..9f02766b6f5
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/led.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Atom Create Engineering Co., Ltd.
+ *
+ * May be copied or modified under the terms of GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * This file contains Renesas Solutions HIGHLANDER R7780RP-1 specific LED code.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/r7780rp/r7780rp.h>
+
+/* Cycle the LED's in the clasic Knightriger/Sun pattern */
+void heartbeat_r7780rp(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short *p = (volatile unsigned short *)PA_OBLED;
+ static unsigned bit = 0, up = 1;
+ unsigned bit_pos[] = {2, 1, 0, 3, 6, 5, 4, 7};
+
+ cnt += 1;
+ if (cnt < period)
+ return;
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
+ */
+ period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
+
+ *p = 1 << bit_pos[bit];
+ if (up)
+ if (bit == 7) {
+ bit--;
+ up = 0;
+ } else
+ bit++;
+ else if (bit == 0)
+ up = 1;
+ else
+ bit--;
+}
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
new file mode 100644
index 00000000000..b941aa0aa34
--- /dev/null
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -0,0 +1,163 @@
+/*
+ * arch/sh/boards/renesas/r7780rp/setup.c
+ *
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/clock.h>
+#include <asm/io.h>
+
+extern void heartbeat_r7780rp(void);
+extern void init_r7780rp_IRQ(void);
+
+static struct resource m66596_usb_host_resources[] = {
+ [0] = {
+ .start = 0xa4800000,
+ .end = 0xa4ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 6, /* irq number */
+ .end = 6,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device m66596_usb_host_device = {
+ .name = "m66596-hcd",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL, /* don't use dma */
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(m66596_usb_host_resources),
+ .resource = m66596_usb_host_resources,
+};
+
+static struct platform_device *r7780rp_devices[] __initdata = {
+ &m66596_usb_host_device,
+};
+
+static int __init r7780rp_devices_setup(void)
+{
+ return platform_add_devices(r7780rp_devices,
+ ARRAY_SIZE(r7780rp_devices));
+}
+
+/*
+ * Platform specific clocks
+ */
+static void ivdr_clk_enable(struct clk *clk)
+{
+ ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << 8), PA_IVDRCTL);
+}
+
+static void ivdr_clk_disable(struct clk *clk)
+{
+ ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << 8), PA_IVDRCTL);
+}
+
+static struct clk_ops ivdr_clk_ops = {
+ .enable = ivdr_clk_enable,
+ .disable = ivdr_clk_disable,
+};
+
+static struct clk ivdr_clk = {
+ .name = "ivdr_clk",
+ .ops = &ivdr_clk_ops,
+};
+
+static struct clk *r7780rp_clocks[] = {
+ &ivdr_clk,
+};
+
+static void r7780rp_power_off(void)
+{
+#ifdef CONFIG_SH_R7780MP
+ ctrl_outw(0x0001, PA_POFF);
+#endif
+}
+
+/*
+ * Initialize the board
+ */
+static void __init r7780rp_setup(char **cmdline_p)
+{
+ u16 ver = ctrl_inw(PA_VERREG);
+ int i;
+
+ device_initcall(r7780rp_devices_setup);
+
+ printk(KERN_INFO "Renesas Solutions Highlander R7780RP-1 support.\n");
+
+ printk(KERN_INFO "Board version: %d (revision %d), "
+ "FPGA version: %d (revision %d)\n",
+ (ver >> 12) & 0xf, (ver >> 8) & 0xf,
+ (ver >> 4) & 0xf, ver & 0xf);
+
+ /*
+ * Enable the important clocks right away..
+ */
+ for (i = 0; i < ARRAY_SIZE(r7780rp_clocks); i++) {
+ struct clk *clk = r7780rp_clocks[i];
+
+ clk_register(clk);
+ clk_enable(clk);
+ }
+
+ ctrl_outw(0x0000, PA_OBLED); /* Clear LED. */
+#ifndef CONFIG_SH_R7780MP
+ ctrl_outw(0x0001, PA_SDPOW); /* SD Power ON */
+#endif
+ ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x0100, PA_IVDRCTL); /* Si13112 */
+
+ pm_power_off = r7780rp_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_r7780rp __initmv = {
+ .mv_name = "Highlander R7780RP-1",
+ .mv_setup = r7780rp_setup,
+
+ .mv_nr_irqs = 109,
+
+ .mv_inb = r7780rp_inb,
+ .mv_inw = r7780rp_inw,
+ .mv_inl = r7780rp_inl,
+ .mv_outb = r7780rp_outb,
+ .mv_outw = r7780rp_outw,
+ .mv_outl = r7780rp_outl,
+
+ .mv_inb_p = r7780rp_inb_p,
+ .mv_inw_p = r7780rp_inw,
+ .mv_inl_p = r7780rp_inl,
+ .mv_outb_p = r7780rp_outb_p,
+ .mv_outw_p = r7780rp_outw,
+ .mv_outl_p = r7780rp_outl,
+
+ .mv_insb = r7780rp_insb,
+ .mv_insw = r7780rp_insw,
+ .mv_insl = r7780rp_insl,
+ .mv_outsb = r7780rp_outsb,
+ .mv_outsw = r7780rp_outsw,
+ .mv_outsl = r7780rp_outsl,
+
+ .mv_ioport_map = r7780rp_ioport_map,
+ .mv_init_irq = init_r7780rp_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_r7780rp,
+#endif
+};
+ALIAS_MV(r7780rp)
diff --git a/arch/sh/boards/renesas/rts7751r2d/Kconfig b/arch/sh/boards/renesas/rts7751r2d/Kconfig
new file mode 100644
index 00000000000..7780d1fb13f
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/Kconfig
@@ -0,0 +1,12 @@
+if SH_RTS7751R2D
+
+menu "RTS7751R2D options"
+
+config RTS7751R2D_REV11
+ bool "RTS7751R2D Rev. 1.1 board support"
+ help
+ Selecting this option will support version rev. 1.1.
+endmenu
+
+endif
+
diff --git a/arch/sh/boards/renesas/rts7751r2d/Makefile b/arch/sh/boards/renesas/rts7751r2d/Makefile
index daa53334bdc..686fc9ea598 100644
--- a/arch/sh/boards/renesas/rts7751r2d/Makefile
+++ b/arch/sh/boards/renesas/rts7751r2d/Makefile
@@ -1,10 +1,6 @@
#
# Makefile for the RTS7751R2D specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y := mach.o setup.o io.o irq.o led.o
+obj-y := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
index 123abbbc91e..135aa0b5e62 100644
--- a/arch/sh/boards/renesas/rts7751r2d/io.c
+++ b/arch/sh/boards/renesas/rts7751r2d/io.c
@@ -1,6 +1,4 @@
/*
- * linux/arch/sh/kernel/io_rts7751r2d.c
- *
* Copyright (C) 2001 Ian da Silva, Jeremy Siegel
* Based largely on io_se.c.
*
@@ -10,17 +8,13 @@
* placeholder code from io_rts7751r2d.c left in with the
* expectation of later SuperIO and PCMCIA access.
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
-#include <asm/io.h>
+#include <linux/pci.h>
#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
#include <asm/addrspace.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
/*
* The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
* of the 7751R processor, and has a SuperIO accessible via the PCI.
@@ -28,22 +22,6 @@
* like the other Solution Engine boards.
*/
-#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
static inline unsigned long port2adr(unsigned int port)
{
if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
@@ -52,7 +30,7 @@ static inline unsigned long port2adr(unsigned int port)
else
return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
else
- maybebadio(port2adr, (unsigned long)port);
+ maybebadio((unsigned long)port);
return port;
}
@@ -81,17 +59,6 @@ static inline int shifted_port(unsigned long port)
return 1;
}
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
- ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
#define CHECK_AX88796L_PORT(port) \
((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
@@ -112,8 +79,8 @@ unsigned char rts7751r2d_inb(unsigned long port)
return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
else if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return *(volatile unsigned char *)pci_ioaddr(port);
else
return (*(volatile unsigned short *)port2adr(port) & 0xff);
}
@@ -126,11 +93,12 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
else if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ v = *(volatile unsigned char *)pci_ioaddr(port);
else
v = (*(volatile unsigned short *)port2adr(port) & 0xff);
- delay();
+
+ ctrl_delay();
return v;
}
@@ -138,13 +106,13 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
unsigned short rts7751r2d_inw(unsigned long port)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(inw, port);
+ maybebadio(port);
else if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return *(volatile unsigned short *)pci_ioaddr(port);
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
@@ -152,13 +120,13 @@ unsigned short rts7751r2d_inw(unsigned long port)
unsigned int rts7751r2d_inl(unsigned long port)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(inl, port);
+ maybebadio(port);
else if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- return *(volatile unsigned long *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ return *(volatile unsigned long *)pci_ioaddr(port);
else
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
@@ -169,8 +137,8 @@ void rts7751r2d_outb(unsigned char value, unsigned long port)
*((volatile unsigned short *)port88796l(port, 0)) = value;
else if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(volatile unsigned char *)PCI_IOMAP(port) = value;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ *(volatile unsigned char *)pci_ioaddr(port) = value;
else
*(volatile unsigned short *)port2adr(port) = value;
}
@@ -181,143 +149,152 @@ void rts7751r2d_outb_p(unsigned char value, unsigned long port)
*((volatile unsigned short *)port88796l(port, 0)) = value;
else if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(volatile unsigned char *)PCI_IOMAP(port) = value;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ *(volatile unsigned char *)pci_ioaddr(port) = value;
else
*(volatile unsigned short *)port2adr(port) = value;
- delay();
+
+ ctrl_delay();
}
void rts7751r2d_outw(unsigned short value, unsigned long port)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(outw, port);
+ maybebadio(port);
else if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(volatile unsigned short *)PCI_IOMAP(port) = value;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ *(volatile unsigned short *)pci_ioaddr(port) = value;
else
- maybebadio(outw, port);
+ maybebadio(port);
}
void rts7751r2d_outl(unsigned int value, unsigned long port)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(outl, port);
+ maybebadio(port);
else if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- *(volatile unsigned long *)PCI_IOMAP(port) = value;
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ *(volatile unsigned long *)pci_ioaddr(port) = value;
else
- maybebadio(outl, port);
+ maybebadio(port);
}
void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
{
+ unsigned long a = (unsigned long)addr;
volatile __u8 *bp;
volatile __u16 *p;
- unsigned char *s = addr;
if (CHECK_AX88796L_PORT(port)) {
p = (volatile unsigned short *)port88796l(port, 0);
- while (count--) *s++ = *p & 0xff;
+ while (count--)
+ ctrl_outb(*p & 0xff, a++);
} else if (PXSEG(port))
- while (count--) *s++ = *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- bp = (__u8 *)PCI_IOMAP(port);
- while (count--) *s++ = *bp;
+ while (count--)
+ ctrl_outb(ctrl_inb(port), a++);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ bp = (__u8 *)pci_ioaddr(port);
+ while (count--)
+ ctrl_outb(*bp, a++);
} else {
p = (volatile unsigned short *)port2adr(port);
- while (count--) *s++ = *p & 0xff;
+ while (count--)
+ ctrl_outb(*p & 0xff, a++);
}
}
void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
{
+ unsigned long a = (unsigned long)addr;
volatile __u16 *p;
- __u16 *s = addr;
if (CHECK_AX88796L_PORT(port))
p = (volatile unsigned short *)port88796l(port, 1);
else if (PXSEG(port))
p = (volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- p = (volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile unsigned short *)pci_ioaddr(port);
else
p = (volatile unsigned short *)port2adr(port);
- while (count--) *s++ = *p;
+ while (count--)
+ ctrl_outw(*p, a++);
}
void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(insl, port);
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
- __u32 *s = addr;
-
- while (count--) *s++ = *p;
+ maybebadio(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ unsigned long a = (unsigned long)addr;
+
+ while (count--) {
+ ctrl_outl(ctrl_inl(pci_ioaddr(port)), a);
+ a += 4;
+ }
} else
- maybebadio(insl, port);
+ maybebadio(port);
}
void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
{
+ unsigned long a = (unsigned long)addr;
volatile __u8 *bp;
volatile __u16 *p;
- const __u8 *s = addr;
if (CHECK_AX88796L_PORT(port)) {
p = (volatile unsigned short *)port88796l(port, 0);
- while (count--) *p = *s++;
+ while (count--)
+ *p = ctrl_inb(a++);
} else if (PXSEG(port))
- while (count--) *(volatile unsigned char *)port = *s++;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- bp = (__u8 *)PCI_IOMAP(port);
- while (count--) *bp = *s++;
+ while (count--)
+ ctrl_outb(a++, port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ bp = (__u8 *)pci_ioaddr(port);
+ while (count--)
+ *bp = ctrl_inb(a++);
} else {
p = (volatile unsigned short *)port2adr(port);
- while (count--) *p = *s++;
+ while (count--)
+ *p = ctrl_inb(a++);
}
}
void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
{
+ unsigned long a = (unsigned long)addr;
volatile __u16 *p;
- const __u16 *s = addr;
if (CHECK_AX88796L_PORT(port))
p = (volatile unsigned short *)port88796l(port, 1);
else if (PXSEG(port))
p = (volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
- p = (volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port))
+ p = (volatile unsigned short *)pci_ioaddr(port);
else
p = (volatile unsigned short *)port2adr(port);
- while (count--) *p = *s++;
+
+ while (count--) {
+ ctrl_outw(*p, a);
+ a += 2;
+ }
}
void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
{
if (CHECK_AX88796L_PORT(port))
- maybebadio(outsl, port);
- else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
- volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
- const __u32 *s = addr;
-
- while (count--) *p = *s++;
+ maybebadio(port);
+ else if (is_pci_ioaddr(port) || shifted_port(port)) {
+ unsigned long a = (unsigned long)addr;
+
+ while (count--) {
+ ctrl_outl(ctrl_inl(a), pci_ioaddr(port));
+ a += 4;
+ }
} else
- maybebadio(outsl, port);
-}
-
-void *rts7751r2d_ioremap(unsigned long offset, unsigned long size)
-{
- if (offset >= 0xfd000000)
- return (void *)offset;
- else
- return (void *)P2SEGADDR(offset);
+ maybebadio(port);
}
-EXPORT_SYMBOL(rts7751r2d_ioremap);
unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
{
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
index 154535440bb..c915e7a3693 100644
--- a/arch/sh/boards/renesas/rts7751r2d/irq.c
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -41,30 +41,24 @@ static unsigned int startup_rts7751r2d_irq(unsigned int irq)
static void disable_rts7751r2d_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short val;
unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
/* Set the priority in IPR to 0 */
- local_irq_save(flags);
val = ctrl_inw(IRLCNTR1);
val &= mask;
ctrl_outw(val, IRLCNTR1);
- local_irq_restore(flags);
}
static void enable_rts7751r2d_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short val;
unsigned short value = (0x0001 << mask_pos[irq]);
/* Set priority in IPR back to original value */
- local_irq_save(flags);
val = ctrl_inw(IRLCNTR1);
val |= value;
ctrl_outw(val, IRLCNTR1);
- local_irq_restore(flags);
}
int rts7751r2d_irq_demux(int irq)
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
index 4d16de71fac..e14a13d12d4 100644
--- a/arch/sh/boards/renesas/rts7751r2d/led.c
+++ b/arch/sh/boards/renesas/rts7751r2d/led.c
@@ -12,8 +12,6 @@
#include <asm/io.h>
#include <asm/rts7751r2d/rts7751r2d.h>
-extern unsigned int debug_counter;
-
#ifdef CONFIG_HEARTBEAT
#include <linux/sched.h>
@@ -55,12 +53,3 @@ void rts7751r2d_led(unsigned short value)
ctrl_outw(value, PA_OUTPORT);
}
-void debug_led_disp(void)
-{
- unsigned short value;
-
- value = (unsigned short)debug_counter++;
- rts7751r2d_led(value);
- if (value == 0xff)
- debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
deleted file mode 100644
index 5ed9e97ea19..00000000000
--- a/arch/sh/boards/renesas/rts7751r2d/mach.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_rts7751r2d.c
- *
- * Minor tweak of mach_se.c file to reference rts7751r2d-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales RTS7751R2D
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/rts7751r2d/io.h>
-
-extern void heartbeat_rts7751r2d(void);
-extern void init_rts7751r2d_IRQ(void);
-extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
-extern int rts7751r2d_irq_demux(int irq);
-
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
-extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_rts7751r2d __initmv = {
- .mv_nr_irqs = 72,
-
- .mv_inb = rts7751r2d_inb,
- .mv_inw = rts7751r2d_inw,
- .mv_inl = rts7751r2d_inl,
- .mv_outb = rts7751r2d_outb,
- .mv_outw = rts7751r2d_outw,
- .mv_outl = rts7751r2d_outl,
-
- .mv_inb_p = rts7751r2d_inb_p,
- .mv_inw_p = rts7751r2d_inw,
- .mv_inl_p = rts7751r2d_inl,
- .mv_outb_p = rts7751r2d_outb_p,
- .mv_outw_p = rts7751r2d_outw,
- .mv_outl_p = rts7751r2d_outl,
-
- .mv_insb = rts7751r2d_insb,
- .mv_insw = rts7751r2d_insw,
- .mv_insl = rts7751r2d_insl,
- .mv_outsb = rts7751r2d_outsb,
- .mv_outsw = rts7751r2d_outsw,
- .mv_outsl = rts7751r2d_outsl,
-
- .mv_ioremap = rts7751r2d_ioremap,
- .mv_isa_port2addr = rts7751r2d_isa_port2addr,
- .mv_init_irq = init_rts7751r2d_IRQ,
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_rts7751r2d,
-#endif
- .mv_irq_demux = rts7751r2d_irq_demux,
-
-#ifdef CONFIG_USB_OHCI_HCD
- .mv_consistent_alloc = voyagergx_consistent_alloc,
- .mv_consistent_free = voyagergx_consistent_free,
-#endif
-};
-ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 2587fd1a024..20597a6e670 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -1,31 +1,142 @@
/*
- * linux/arch/sh/kernel/setup_rts7751r2d.c
- *
- * Copyright (C) 2000 Kazumoto Kojima
- *
* Renesas Technology Sales RTS7751R2D Support.
*
- * Modified for RTS7751R2D by
- * Atom Create Engineering Co., Ltd. 2002.
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2004 - 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*/
-
#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/pm.h>
#include <asm/io.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/machvec.h>
+#include <asm/mach/rts7751r2d.h>
+#include <asm/voyagergx.h>
+
+extern void heartbeat_rts7751r2d(void);
+extern void init_rts7751r2d_IRQ(void);
+extern int rts7751r2d_irq_demux(int irq);
+
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
+extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
+
+static struct plat_serial8250_port uart_platform_data[] = {
+ {
+ .membase = (void *)VOYAGER_UART_BASE,
+ .mapbase = VOYAGER_UART_BASE,
+ .iotype = UPIO_MEM,
+ .irq = VOYAGER_UART0_IRQ,
+ .flags = UPF_BOOT_AUTOCONF,
+ .regshift = 2,
+ .uartclk = (9600 * 16),
+ }, {
+ .flags = 0,
+ },
+};
+
+static void __init voyagergx_serial_init(void)
+{
+ unsigned long val;
+
+ /*
+ * GPIO Control
+ */
+ val = inl(GPIO_MUX_HIGH);
+ val |= 0x00001fe0;
+ outl(val, GPIO_MUX_HIGH);
+
+ /*
+ * Power Mode Gate
+ */
+ val = inl(POWER_MODE0_GATE);
+ val |= (POWER_MODE0_GATE_U0 | POWER_MODE0_GATE_U1);
+ outl(val, POWER_MODE0_GATE);
+
+ val = inl(POWER_MODE1_GATE);
+ val |= (POWER_MODE1_GATE_U0 | POWER_MODE1_GATE_U1);
+ outl(val, POWER_MODE1_GATE);
+}
+
+static struct platform_device uart_device = {
+ .name = "serial8250",
+ .id = -1,
+ .dev = {
+ .platform_data = uart_platform_data,
+ },
+};
+
+static struct platform_device *rts7751r2d_devices[] __initdata = {
+ &uart_device,
+};
-unsigned int debug_counter;
+static int __init rts7751r2d_devices_setup(void)
+{
+ return platform_add_devices(rts7751r2d_devices,
+ ARRAY_SIZE(rts7751r2d_devices));
+}
-const char *get_system_type(void)
+static void rts7751r2d_power_off(void)
{
- return "RTS7751R2D";
+ ctrl_outw(0x0001, PA_POWOFF);
}
/*
* Initialize the board
*/
-void __init platform_setup(void)
+static void __init rts7751r2d_setup(char **cmdline_p)
{
- printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+ device_initcall(rts7751r2d_devices_setup);
+
ctrl_outw(0x0000, PA_OUTPORT);
- debug_counter = 0;
+ pm_power_off = rts7751r2d_power_off;
+
+ voyagergx_serial_init();
+
+ printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_rts7751r2d __initmv = {
+ .mv_name = "RTS7751R2D",
+ .mv_setup = rts7751r2d_setup,
+ .mv_nr_irqs = 72,
+
+ .mv_inb = rts7751r2d_inb,
+ .mv_inw = rts7751r2d_inw,
+ .mv_inl = rts7751r2d_inl,
+ .mv_outb = rts7751r2d_outb,
+ .mv_outw = rts7751r2d_outw,
+ .mv_outl = rts7751r2d_outl,
+
+ .mv_inb_p = rts7751r2d_inb_p,
+ .mv_inw_p = rts7751r2d_inw,
+ .mv_inl_p = rts7751r2d_inl,
+ .mv_outb_p = rts7751r2d_outb_p,
+ .mv_outw_p = rts7751r2d_outw,
+ .mv_outl_p = rts7751r2d_outl,
+
+ .mv_insb = rts7751r2d_insb,
+ .mv_insw = rts7751r2d_insw,
+ .mv_insl = rts7751r2d_insl,
+ .mv_outsb = rts7751r2d_outsb,
+ .mv_outsw = rts7751r2d_outsw,
+ .mv_outsl = rts7751r2d_outsl,
+
+ .mv_init_irq = init_rts7751r2d_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_rts7751r2d,
+#endif
+ .mv_irq_demux = rts7751r2d_irq_demux,
+
+#ifdef CONFIG_USB_SM501
+ .mv_consistent_alloc = voyagergx_consistent_alloc,
+ .mv_consistent_free = voyagergx_consistent_free,
+#endif
+};
+ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/Makefile b/arch/sh/boards/renesas/sh7710voipgw/Makefile
new file mode 100644
index 00000000000..77037567633
--- /dev/null
+++ b/arch/sh/boards/renesas/sh7710voipgw/Makefile
@@ -0,0 +1 @@
+obj-y := setup.o
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
new file mode 100644
index 00000000000..e57e7afab8c
--- /dev/null
+++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c
@@ -0,0 +1,109 @@
+/*
+ * Renesas Technology SH7710 VoIP Gateway
+ *
+ * Copyright (C) 2006 Ranjit Deshpande
+ * Kenati Technologies Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * Initialize IRQ setting
+ */
+static void __init sh7710voipgw_init_irq(void)
+{
+ /* Disable all interrupts in IPR registers */
+ ctrl_outw(0x0, INTC_IPRA);
+ ctrl_outw(0x0, INTC_IPRB);
+ ctrl_outw(0x0, INTC_IPRC);
+ ctrl_outw(0x0, INTC_IPRD);
+ ctrl_outw(0x0, INTC_IPRE);
+ ctrl_outw(0x0, INTC_IPRF);
+ ctrl_outw(0x0, INTC_IPRG);
+ ctrl_outw(0x0, INTC_IPRH);
+ ctrl_outw(0x0, INTC_IPRI);
+
+ /* Ack all interrupt sources in the IRR0 register */
+ ctrl_outb(0x3f, INTC_IRR0);
+
+ /* Use IRQ0 - IRQ3 as active low interrupt lines i.e. disable
+ * IRL mode.
+ */
+ ctrl_outw(0x2aa, INTC_ICR1);
+
+ /* Now make IPR interrupts */
+ make_ipr_irq(TIMER2_IRQ, TIMER2_IPR_ADDR,
+ TIMER2_IPR_POS, TIMER2_PRIORITY);
+ make_ipr_irq(WDT_IRQ, WDT_IPR_ADDR, WDT_IPR_POS, WDT_PRIORITY);
+
+ /* SCIF0 */
+ make_ipr_irq(SCIF0_ERI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+ SCIF0_PRIORITY);
+ make_ipr_irq(SCIF0_RXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+ SCIF0_PRIORITY);
+ make_ipr_irq(SCIF0_BRI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+ SCIF0_PRIORITY);
+ make_ipr_irq(SCIF0_TXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+ SCIF0_PRIORITY);
+
+ /* DMAC-1 */
+ make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ make_ipr_irq(DMTE2_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ make_ipr_irq(DMTE3_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+
+ /* DMAC-2 */
+ make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+ make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+ /* IPSEC */
+ make_ipr_irq(IPSEC_IRQ, IPSEC_IPR_ADDR, IPSEC_IPR_POS, IPSEC_PRIORITY);
+
+ /* EDMAC */
+ make_ipr_irq(EDMAC0_IRQ, EDMAC0_IPR_ADDR, EDMAC0_IPR_POS,
+ EDMAC0_PRIORITY);
+ make_ipr_irq(EDMAC1_IRQ, EDMAC1_IPR_ADDR, EDMAC1_IPR_POS,
+ EDMAC1_PRIORITY);
+ make_ipr_irq(EDMAC2_IRQ, EDMAC2_IPR_ADDR, EDMAC2_IPR_POS,
+ EDMAC2_PRIORITY);
+
+ /* SIOF0 */
+ make_ipr_irq(SIOF0_ERI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+ SIOF0_PRIORITY);
+ make_ipr_irq(SIOF0_TXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+ SIOF0_PRIORITY);
+ make_ipr_irq(SIOF0_RXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+ SIOF0_PRIORITY);
+ make_ipr_irq(SIOF0_CCI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+ SIOF0_PRIORITY);
+
+ /* SIOF1 */
+ make_ipr_irq(SIOF1_ERI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+ SIOF1_PRIORITY);
+ make_ipr_irq(SIOF1_TXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+ SIOF1_PRIORITY);
+ make_ipr_irq(SIOF1_RXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+ SIOF1_PRIORITY);
+ make_ipr_irq(SIOF1_CCI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+ SIOF1_PRIORITY);
+
+ /* SLIC IRQ's */
+ make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+ make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh7710voipgw __initmv = {
+ .mv_name = "SH7710 VoIP Gateway",
+ .mv_nr_irqs = 104,
+ .mv_init_irq = sh7710voipgw_init_irq,
+};
+ALIAS_MV(sh7710voipgw)
diff --git a/arch/sh/boards/renesas/systemh/io.c b/arch/sh/boards/renesas/systemh/io.c
index cf979011aa9..cde6e5d192c 100644
--- a/arch/sh/boards/renesas/systemh/io.c
+++ b/arch/sh/boards/renesas/systemh/io.c
@@ -5,66 +5,25 @@
* Based largely on io_se.c.
*
* I/O routine for Hitachi 7751 Systemh.
- *
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
-#include <asm/systemh/7751systemh.h>
+#include <linux/pci.h>
+#include <asm/systemh7751.h>
#include <asm/addrspace.h>
#include <asm/io.h>
-#include <linux/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
-/*
- * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
- * of the 7751 processor, and has a SuperIO accessible on its memory
- * bus.
- */
-
-#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
#define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
of smc lan chip*/
-
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
static inline volatile __u16 *
port2adr(unsigned int port)
{
if (port >= 0x2000)
return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
- else
- return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
- maybebadio(name,(unsigned long)port);
+ maybebadio((unsigned long)port);
return (volatile __u16*)port;
}
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
- ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
/*
* General outline: remap really low stuff [eventually] to SuperIO,
* stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -76,8 +35,8 @@ unsigned char sh7751systemh_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned char *)pci_ioaddr(port);
else if (port <= 0x3F1)
return *(volatile unsigned char *)ETHER_IOMAP(port);
else
@@ -90,13 +49,13 @@ unsigned char sh7751systemh_inb_p(unsigned long port)
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ v = *(volatile unsigned char *)pci_ioaddr(port);
else if (port <= 0x3F1)
v = *(volatile unsigned char *)ETHER_IOMAP(port);
else
v = (*port2adr(port))&0xff;
- delay();
+ ctrl_delay();
return v;
}
@@ -104,14 +63,14 @@ unsigned short sh7751systemh_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else if (port <= 0x3F1)
return *(volatile unsigned int *)ETHER_IOMAP(port);
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
@@ -119,14 +78,14 @@ unsigned int sh7751systemh_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else if (port <= 0x3F1)
return *(volatile unsigned int *)ETHER_IOMAP(port);
else
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
@@ -135,8 +94,8 @@ void sh7751systemh_outb(unsigned char value, unsigned long port)
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else if (port <= 0x3F1)
*(volatile unsigned char *)ETHER_IOMAP(port) = value;
else
@@ -147,37 +106,37 @@ void sh7751systemh_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else if (port <= 0x3F1)
*(volatile unsigned char *)ETHER_IOMAP(port) = value;
else
*(port2adr(port)) = value;
- delay();
+ ctrl_delay();
}
void sh7751systemh_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else if (port <= 0x3F1)
*(volatile unsigned short *)ETHER_IOMAP(port) = value;
else
- maybebadio(outw, port);
+ maybebadio(port);
}
void sh7751systemh_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned long*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned long*)pci_ioaddr(port)) = value;
else
- maybebadio(outl, port);
+ maybebadio(port);
}
void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
@@ -194,7 +153,7 @@ void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
{
- maybebadio(insl, port);
+ maybebadio(port);
}
void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -211,73 +170,5 @@ void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long cou
void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
{
- maybebadio(outsw, port);
-}
-
-/* For read/write calls, just copy generic (pass-thru); PCIMBR is */
-/* already set up. For a larger memory space, these would need to */
-/* reset PCIMBR as needed on a per-call basis... */
-
-unsigned char sh7751systemh_readb(unsigned long addr)
-{
- return *(volatile unsigned char*)addr;
-}
-
-unsigned short sh7751systemh_readw(unsigned long addr)
-{
- return *(volatile unsigned short*)addr;
-}
-
-unsigned int sh7751systemh_readl(unsigned long addr)
-{
- return *(volatile unsigned long*)addr;
-}
-
-void sh7751systemh_writeb(unsigned char b, unsigned long addr)
-{
- *(volatile unsigned char*)addr = b;
-}
-
-void sh7751systemh_writew(unsigned short b, unsigned long addr)
-{
- *(volatile unsigned short*)addr = b;
-}
-
-void sh7751systemh_writel(unsigned int b, unsigned long addr)
-{
- *(volatile unsigned long*)addr = b;
-}
-
-
-
-/* Map ISA bus address to the real address. Only for PCMCIA. */
-
-/* ISA page descriptor. */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
- int idx;
-
- if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
- return -1;
-
- idx = start >> 12;
- sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
- printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
- start, length, offset, idx, sh_isa_memmap[idx]);
- return 0;
-}
-#endif
-
-unsigned long
-sh7751systemh_isa_port2addr(unsigned long offset)
-{
- int idx;
-
- idx = (offset >> 12) & 0xff;
- offset &= 0xfff;
- return sh_isa_memmap[idx] + offset;
+ maybebadio(port);
}
diff --git a/arch/sh/boards/renesas/systemh/irq.c b/arch/sh/boards/renesas/systemh/irq.c
index 8372d967f60..8d016dae233 100644
--- a/arch/sh/boards/renesas/systemh/irq.c
+++ b/arch/sh/boards/renesas/systemh/irq.c
@@ -15,7 +15,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include <asm/mach/7751systemh.h>
+#include <asm/systemh7751.h>
#include <asm/smc37c93x.h>
/* address of external interrupt mask register
@@ -57,12 +57,9 @@ static void shutdown_systemh_irq(unsigned int irq)
static void disable_systemh_irq(unsigned int irq)
{
if (systemh_irq_mask_register) {
- unsigned long flags;
unsigned long val, mask = 0x01 << 1;
/* Clear the "irq"th bit in the mask and set it in the request */
- local_irq_save(flags);
-
val = ctrl_inl((unsigned long)systemh_irq_mask_register);
val &= ~mask;
ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
@@ -70,23 +67,18 @@ static void disable_systemh_irq(unsigned int irq)
val = ctrl_inl((unsigned long)systemh_irq_request_register);
val |= mask;
ctrl_outl(val, (unsigned long)systemh_irq_request_register);
-
- local_irq_restore(flags);
}
}
static void enable_systemh_irq(unsigned int irq)
{
if (systemh_irq_mask_register) {
- unsigned long flags;
unsigned long val, mask = 0x01 << 1;
/* Set "irq"th bit in the mask register */
- local_irq_save(flags);
val = ctrl_inl((unsigned long)systemh_irq_mask_register);
val |= mask;
ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
- local_irq_restore(flags);
}
}
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
index 826fa3d7669..a8467bf90c2 100644
--- a/arch/sh/boards/renesas/systemh/setup.c
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -15,28 +15,21 @@
* for more details.
*/
#include <linux/init.h>
-#include <asm/mach/7751systemh.h>
-#include <asm/mach/io.h>
#include <asm/machvec.h>
+#include <asm/systemh7751.h>
extern void make_systemh_irq(unsigned int irq);
-const char *get_system_type(void)
-{
- return "7751 SystemH";
-}
-
/*
* Initialize IRQ setting
*/
-void __init init_7751systemh_IRQ(void)
+static void __init sh7751systemh_init_irq(void)
{
-/* make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */
-/* make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */
make_systemh_irq(0xb); /* Ethernet interrupt */
}
struct sh_machine_vector mv_7751systemh __initmv = {
+ .mv_name = "7751 SystemH",
.mv_nr_irqs = 72,
.mv_inb = sh7751systemh_inb,
@@ -60,21 +53,6 @@ struct sh_machine_vector mv_7751systemh __initmv = {
.mv_outsw = sh7751systemh_outsw,
.mv_outsl = sh7751systemh_outsl,
- .mv_readb = sh7751systemh_readb,
- .mv_readw = sh7751systemh_readw,
- .mv_readl = sh7751systemh_readl,
- .mv_writeb = sh7751systemh_writeb,
- .mv_writew = sh7751systemh_writew,
- .mv_writel = sh7751systemh_writel,
-
- .mv_isa_port2addr = sh7751systemh_isa_port2addr,
-
- .mv_init_irq = init_7751systemh_IRQ,
+ .mv_init_irq = sh7751system_init_irq,
};
ALIAS_MV(7751systemh)
-
-int __init platform_setup(void)
-{
- return 0;
-}
-
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
index bea6c572ad8..a3a37c9aad2 100644
--- a/arch/sh/boards/saturn/setup.c
+++ b/arch/sh/boards/saturn/setup.c
@@ -9,22 +9,17 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
-
#include <asm/io.h>
#include <asm/machvec.h>
#include <asm/mach/io.h>
extern int saturn_irq_demux(int irq_nr);
-const char *get_system_type(void)
-{
- return "Sega Saturn";
-}
-
/*
* The Machine Vector
*/
struct sh_machine_vector mv_saturn __initmv = {
+ .mv_name = "Sega Saturn",
.mv_nr_irqs = 80, /* Fix this later */
.mv_isa_port2addr = saturn_isa_port2addr,
@@ -33,11 +28,4 @@ struct sh_machine_vector mv_saturn __initmv = {
.mv_ioremap = saturn_ioremap,
.mv_iounmap = saturn_iounmap,
};
-
ALIAS_MV(saturn)
-
-int __init platform_setup(void)
-{
- return 0;
-}
-
diff --git a/arch/sh/boards/se/7300/io.c b/arch/sh/boards/se/7300/io.c
index f449a94ddff..8a03d7a52a7 100644
--- a/arch/sh/boards/se/7300/io.c
+++ b/arch/sh/boards/se/7300/io.c
@@ -9,8 +9,8 @@
*/
#include <linux/kernel.h>
-#include <asm/mach/se7300.h>
#include <asm/io.h>
+#include <asm/se7300.h>
#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
badio(inw, port);
}
+#ifdef CONFIG_SMC91X
/* MSTLANEX01 LAN at 0xb400:0000 */
static struct iop laniop = {
.start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
.outb = simple_outb,
.outw = simple_outw,
};
+#endif
/* NE2000 pc card NIC */
static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
.outw = simple_outw,
};
+#ifdef CONFIG_IDE
/* CF in CF slot */
static struct iop cfiop = {
.base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
.outb = pcc_outb,
.outw = simple_outw,
};
+#endif
static __inline__ struct iop *
port2iop(unsigned long port)
{
if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
else if (laniop.check(&laniop, port))
return &laniop;
#endif
diff --git a/arch/sh/boards/se/7300/irq.c b/arch/sh/boards/se/7300/irq.c
index 216a78d1a10..ad1034f98a2 100644
--- a/arch/sh/boards/se/7300/irq.c
+++ b/arch/sh/boards/se/7300/irq.c
@@ -11,7 +11,7 @@
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/mach/se7300.h>
+#include <asm/se7300.h>
/*
* Initialize IRQ setting
diff --git a/arch/sh/boards/se/7300/led.c b/arch/sh/boards/se/7300/led.c
index ad51f0a9c1e..4d03bb7774b 100644
--- a/arch/sh/boards/se/7300/led.c
+++ b/arch/sh/boards/se/7300/led.c
@@ -12,24 +12,10 @@
*/
#include <linux/sched.h>
-#include <asm/mach/se7300.h>
-
-static void
-mach_led(int position, int value)
-{
- volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
- if (value) {
- *p |= (1 << 8);
- } else {
- *p &= ~(1 << 8);
- }
-}
-
+#include <asm/se7300.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_7300se(void)
+void heartbeat_7300se(void)
{
static unsigned int cnt = 0, period = 0;
volatile unsigned short *p = (volatile unsigned short *) PA_LED;
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
index ebcd98d4c08..6f082a722d4 100644
--- a/arch/sh/boards/se/7300/setup.c
+++ b/arch/sh/boards/se/7300/setup.c
@@ -9,23 +9,16 @@
#include <linux/init.h>
#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se7300.h>
void heartbeat_7300se(void);
void init_7300se_IRQ(void);
-const char *
-get_system_type(void)
-{
- return "SolutionEngine 7300";
-}
-
/*
* The Machine Vector
*/
-
struct sh_machine_vector mv_7300se __initmv = {
+ .mv_name = "SolutionEngine 7300",
.mv_nr_irqs = 109,
.mv_inb = sh7300se_inb,
.mv_inw = sh7300se_inw,
@@ -53,13 +46,4 @@ struct sh_machine_vector mv_7300se __initmv = {
.mv_heartbeat = heartbeat_7300se,
#endif
};
-
ALIAS_MV(7300se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
diff --git a/arch/sh/boards/se/73180/io.c b/arch/sh/boards/se/73180/io.c
index 755df5ac4a4..72715575458 100644
--- a/arch/sh/boards/se/73180/io.c
+++ b/arch/sh/boards/se/73180/io.c
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
badio(inw, port);
}
+#ifdef CONFIG_SMC91X
/* MSTLANEX01 LAN at 0xb400:0000 */
static struct iop laniop = {
.start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
.outb = simple_outb,
.outw = simple_outw,
};
+#endif
/* NE2000 pc card NIC */
static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
.outw = simple_outw,
};
+#ifdef CONFIG_IDE
/* CF in CF slot */
static struct iop cfiop = {
.base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
.outb = pcc_outb,
.outw = simple_outw,
};
+#endif
static __inline__ struct iop *
port2iop(unsigned long port)
{
if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
else if (laniop.check(&laniop, port))
return &laniop;
#endif
diff --git a/arch/sh/boards/se/73180/irq.c b/arch/sh/boards/se/73180/irq.c
index 4344d0ef24a..2c62b8ea350 100644
--- a/arch/sh/boards/se/73180/irq.c
+++ b/arch/sh/boards/se/73180/irq.c
@@ -7,7 +7,6 @@
* Modified for SH-Mobile SolutionEngine 73180 Support
* by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
*
- *
*/
#include <linux/init.h>
@@ -17,14 +16,6 @@
#include <asm/mach/se73180.h>
static int
-intreq2irq(int i)
-{
- if (i == 5)
- return 10;
- return 32 + 7 - i;
-}
-
-static int
irq2intreq(int irq)
{
if (irq == 10)
diff --git a/arch/sh/boards/se/73180/led.c b/arch/sh/boards/se/73180/led.c
index 610439fde6e..4b72e9a3ead 100644
--- a/arch/sh/boards/se/73180/led.c
+++ b/arch/sh/boards/se/73180/led.c
@@ -14,21 +14,8 @@
#include <linux/sched.h>
#include <asm/mach/se73180.h>
-static void
-mach_led(int position, int value)
-{
- volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
- if (value) {
- *p |= (1 << LED_SHIFT);
- } else {
- *p &= ~(1 << LED_SHIFT);
- }
-}
-
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_73180se(void)
+void heartbeat_73180se(void)
{
static unsigned int cnt = 0, period = 0;
volatile unsigned short *p = (volatile unsigned short *) PA_LED;
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index cdb7b5f8d94..b38ef50a160 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -11,23 +11,17 @@
#include <linux/init.h>
#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se73180.h>
+#include <asm/irq.h>
void heartbeat_73180se(void);
void init_73180se_IRQ(void);
-const char *
-get_system_type(void)
-{
- return "SolutionEngine 73180";
-}
-
/*
* The Machine Vector
*/
-
struct sh_machine_vector mv_73180se __initmv = {
+ .mv_name = "SolutionEngine 73180",
.mv_nr_irqs = 108,
.mv_inb = sh73180se_inb,
.mv_inw = sh73180se_inw,
@@ -51,17 +45,9 @@ struct sh_machine_vector mv_73180se __initmv = {
.mv_outsl = sh73180se_outsl,
.mv_init_irq = init_73180se_IRQ,
+ .mv_irq_demux = shmse_irq_demux,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_73180se,
#endif
};
-
ALIAS_MV(73180se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
diff --git a/arch/sh/boards/se/7343/Makefile b/arch/sh/boards/se/7343/Makefile
new file mode 100644
index 00000000000..4291069c0b4
--- /dev/null
+++ b/arch/sh/boards/se/7343/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7343 SolutionEngine specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7343/io.c b/arch/sh/boards/se/7343/io.c
new file mode 100644
index 00000000000..646661a146a
--- /dev/null
+++ b/arch/sh/boards/se/7343/io.c
@@ -0,0 +1,275 @@
+/*
+ * arch/sh/boards/se/7343/io.c
+ *
+ * I/O routine for SH-Mobile3AS 7343 SolutionEngine.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
+
+struct iop {
+ unsigned long start, end;
+ unsigned long base;
+ struct iop *(*check) (struct iop * p, unsigned long port);
+ unsigned char (*inb) (struct iop * p, unsigned long port);
+ unsigned short (*inw) (struct iop * p, unsigned long port);
+ void (*outb) (struct iop * p, unsigned char value, unsigned long port);
+ void (*outw) (struct iop * p, unsigned short value, unsigned long port);
+};
+
+struct iop *
+simple_check(struct iop *p, unsigned long port)
+{
+ static int count;
+
+ if (count < 100)
+ count++;
+
+ port &= 0xFFFF;
+
+ if ((p->start <= port) && (port <= p->end))
+ return p;
+ else
+ badio(check, port);
+}
+
+struct iop *
+ide_check(struct iop *p, unsigned long port)
+{
+ if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
+ return p;
+ return NULL;
+}
+
+unsigned char
+simple_inb(struct iop *p, unsigned long port)
+{
+ return *(unsigned char *) (p->base + port);
+}
+
+unsigned short
+simple_inw(struct iop *p, unsigned long port)
+{
+ return *(unsigned short *) (p->base + port);
+}
+
+void
+simple_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ *(unsigned char *) (p->base + port) = value;
+}
+
+void
+simple_outw(struct iop *p, unsigned short value, unsigned long port)
+{
+ *(unsigned short *) (p->base + port) = value;
+}
+
+unsigned char
+pcc_inb(struct iop *p, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+ unsigned long v;
+
+ if (port & 1)
+ addr += 0x00400000;
+ v = *(volatile unsigned char *) addr;
+ return v;
+}
+
+void
+pcc_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+
+ if (port & 1)
+ addr += 0x00400000;
+ *(volatile unsigned char *) addr = value;
+}
+
+unsigned char
+bad_inb(struct iop *p, unsigned long port)
+{
+ badio(inb, port);
+}
+
+void
+bad_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ badio(inw, port);
+}
+
+#ifdef CONFIG_SMC91X
+/* MSTLANEX01 LAN at 0xb400:0000 */
+static struct iop laniop = {
+ .start = 0x00,
+ .end = 0x0F,
+ .base = 0x04000000,
+ .check = simple_check,
+ .inb = simple_inb,
+ .inw = simple_inw,
+ .outb = simple_outb,
+ .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_NE2000
+/* NE2000 pc card NIC */
+static struct iop neiop = {
+ .start = 0x280,
+ .end = 0x29f,
+ .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
+ .check = simple_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_IDE
+/* CF in CF slot */
+static struct iop cfiop = {
+ .base = 0xb0600000,
+ .check = ide_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+#endif
+
+static __inline__ struct iop *
+port2iop(unsigned long port)
+{
+ if (0) ;
+#if defined(CONFIG_SMC91X)
+ else if (laniop.check(&laniop, port))
+ return &laniop;
+#endif
+#if defined(CONFIG_NE2000)
+ else if (neiop.check(&neiop, port))
+ return &neiop;
+#endif
+#if defined(CONFIG_IDE)
+ else if (cfiop.check(&cfiop, port))
+ return &cfiop;
+#endif
+ else
+ return NULL;
+}
+
+static inline void
+delay(void)
+{
+ ctrl_inw(0xac000000);
+ ctrl_inw(0xac000000);
+}
+
+unsigned char
+sh7343se_inb(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inb) (p, port);
+}
+
+unsigned char
+sh7343se_inb_p(unsigned long port)
+{
+ unsigned char v = sh7343se_inb(port);
+ delay();
+ return v;
+}
+
+unsigned short
+sh7343se_inw(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inw) (p, port);
+}
+
+unsigned int
+sh7343se_inl(unsigned long port)
+{
+ badio(inl, port);
+}
+
+void
+sh7343se_outb(unsigned char value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outb) (p, value, port);
+}
+
+void
+sh7343se_outb_p(unsigned char value, unsigned long port)
+{
+ sh7343se_outb(value, port);
+ delay();
+}
+
+void
+sh7343se_outw(unsigned short value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outw) (p, value, port);
+}
+
+void
+sh7343se_outl(unsigned int value, unsigned long port)
+{
+ badio(outl, port);
+}
+
+void
+sh7343se_insb(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned char *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inb) (p, port);
+}
+
+void
+sh7343se_insw(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned short *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inw) (p, port);
+}
+
+void
+sh7343se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ badio(insl, port);
+}
+
+void
+sh7343se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned char *a = (unsigned char *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outb) (p, *a++, port);
+}
+
+void
+sh7343se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned short *a = (unsigned short *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outw) (p, *a++, port);
+}
+
+void
+sh7343se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/7343/irq.c b/arch/sh/boards/se/7343/irq.c
new file mode 100644
index 00000000000..b41e3d4ea37
--- /dev/null
+++ b/arch/sh/boards/se/7343/irq.c
@@ -0,0 +1,193 @@
+/*
+ * arch/sh/boards/se/7343/irq.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+static void
+disable_intreq_irq(unsigned int irq)
+{
+ int bit = irq - OFFCHIP_IRQ_BASE;
+ u16 val;
+
+ val = ctrl_inw(PA_CPLD_IMSK);
+ val |= 1 << bit;
+ ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+enable_intreq_irq(unsigned int irq)
+{
+ int bit = irq - OFFCHIP_IRQ_BASE;
+ u16 val;
+
+ val = ctrl_inw(PA_CPLD_IMSK);
+ val &= ~(1 << bit);
+ ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+mask_and_ack_intreq_irq(unsigned int irq)
+{
+ disable_intreq_irq(irq);
+}
+
+static unsigned int
+startup_intreq_irq(unsigned int irq)
+{
+ enable_intreq_irq(irq);
+ return 0;
+}
+
+static void
+shutdown_intreq_irq(unsigned int irq)
+{
+ disable_intreq_irq(irq);
+}
+
+static void
+end_intreq_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_intreq_irq(irq);
+}
+
+static struct hw_interrupt_type intreq_irq_type = {
+ .typename = "FPGA-IRQ",
+ .startup = startup_intreq_irq,
+ .shutdown = shutdown_intreq_irq,
+ .enable = enable_intreq_irq,
+ .disable = disable_intreq_irq,
+ .ack = mask_and_ack_intreq_irq,
+ .end = end_intreq_irq
+};
+
+static void
+make_intreq_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &intreq_irq_type;
+ disable_intreq_irq(irq);
+}
+
+int
+shmse_irq_demux(int irq)
+{
+ int bit;
+ volatile u16 val;
+
+ if (irq == IRQ5_IRQ) {
+ /* Read status Register */
+ val = ctrl_inw(PA_CPLD_ST);
+ bit = ffs(val);
+ if (bit != 0)
+ return OFFCHIP_IRQ_BASE + bit - 1;
+ }
+ return irq;
+}
+
+/* IRQ5 is multiplexed between the following sources:
+ * 1. PC Card socket
+ * 2. Extension slot
+ * 3. USB Controller
+ * 4. Serial Controller
+ *
+ * We configure IRQ5 as a cascade IRQ.
+ */
+static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade",
+ NULL, NULL};
+
+/*
+ * Initialize IRQ setting
+ */
+void __init
+init_7343se_IRQ(void)
+{
+ /* Setup Multiplexed interrupts */
+ ctrl_outw(8, PA_CPLD_MODESET); /* Set all CPLD interrupts to active
+ * low.
+ */
+ /* Mask all CPLD controller interrupts */
+ ctrl_outw(0x0fff, PA_CPLD_IMSK);
+
+ /* PC Card interrupts */
+ make_intreq_irq(PC_IRQ0);
+ make_intreq_irq(PC_IRQ1);
+ make_intreq_irq(PC_IRQ2);
+ make_intreq_irq(PC_IRQ3);
+
+ /* Extension Slot Interrupts */
+ make_intreq_irq(EXT_IRQ0);
+ make_intreq_irq(EXT_IRQ1);
+ make_intreq_irq(EXT_IRQ2);
+ make_intreq_irq(EXT_IRQ3);
+
+ /* USB Controller interrupts */
+ make_intreq_irq(USB_IRQ0);
+ make_intreq_irq(USB_IRQ1);
+
+ /* Serial Controller interrupts */
+ make_intreq_irq(UART_IRQ0);
+ make_intreq_irq(UART_IRQ1);
+
+ /* Setup all external interrupts to be active low */
+ ctrl_outw(0xaaaa, INTC_ICR1);
+
+ make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY);
+ setup_irq(IRQ5_IRQ, &irq5);
+ /* Set port control to use IRQ5 */
+ *(u16 *)0xA4050108 &= ~0xc;
+
+ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+ make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
+
+ ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */
+
+ make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+ make_ipr_irq(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+ /* I2C block */
+ make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+ make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+ IIC0_PRIORITY);
+ make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+ IIC0_PRIORITY);
+ make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+
+ make_ipr_irq(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+ make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+ IIC1_PRIORITY);
+ make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+ IIC1_PRIORITY);
+ make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+
+ /* SIOF */
+ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+
+ /* SIU */
+ make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
+
+ /* VIO interrupt */
+ make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+ make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+ make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+
+ /*MFI interrupt*/
+
+ make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY);
+
+ /* LCD controller */
+ make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
+ ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
+}
diff --git a/arch/sh/boards/se/7343/led.c b/arch/sh/boards/se/7343/led.c
new file mode 100644
index 00000000000..6a439cf83e4
--- /dev/null
+++ b/arch/sh/boards/se/7343/led.c
@@ -0,0 +1,46 @@
+/*
+ * arch/sh/boards/se/7343/led.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/mach/se7343.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_7343se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up = 0;
+ } else {
+ bit++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up = 1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1 << (bit + LED_SHIFT);
+
+}
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
new file mode 100644
index 00000000000..787322291fb
--- /dev/null
+++ b/arch/sh/boards/se/7343/setup.c
@@ -0,0 +1,84 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/mach/se7343.h>
+#include <asm/irq.h>
+
+void heartbeat_7343se(void);
+void init_7343se_IRQ(void);
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = 0x10000000,
+ .end = 0x1000000F,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /*
+ * shared with other devices via externel
+ * interrupt controller in FPGA...
+ */
+ .start = EXT_IRQ2,
+ .end = EXT_IRQ2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device *smc91x_platform_devices[] __initdata = {
+ &smc91x_device,
+};
+
+static int __init sh7343se_devices_setup(void)
+{
+ return platform_add_devices(smc91x_platform_devices,
+ ARRAY_SIZE(smc91x_platform_devices));
+}
+
+static void __init sh7343se_setup(char **cmdline_p)
+{
+ device_initcall(sh7343se_devices_setup);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_7343se __initmv = {
+ .mv_name = "SolutionEngine 7343",
+ .mv_setup = sh7343se_setup,
+ .mv_nr_irqs = 108,
+ .mv_inb = sh7343se_inb,
+ .mv_inw = sh7343se_inw,
+ .mv_inl = sh7343se_inl,
+ .mv_outb = sh7343se_outb,
+ .mv_outw = sh7343se_outw,
+ .mv_outl = sh7343se_outl,
+
+ .mv_inb_p = sh7343se_inb_p,
+ .mv_inw_p = sh7343se_inw,
+ .mv_inl_p = sh7343se_inl,
+ .mv_outb_p = sh7343se_outb_p,
+ .mv_outw_p = sh7343se_outw,
+ .mv_outl_p = sh7343se_outl,
+
+ .mv_insb = sh7343se_insb,
+ .mv_insw = sh7343se_insw,
+ .mv_insl = sh7343se_insl,
+ .mv_outsb = sh7343se_outsb,
+ .mv_outsw = sh7343se_outsw,
+ .mv_outsl = sh7343se_outsl,
+
+ .mv_init_irq = init_7343se_IRQ,
+ .mv_irq_demux = shmse_irq_demux,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_7343se,
+#endif
+};
+ALIAS_MV(7343se)
diff --git a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile
index be89a73cc41..9a5035f80ec 100644
--- a/arch/sh/boards/se/770x/Makefile
+++ b/arch/sh/boards/se/770x/Makefile
@@ -2,5 +2,5 @@
# Makefile for the 770x SolutionEngine specific parts of the kernel
#
-obj-y := mach.o setup.o io.o irq.o led.o
-
+obj-y := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/770x/io.c b/arch/sh/boards/se/770x/io.c
index 9a39ee96314..9941949331a 100644
--- a/arch/sh/boards/se/770x/io.c
+++ b/arch/sh/boards/se/770x/io.c
@@ -1,4 +1,4 @@
-/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+/* $Id: io.c,v 1.7 2006/02/05 21:55:29 lethal Exp $
*
* linux/arch/sh/kernel/io_se.c
*
@@ -11,7 +11,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
/* SH pcmcia io window base, start and end. */
int sh_pcic_io_wbase = 0xb8400000;
@@ -20,11 +20,6 @@ int sh_pcic_io_stop;
int sh_pcic_io_type;
int sh_pcic_io_dummy;
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
/* MS7750 requires special versions of in*, out* routines, since
PC-like io ports are located at upper half byte of 16-bit word which
can be accessed only with 16-bit wide. */
@@ -52,10 +47,6 @@ shifted_port(unsigned long port)
return 1;
}
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
unsigned char se_inb(unsigned long port)
{
if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
@@ -76,7 +67,7 @@ unsigned char se_inb_p(unsigned long port)
v = (*port2adr(port) >> 8);
else
v = (*port2adr(port))&0xff;
- delay();
+ ctrl_delay();
return v;
}
@@ -86,13 +77,13 @@ unsigned short se_inw(unsigned long port)
(sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
return *port2adr(port);
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
unsigned int se_inl(unsigned long port)
{
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
@@ -114,7 +105,7 @@ void se_outb_p(unsigned char value, unsigned long port)
*(port2adr(port)) = value << 8;
else
*(port2adr(port)) = value;
- delay();
+ ctrl_delay();
}
void se_outw(unsigned short value, unsigned long port)
@@ -123,12 +114,12 @@ void se_outw(unsigned short value, unsigned long port)
(sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
*port2adr(port) = value;
else
- maybebadio(outw, port);
+ maybebadio(port);
}
void se_outl(unsigned int value, unsigned long port)
{
- maybebadio(outl, port);
+ maybebadio(port);
}
void se_insb(unsigned long port, void *addr, unsigned long count)
@@ -159,7 +150,7 @@ void se_insw(unsigned long port, void *addr, unsigned long count)
void se_insl(unsigned long port, void *addr, unsigned long count)
{
- maybebadio(insl, port);
+ maybebadio(port);
}
void se_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -190,37 +181,5 @@ void se_outsw(unsigned long port, const void *addr, unsigned long count)
void se_outsl(unsigned long port, const void *addr, unsigned long count)
{
- maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA. */
-
-/* ISA page descriptor. */
-static __u32 sh_isa_memmap[256];
-
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
- int idx;
-
- if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
- return -1;
-
- idx = start >> 12;
- sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
- printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
- start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
- return 0;
-}
-
-unsigned long
-se_isa_port2addr(unsigned long offset)
-{
- int idx;
-
- idx = (offset >> 12) & 0xff;
- offset &= 0xfff;
- return sh_isa_memmap[idx] + offset;
+ maybebadio(port);
}
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
index 3e558716ce1..cff6700bbaf 100644
--- a/arch/sh/boards/se/770x/irq.c
+++ b/arch/sh/boards/se/770x/irq.c
@@ -11,7 +11,7 @@
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
/*
* Initialize IRQ setting
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
index 3cddbda025f..daf7b1ee786 100644
--- a/arch/sh/boards/se/770x/led.c
+++ b/arch/sh/boards/se/770x/led.c
@@ -9,22 +9,8 @@
* This file contains Solution Engine specific LED code.
*/
-#include <asm/se/se.h>
-
-static void mach_led(int position, int value)
-{
- volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
- if (value) {
- *p |= (1<<8);
- } else {
- *p &= ~(1<<8);
- }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
#include <linux/sched.h>
+#include <asm/se.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void heartbeat_se(void)
@@ -64,4 +50,3 @@ void heartbeat_se(void)
*p = 1<<(bit+8);
}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
deleted file mode 100644
index 6ec07bd3dcf..00000000000
--- a/arch/sh/boards/se/770x/mach.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_se.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the Hitachi SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se/io.h>
-
-void heartbeat_se(void);
-void setup_se(void);
-void init_se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_se __initmv = {
-#if defined(CONFIG_CPU_SH4)
- .mv_nr_irqs = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
- .mv_nr_irqs = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
- .mv_nr_irqs = 61,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
- .mv_nr_irqs = 86,
-#endif
-
- .mv_inb = se_inb,
- .mv_inw = se_inw,
- .mv_inl = se_inl,
- .mv_outb = se_outb,
- .mv_outw = se_outw,
- .mv_outl = se_outl,
-
- .mv_inb_p = se_inb_p,
- .mv_inw_p = se_inw,
- .mv_inl_p = se_inl,
- .mv_outb_p = se_outb_p,
- .mv_outw_p = se_outw,
- .mv_outl_p = se_outl,
-
- .mv_insb = se_insb,
- .mv_insw = se_insw,
- .mv_insl = se_insl,
- .mv_outsb = se_outsb,
- .mv_outsw = se_outsw,
- .mv_outsl = se_outsl,
-
- .mv_isa_port2addr = se_isa_port2addr,
-
- .mv_init_irq = init_se_IRQ,
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_se,
-#endif
-};
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index 7d1a071727c..f3f82b7c821 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -7,15 +7,17 @@
* Hitachi SolutionEngine Support.
*
*/
-
#include <linux/init.h>
#include <linux/irq.h>
-
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include <asm/se/se.h>
-#include <asm/se/smc37c93x.h>
+#include <asm/se.h>
+#include <asm/smc37c93x.h>
+#include <asm/machvec.h>
+
+void heartbeat_se(void);
+void init_se_IRQ(void);
/*
* Configure the Super I/O chip
@@ -26,7 +28,8 @@ static void __init smsc_config(int index, int data)
outb_p(data, DATA_PORT);
}
-static void __init init_smsc(void)
+/* XXX: Another candidate for a more generic cchip machine vector */
+static void __init smsc_setup(char **cmdline_p)
{
outb_p(CONFIG_ENTER, CONFIG_PORT);
outb_p(CONFIG_ENTER, CONFIG_PORT);
@@ -69,16 +72,46 @@ static void __init init_smsc(void)
outb_p(CONFIG_EXIT, CONFIG_PORT);
}
-const char *get_system_type(void)
-{
- return "SolutionEngine";
-}
-
/*
- * Initialize the board
+ * The Machine Vector
*/
-void __init platform_setup(void)
-{
- init_smsc();
- /* XXX: RTC setting comes here */
-}
+struct sh_machine_vector mv_se __initmv = {
+ .mv_name = "SolutionEngine",
+ .mv_setup = smsc_setup,
+#if defined(CONFIG_CPU_SH4)
+ .mv_nr_irqs = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ .mv_nr_irqs = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ .mv_nr_irqs = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+ .mv_nr_irqs = 86,
+#endif
+
+ .mv_inb = se_inb,
+ .mv_inw = se_inw,
+ .mv_inl = se_inl,
+ .mv_outb = se_outb,
+ .mv_outw = se_outw,
+ .mv_outl = se_outl,
+
+ .mv_inb_p = se_inb_p,
+ .mv_inw_p = se_inw,
+ .mv_inl_p = se_inl,
+ .mv_outb_p = se_outb_p,
+ .mv_outw_p = se_outw,
+ .mv_outl_p = se_outl,
+
+ .mv_insb = se_insb,
+ .mv_insw = se_insw,
+ .mv_insl = se_insl,
+ .mv_outsb = se_outsb,
+ .mv_outsw = se_outsw,
+ .mv_outsl = se_outsl,
+
+ .mv_init_irq = init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile
index ce7ca247f84..188900c4832 100644
--- a/arch/sh/boards/se/7751/Makefile
+++ b/arch/sh/boards/se/7751/Makefile
@@ -2,7 +2,7 @@
# Makefile for the 7751 SolutionEngine specific parts of the kernel
#
-obj-y := mach.o setup.o io.o irq.o led.o
+obj-y := setup.o io.o irq.o
obj-$(CONFIG_PCI) += pci.o
-
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c
index 99041b26926..e8d846cec89 100644
--- a/arch/sh/boards/se/7751/io.c
+++ b/arch/sh/boards/se/7751/io.c
@@ -1,6 +1,4 @@
-/*
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
* Copyright (C) 2001 Ian da Silva, Jeremy Siegel
* Based largely on io_se.c.
*
@@ -10,96 +8,21 @@
* placeholder code from io_se.c left in with the
* expectation of later SuperIO and PCMCIA access.
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/pci.h>
#include <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
#include <asm/addrspace.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-#if 0
-/******************************************************************
- * Variables from io_se.c, related to PCMCIA (not PCI); we're not
- * compiling them in, and have removed references from functions
- * which follow. [Many checked for IO ports in the range bounded
- * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
- * As start/stop are uninitialized, only port 0x0 would match?]
- * When used, remember to adjust names to avoid clash with io_se?
- *****************************************************************/
-/* SH pcmcia io window base, start and end. */
-int sh_pcic_io_wbase = 0xb8400000;
-int sh_pcic_io_start;
-int sh_pcic_io_stop;
-int sh_pcic_io_type;
-int sh_pcic_io_dummy;
-/*************************************************************/
-#endif
-
-/*
- * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
- * of the 7751 processor, and has a SuperIO accessible via the PCI.
- * The board also includes a PCMCIA controller on its memory bus,
- * like the other Solution Engine boards.
- */
-
-#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
-static inline volatile __u16 *
-port2adr(unsigned int port)
+static inline volatile u16 *port2adr(unsigned int port)
{
if (port >= 0x2000)
return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
- else
- return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
- maybebadio(name,(unsigned long)port);
+ maybebadio((unsigned long)port);
return (volatile __u16*)port;
}
-#if 0
-/* The 7751 Solution Engine seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int
-shifted_port(unsigned long port)
-{
- /* For IDE registers, value is not shifted */
- if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
- return 0;
- else
- return 1;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
- ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
/*
* General outline: remap really low stuff [eventually] to SuperIO,
* stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -111,10 +34,10 @@ unsigned char sh7751se_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned char *)pci_ioaddr(port);
else
- return (*port2adr(port))&0xff;
+ return (*port2adr(port)) & 0xff;
}
unsigned char sh7751se_inb_p(unsigned long port)
@@ -123,11 +46,11 @@ unsigned char sh7751se_inb_p(unsigned long port)
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ v = *(volatile unsigned char *)pci_ioaddr(port);
else
- v = (*port2adr(port))&0xff;
- delay();
+ v = (*port2adr(port)) & 0xff;
+ ctrl_delay();
return v;
}
@@ -135,12 +58,12 @@ unsigned short sh7751se_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
@@ -148,12 +71,12 @@ unsigned int sh7751se_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
@@ -162,8 +85,8 @@ void sh7751se_outb(unsigned char value, unsigned long port)
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
}
@@ -172,73 +95,41 @@ void sh7751se_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
- delay();
+ ctrl_delay();
}
void sh7751se_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else
- maybebadio(outw, port);
+ maybebadio(port);
}
void sh7751se_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned long*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned long*)pci_ioaddr(port)) = value;
else
- maybebadio(outl, port);
+ maybebadio(port);
}
void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
{
- maybebadio(insl, port);
+ maybebadio(port);
}
void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
{
- maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA. */
-
-/* ISA page descriptor. */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
- int idx;
-
- if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
- return -1;
-
- idx = start >> 12;
- sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
- printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
- start, length, offset, idx, sh_isa_memmap[idx]);
- return 0;
-}
-#endif
-
-unsigned long
-sh7751se_isa_port2addr(unsigned long offset)
-{
- int idx;
-
- idx = (offset >> 12) & 0xff;
- offset &= 0xfff;
- return sh_isa_memmap[idx] + offset;
+ maybebadio(port);
}
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
index bf6c023615d..c607b0a4847 100644
--- a/arch/sh/boards/se/7751/irq.c
+++ b/arch/sh/boards/se/7751/irq.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/irq.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
/*
* Initialize IRQ setting
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
index a878726d3c7..ff0355dea81 100644
--- a/arch/sh/boards/se/7751/led.c
+++ b/arch/sh/boards/se/7751/led.c
@@ -8,23 +8,8 @@
*
* This file contains Solution Engine specific LED code.
*/
-
-#include <asm/se7751/se7751.h>
-
-static void mach_led(int position, int value)
-{
- volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
- if (value) {
- *p |= (1<<8);
- } else {
- *p &= ~(1<<8);
- }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
#include <linux/sched.h>
+#include <asm/se7751.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void heartbeat_7751se(void)
@@ -64,4 +49,3 @@ void heartbeat_7751se(void)
*p = 1<<(bit+8);
}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7751/mach.c b/arch/sh/boards/se/7751/mach.c
deleted file mode 100644
index 62d8d3e6259..00000000000
--- a/arch/sh/boards/se/7751/mach.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_7751se.c
- *
- * Minor tweak of mach_se.c file to reference 7751se-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the Hitachi 7751 SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se7751/io.h>
-
-void heartbeat_7751se(void);
-void init_7751se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_7751se __initmv = {
- .mv_nr_irqs = 72,
-
- .mv_inb = sh7751se_inb,
- .mv_inw = sh7751se_inw,
- .mv_inl = sh7751se_inl,
- .mv_outb = sh7751se_outb,
- .mv_outw = sh7751se_outw,
- .mv_outl = sh7751se_outl,
-
- .mv_inb_p = sh7751se_inb_p,
- .mv_inw_p = sh7751se_inw,
- .mv_inl_p = sh7751se_inl,
- .mv_outb_p = sh7751se_outb_p,
- .mv_outw_p = sh7751se_outw,
- .mv_outl_p = sh7751se_outl,
-
- .mv_insl = sh7751se_insl,
- .mv_outsl = sh7751se_outsl,
-
- .mv_isa_port2addr = sh7751se_isa_port2addr,
-
- .mv_init_irq = init_7751se_IRQ,
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = heartbeat_7751se,
-#endif
-};
-ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index 48dc5aee67d..73e826310ba 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -1,4 +1,4 @@
-/*
+/*
* linux/arch/sh/kernel/setup_7751se.c
*
* Copyright (C) 2000 Kazumoto Kojima
@@ -11,78 +11,15 @@
#include <linux/init.h>
#include <linux/irq.h>
-
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#endif
-
-/*
- * Configure the Super I/O chip
- */
-#if 0
-/* Leftover code from regular Solution Engine, for reference. */
-/* The SH7751 Solution Engine has a different SuperIO. */
-static void __init smsc_config(int index, int data)
-{
- outb_p(index, INDEX_PORT);
- outb_p(data, DATA_PORT);
-}
-
-static void __init init_smsc(void)
-{
- outb_p(CONFIG_ENTER, CONFIG_PORT);
- outb_p(CONFIG_ENTER, CONFIG_PORT);
-
- /* FDC */
- smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
- smsc_config(ACTIVATE_INDEX, 0x01);
- smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
-
- /* IDE1 */
- smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
- smsc_config(ACTIVATE_INDEX, 0x01);
- smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
-
- /* AUXIO (GPIO): to use IDE1 */
- smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
- smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
- smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
-
- /* COM1 */
- smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
- smsc_config(ACTIVATE_INDEX, 0x01);
- smsc_config(IO_BASE_HI_INDEX, 0x03);
- smsc_config(IO_BASE_LO_INDEX, 0xf8);
- smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
-
- /* COM2 */
- smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
- smsc_config(ACTIVATE_INDEX, 0x01);
- smsc_config(IO_BASE_HI_INDEX, 0x02);
- smsc_config(IO_BASE_LO_INDEX, 0xf8);
- smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
-
- /* RTC */
- smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
- smsc_config(ACTIVATE_INDEX, 0x01);
- smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
-
- /* XXX: PARPORT, KBD, and MOUSE will come here... */
- outb_p(CONFIG_EXIT, CONFIG_PORT);
-}
-#endif
-
-const char *get_system_type(void)
-{
- return "7751 SolutionEngine";
-}
+void heartbeat_7751se(void);
+void init_7751se_IRQ(void);
#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
static int kgdb_uart_setup(void);
static struct kgdb_sermap kgdb_uart_sermap =
{ "ttyS", 0, kgdb_uart_setup, NULL };
@@ -91,7 +28,7 @@ static struct kgdb_sermap kgdb_uart_sermap =
/*
* Initialize the board
*/
-void __init platform_setup(void)
+static void __init sh7751se_setup(char **cmdline_p)
{
/* Call init_smsc() replacement to set up SuperIO. */
/* XXX: RTC setting comes here */
@@ -225,3 +162,37 @@ static int kgdb_uart_setup(void)
return 0;
}
#endif /* CONFIG_SH_KGDB */
+
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7751se __initmv = {
+ .mv_name = "7751 SolutionEngine",
+ .mv_setup = sh7751se_setup,
+ .mv_nr_irqs = 72,
+
+ .mv_inb = sh7751se_inb,
+ .mv_inw = sh7751se_inw,
+ .mv_inl = sh7751se_inl,
+ .mv_outb = sh7751se_outb,
+ .mv_outw = sh7751se_outw,
+ .mv_outl = sh7751se_outl,
+
+ .mv_inb_p = sh7751se_inb_p,
+ .mv_inw_p = sh7751se_inw,
+ .mv_inl_p = sh7751se_inl,
+ .mv_outb_p = sh7751se_outb_p,
+ .mv_outw_p = sh7751se_outw,
+ .mv_outl_p = sh7751se_outl,
+
+ .mv_insl = sh7751se_insl,
+ .mv_outsl = sh7751se_outsl,
+
+ .mv_init_irq = init_7751se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_7751se,
+#endif
+};
+ALIAS_MV(7751se)
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
index d609863cfe5..0a9266bb51c 100644
--- a/arch/sh/boards/sh03/rtc.c
+++ b/arch/sh/boards/sh03/rtc.c
@@ -10,9 +10,10 @@
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/bcd.h>
-#include <asm/io.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/rtc.h>
#define RTC_BASE 0xb0000000
#define RTC_SEC1 (RTC_BASE + 0)
@@ -34,8 +35,6 @@
#define RTC_BUSY 1
#define RTC_STOP 2
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
extern spinlock_t rtc_lock;
unsigned long get_cmos_time(void)
@@ -128,6 +127,6 @@ int sh03_rtc_settimeofday(const time_t secs)
void sh03_time_init(void)
{
- rtc_get_time = sh03_rtc_gettimeofday;
- rtc_set_time = sh03_rtc_settimeofday;
+ rtc_sh_get_time = sh03_rtc_gettimeofday;
+ rtc_sh_set_time = sh03_rtc_settimeofday;
}
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
index 60290f8f289..6c310587ddf 100644
--- a/arch/sh/boards/sh03/setup.c
+++ b/arch/sh/boards/sh03/setup.c
@@ -7,22 +7,13 @@
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
#include <asm/io.h>
+#include <asm/rtc.h>
#include <asm/sh03/io.h>
#include <asm/sh03/sh03.h>
#include <asm/addrspace.h>
-#include "../../drivers/pci/pci-sh7751.h"
-extern void (*board_time_init)(void);
-
-const char *get_system_type(void)
-{
- return "Interface CTP/PCI-SH03)";
-}
-
-void init_sh03_IRQ(void)
+static void __init init_sh03_IRQ(void)
{
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
@@ -34,38 +25,34 @@ void init_sh03_IRQ(void)
extern void *cf_io_base;
-unsigned long sh03_isa_port2addr(unsigned long port)
+static void __iomem *sh03_ioport_map(unsigned long port, unsigned int size)
{
if (PXSEG(port))
- return port;
+ return (void __iomem *)port;
/* CompactFlash (IDE) */
- if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6)) {
- return (unsigned long)cf_io_base + port;
- }
- return port + SH7751_PCI_IO_BASE;
+ if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6))
+ return (void __iomem *)((unsigned long)cf_io_base + port);
+
+ return (void __iomem *)(port + PCI_IO_BASE);
}
-/*
- * The Machine Vector
- */
+/* arch/sh/boards/sh03/rtc.c */
+void sh03_time_init(void);
+
+static void __init sh03_setup(char **cmdline_p)
+{
+ board_time_init = sh03_time_init;
+}
struct sh_machine_vector mv_sh03 __initmv = {
+ .mv_name = "Interface (CTP/PCI-SH03)",
+ .mv_setup = sh03_setup,
.mv_nr_irqs = 48,
- .mv_isa_port2addr = sh03_isa_port2addr,
+ .mv_ioport_map = sh03_ioport_map,
.mv_init_irq = init_sh03_IRQ,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_sh03,
#endif
};
-
ALIAS_MV(sh03)
-
-/* arch/sh/boards/sh03/rtc.c */
-void sh03_time_init(void);
-
-int __init platform_setup(void)
-{
- board_time_init = sh03_time_init;
- return 0;
-}
diff --git a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile
deleted file mode 100644
index 05d390c3599..00000000000
--- a/arch/sh/boards/sh2000/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the SH2000 specific parts of the kernel
-#
-
-obj-y := setup.o
-
diff --git a/arch/sh/boards/sh2000/setup.c b/arch/sh/boards/sh2000/setup.c
deleted file mode 100644
index 2fe6a11765e..00000000000
--- a/arch/sh/boards/sh2000/setup.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_sh2000.c
- *
- * Copyright (C) 2001 SUGIOKA Tochinobu
- *
- * SH-2000 Support.
- *
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/sh2000.h>
-
-#define CF_CIS_BASE 0xb4200000
-
-#define PORT_PECR 0xa4000108
-#define PORT_PHCR 0xa400010E
-#define PORT_ICR1 0xa4000010
-#define PORT_IRR0 0xa4000004
-
-#define IDE_OFFSET 0xb6200000
-#define NIC_OFFSET 0xb6000000
-#define EXTBUS_OFFSET 0xba000000
-
-
-const char *get_system_type(void)
-{
- return "sh2000";
-}
-
-static unsigned long sh2000_isa_port2addr(unsigned long offset)
-{
- if((offset & ~7) == 0x1f0 || offset == 0x3f6)
- return IDE_OFFSET + offset;
- else if((offset & ~0x1f) == 0x300)
- return NIC_OFFSET + offset;
- return EXTBUS_OFFSET + offset;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_sh2000 __initmv = {
- .mv_nr_irqs = 80,
- .mv_isa_port2addr = sh2000_isa_port2addr,
-};
-ALIAS_MV(sh2000)
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
- /* XXX: RTC setting comes here */
-
- /* These should be done by BIOS/IPL ... */
- /* Enable nCE2A, nCE2B output */
- ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
- /* Enable the Compact Flash card, and set the level interrupt */
- ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
- /* Enable interrupt */
- ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
- ctrl_outw(1, PORT_ICR1);
- ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
- printk(KERN_INFO "SH-2000 Setup...done\n");
- return 0;
-}
diff --git a/arch/sh/boards/shmin/Makefile b/arch/sh/boards/shmin/Makefile
new file mode 100644
index 00000000000..3190cc72430
--- /dev/null
+++ b/arch/sh/boards/shmin/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the SHMIN board.
+#
+
+obj-y := setup.o
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
new file mode 100644
index 00000000000..2f0c19706cf
--- /dev/null
+++ b/arch/sh/boards/shmin/setup.c
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/boards/shmin/setup.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII
+ *
+ * SHMIN Support.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/shmin/shmin.h>
+#include <asm/clock.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#define PFC_PHCR 0xa400010e
+
+static void __init init_shmin_irq(void)
+{
+ ctrl_outw(0x2a00, PFC_PHCR); // IRQ0-3=IRQ
+ ctrl_outw(0x0aaa, INTC_ICR1); // IRQ0-3=IRQ-mode,Low-active.
+}
+
+static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
+{
+ static int dummy;
+
+ if ((port & ~0x1f) == SHMIN_NE_BASE)
+ return (void __iomem *)(SHMIN_IO_BASE + port);
+
+ dummy = 0;
+
+ return &dummy;
+
+}
+
+struct sh_machine_vector mv_shmin __initmv = {
+ .mv_name = "SHMIN",
+ .mv_init_irq = init_shmin_irq,
+ .mv_ioport_map = shmin_ioport_map,
+};
+ALIAS_MV(shmin)
diff --git a/arch/sh/boards/snapgear/io.c b/arch/sh/boards/snapgear/io.c
index e2eb78fc381..0f482426455 100644
--- a/arch/sh/boards/snapgear/io.c
+++ b/arch/sh/boards/snapgear/io.c
@@ -1,6 +1,4 @@
-/*
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
* Copyright (C) 2002 David McCullough <davidm@snapgear.com>
* Copyright (C) 2001 Ian da Silva, Jeremy Siegel
* Based largely on io_se.c.
@@ -11,67 +9,22 @@
* placeholder code from io_se.c left in with the
* expectation of later SuperIO and PCMCIA access.
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/addrspace.h>
-#include <asm/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
#ifdef CONFIG_SH_SECUREEDGE5410
unsigned short secureedge5410_ioport;
#endif
-/*
- * The SnapGear uses the built-in PCI controller (PCIC)
- * of the 7751 processor
- */
-
-#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
-
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-
-#define maybebadio(name,port) \
- printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
-
static inline volatile __u16 *port2adr(unsigned int port)
{
-#if 0
- if (port >= 0x2000)
- return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#endif
- maybebadio(name,(unsigned long)port);
+ maybebadio((unsigned long)port);
return (volatile __u16*)port;
}
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
- ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
/*
* General outline: remap really low stuff [eventually] to SuperIO,
* stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -79,148 +32,106 @@ static inline volatile __u16 *port2adr(unsigned int port)
* should be way beyond the window, and is used w/o translation for
* compatibility.
*/
-
unsigned char snapgear_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned char *)pci_ioaddr(port);
else
- return (*port2adr(port))&0xff;
+ return (*port2adr(port)) & 0xff;
}
-
unsigned char snapgear_inb_p(unsigned long port)
{
unsigned char v;
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (CHECK_SH7751_PCIIO(port))
- v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ v = *(volatile unsigned char *)pci_ioaddr(port);
else
- v = (*port2adr(port))&0xff;
- delay();
+ v = (*port2adr(port))&0xff;
+ ctrl_delay();
return v;
}
-
unsigned short snapgear_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
- maybebadio(inw, port);
+ maybebadio(port);
return 0;
}
-
unsigned int snapgear_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (CHECK_SH7751_PCIIO(port))
- return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (is_pci_ioaddr(port))
+ return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
- maybebadio(inl, port);
+ maybebadio(port);
return 0;
}
-
void snapgear_outb(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
}
-
void snapgear_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
- delay();
+ ctrl_delay();
}
-
void snapgear_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else
- maybebadio(outw, port);
+ maybebadio(port);
}
-
void snapgear_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (CHECK_SH7751_PCIIO(port))
- *((unsigned long*)PCI_IOMAP(port)) = value;
+ else if (is_pci_ioaddr(port))
+ *((unsigned long*)pci_ioaddr(port)) = value;
else
- maybebadio(outl, port);
+ maybebadio(port);
}
void snapgear_insl(unsigned long port, void *addr, unsigned long count)
{
- maybebadio(insl, port);
+ maybebadio(port);
}
void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
{
- maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA. */
-
-
-/* ISA page descriptor. */
-static __u32 sh_isa_memmap[256];
-
-
-#if 0
-static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
- int idx;
-
- if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
- return -1;
-
- idx = start >> 12;
- sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
- printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
- start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
- return 0;
-}
-#endif
-
-unsigned long snapgear_isa_port2addr(unsigned long offset)
-{
- int idx;
-
- idx = (offset >> 12) & 0xff;
- offset &= 0xfff;
- return sh_isa_memmap[idx] + offset;
+ maybebadio(port);
}
diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c
index b71e009da35..1659fdd6695 100644
--- a/arch/sh/boards/snapgear/rtc.c
+++ b/arch/sh/boards/snapgear/rtc.c
@@ -17,14 +17,9 @@
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/mc146818rtc.h>
-
#include <asm/io.h>
-#include <asm/rtc.h>
-#include <asm/mc146818rtc.h>
-
-/****************************************************************************/
-static int use_ds1302 = 0;
+static int use_ds1302;
/****************************************************************************/
/*
@@ -82,10 +77,6 @@ static unsigned int ds1302_readbyte(unsigned int addr)
unsigned int val;
unsigned long flags;
-#if 0
- printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
-#endif
-
local_irq_save(flags);
set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -104,10 +95,6 @@ static void ds1302_writebyte(unsigned int addr, unsigned int val)
{
unsigned long flags;
-#if 0
- printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
-#endif
-
local_irq_save(flags);
set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -168,11 +155,8 @@ void __init secureedge5410_rtc_init(void)
}
if (use_ds1302) {
- rtc_get_time = snapgear_rtc_gettimeofday;
- rtc_set_time = snapgear_rtc_settimeofday;
- } else {
- rtc_get_time = sh_rtc_gettimeofday;
- rtc_set_time = sh_rtc_settimeofday;
+ rtc_sh_get_time = snapgear_rtc_gettimeofday;
+ rtc_sh_set_time = snapgear_rtc_settimeofday;
}
printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
@@ -187,10 +171,8 @@ void snapgear_rtc_gettimeofday(struct timespec *ts)
{
unsigned int sec, min, hr, day, mon, yr;
- if (!use_ds1302) {
- sh_rtc_gettimeofday(ts);
+ if (!use_ds1302)
return;
- }
sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
@@ -231,7 +213,7 @@ int snapgear_rtc_settimeofday(const time_t secs)
unsigned long nowtime;
if (!use_ds1302)
- return sh_rtc_settimeofday(secs);
+ return 0;
/*
* This is called direct from the kernel timer handling code.
@@ -240,10 +222,6 @@ int snapgear_rtc_settimeofday(const time_t secs)
nowtime = secs;
-#if 1
- printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
-#endif
-
/* STOP RTC */
ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
@@ -329,5 +307,3 @@ void secureedge5410_cmos_write(unsigned char val, int addr)
default: break;
}
}
-
-/****************************************************************************/
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index f1f7c70c940..f5e98c56b53 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -1,5 +1,4 @@
-/****************************************************************************/
-/*
+/*
* linux/arch/sh/boards/snapgear/setup.c
*
* Copyright (C) 2002 David McCullough <davidm@snapgear.com>
@@ -12,8 +11,6 @@
* Modified for 7751 Solution Engine by
* Ian da Silva and Jeremy Siegel, 2001.
*/
-/****************************************************************************/
-
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
@@ -21,14 +18,13 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/sched.h>
-
#include <asm/machvec.h>
-#include <asm/mach/io.h>
+#include <asm/snapgear.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/rtc.h>
#include <asm/cpu/timer.h>
-extern void (*board_time_init)(void);
extern void secureedge5410_rtc_init(void);
extern void pcibios_init(void);
@@ -85,101 +81,20 @@ static void __init init_snapgear_IRQ(void)
make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
}
-/****************************************************************************/
-/*
- * Fast poll interrupt simulator.
- */
-
/*
- * Leave all of the fast timer/fast poll stuff commented out for now, since
- * it's not clear whether it actually works or not. Since it wasn't being used
- * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM
- */
-#if 0
-#define FAST_POLL 1000
-//#define FAST_POLL_INTR
-
-#define FASTTIMER_IRQ 17
-#define FASTTIMER_IPR_ADDR INTC_IPRA
-#define FASTTIMER_IPR_POS 2
-#define FASTTIMER_PRIORITY 3
-
-#ifdef FAST_POLL_INTR
-#define TMU1_TCR_INIT 0x0020
-#else
-#define TMU1_TCR_INIT 0
-#endif
-#define TMU_TSTR_INIT 1
-#define TMU1_TCR_CALIB 0x0000
-
-
-#ifdef FAST_POLL_INTR
-static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
-{
- unsigned long timer_status;
- timer_status = ctrl_inw(TMU1_TCR);
- timer_status &= ~0x100;
- ctrl_outw(timer_status, TMU1_TCR);
-}
-#endif
-
-/*
- * return the current ticks on the fast timer
- */
-
-unsigned long fast_timer_count(void)
-{
- return(ctrl_inl(TMU1_TCNT));
-}
-
-/*
- * setup a fast timer for profiling etc etc
+ * Initialize the board
*/
-
-static void setup_fast_timer()
-{
- unsigned long interval;
-
-#ifdef FAST_POLL_INTR
- interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
-
- make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
- FASTTIMER_PRIORITY);
-
- printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
-
- if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
- NULL) != 0)
- printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
-#else
- printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
- interval = 0xffffffff;
-#endif
-
- ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
- ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
- ctrl_outl(interval, TMU1_TCOR);
- ctrl_outl(interval, TMU1_TCNT);
- ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
-
- printk("Timer count 1 = 0x%x\n", fast_timer_count());
- udelay(1000);
- printk("Timer count 2 = 0x%x\n", fast_timer_count());
-}
-#endif
-
-/****************************************************************************/
-
-const char *get_system_type(void)
+static void __init snapgear_setup(char **cmdline_p)
{
- return "SnapGear SecureEdge5410";
+ board_time_init = secureedge5410_rtc_init;
}
/*
* The Machine Vector
*/
-
struct sh_machine_vector mv_snapgear __initmv = {
+ .mv_name = "SnapGear SecureEdge5410",
+ .mv_setup = snapgear_setup,
.mv_nr_irqs = 72,
.mv_inb = snapgear_inb,
@@ -196,20 +111,6 @@ struct sh_machine_vector mv_snapgear __initmv = {
.mv_outw_p = snapgear_outw,
.mv_outl_p = snapgear_outl,
- .mv_isa_port2addr = snapgear_isa_port2addr,
-
.mv_init_irq = init_snapgear_IRQ,
};
ALIAS_MV(snapgear)
-
-/*
- * Initialize the board
- */
-
-int __init platform_setup(void)
-{
- board_time_init = secureedge5410_rtc_init;
-
- return 0;
-}
-
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index 236398fbc08..8c64baa3036 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -11,14 +11,12 @@
#include <linux/init.h>
#include <linux/irq.h>
-
#include <asm/system.h>
#include <asm/io.h>
#include <asm/microdev.h>
#define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */
-
static const struct {
unsigned char fpgaIrq;
unsigned char mapped;
@@ -93,53 +91,42 @@ static struct hw_interrupt_type microdev_irq_type = {
static void disable_microdev_irq(unsigned int irq)
{
- unsigned int flags;
unsigned int fpgaIrq;
- if (irq >= NUM_EXTERNAL_IRQS) return;
- if (!fpgaIrqTable[irq].mapped) return;
+ if (irq >= NUM_EXTERNAL_IRQS)
+ return;
+ if (!fpgaIrqTable[irq].mapped)
+ return;
fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
- /* disable interrupts */
- local_irq_save(flags);
-
- /* disable interupts on the FPGA INTC register */
+ /* disable interupts on the FPGA INTC register */
ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
-
- /* restore interrupts */
- local_irq_restore(flags);
}
static void enable_microdev_irq(unsigned int irq)
{
unsigned long priorityReg, priorities, pri;
- unsigned int flags;
unsigned int fpgaIrq;
-
- if (irq >= NUM_EXTERNAL_IRQS) return;
- if (!fpgaIrqTable[irq].mapped) return;
+ if (unlikely(irq >= NUM_EXTERNAL_IRQS))
+ return;
+ if (unlikely(!fpgaIrqTable[irq].mapped))
+ return;
pri = 15 - irq;
fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
- /* disable interrupts */
- local_irq_save(flags);
-
- /* set priority for the interrupt */
+ /* set priority for the interrupt */
priorities = ctrl_inl(priorityReg);
priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
ctrl_outl(priorities, priorityReg);
- /* enable interupts on the FPGA INTC register */
+ /* enable interupts on the FPGA INTC register */
ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
-
- /* restore interrupts */
- local_irq_restore(flags);
}
/* This functions sets the desired irq handler to be a MicroDev type */
@@ -158,9 +145,7 @@ static void mask_and_ack_microdev(unsigned int irq)
static void end_microdev_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- {
enable_microdev_irq(irq);
- }
}
extern void __init init_microdev_irq(void)
@@ -171,9 +156,7 @@ extern void __init init_microdev_irq(void)
ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
- {
make_microdev_irq(i);
- }
}
extern void microdev_print_fpga_intc_status(void)
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
index 61b402a3f5d..031c814e6e7 100644
--- a/arch/sh/boards/superh/microdev/setup.c
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -10,7 +10,6 @@
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*/
-
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
@@ -21,41 +20,6 @@
extern void microdev_heartbeat(void);
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
- .mv_nr_irqs = 72, /* QQQ need to check this - use the MACRO */
-
- .mv_inb = microdev_inb,
- .mv_inw = microdev_inw,
- .mv_inl = microdev_inl,
- .mv_outb = microdev_outb,
- .mv_outw = microdev_outw,
- .mv_outl = microdev_outl,
-
- .mv_inb_p = microdev_inb_p,
- .mv_inw_p = microdev_inw_p,
- .mv_inl_p = microdev_inl_p,
- .mv_outb_p = microdev_outb_p,
- .mv_outw_p = microdev_outw_p,
- .mv_outl_p = microdev_outl_p,
-
- .mv_insb = microdev_insb,
- .mv_insw = microdev_insw,
- .mv_insl = microdev_insl,
- .mv_outsb = microdev_outsb,
- .mv_outsw = microdev_outsw,
- .mv_outsl = microdev_outsl,
-
- .mv_init_irq = init_microdev_irq,
-
-#ifdef CONFIG_HEARTBEAT
- .mv_heartbeat = microdev_heartbeat,
-#endif
-};
-ALIAS_MV(sh4202_microdev)
/****************************************************************************/
@@ -113,11 +77,6 @@ ALIAS_MV(sh4202_microdev)
/* assume a Keyboard Controller is present */
int microdev_kbd_controller_present = 1;
-const char *get_system_type(void)
-{
- return "SH4-202 MicroDev";
-}
-
static struct resource smc91x_resources[] = {
[0] = {
.start = 0x300,
@@ -291,25 +250,9 @@ static int __init microdev_devices_setup(void)
return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
}
-__initcall(microdev_devices_setup);
-
-void __init platform_setup(void)
-{
- int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
- const int fpgaRevision = *fpgaRevisionRegister;
- int * const CacheControlRegister = (int*)CCR;
-
- printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
- get_system_type(), fpgaRevision, *CacheControlRegister);
-}
-
-
-/****************************************************************************/
-
-
- /*
- * Setup for the SMSC FDC37C93xAPM
- */
+/*
+ * Setup for the SMSC FDC37C93xAPM
+ */
static int __init smsc_superio_setup(void)
{
@@ -412,8 +355,52 @@ static int __init smsc_superio_setup(void)
return 0;
}
+static void __init microdev_setup(char **cmdline_p)
+{
+ int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
+ const int fpgaRevision = *fpgaRevisionRegister;
+ int * const CacheControlRegister = (int*)CCR;
+
+ device_initcall(microdev_devices_setup);
+ device_initcall(smsc_superio_setup);
-/* This is grotty, but, because kernel is always referenced on the link line
- * before any devices, this is safe.
+ printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
+ get_system_type(), fpgaRevision, *CacheControlRegister);
+}
+
+/*
+ * The Machine Vector
*/
-__initcall(smsc_superio_setup);
+struct sh_machine_vector mv_sh4202_microdev __initmv = {
+ .mv_name = "SH4-202 MicroDev",
+ .mv_setup = microdev_setup,
+ .mv_nr_irqs = 72, /* QQQ need to check this - use the MACRO */
+
+ .mv_inb = microdev_inb,
+ .mv_inw = microdev_inw,
+ .mv_inl = microdev_inl,
+ .mv_outb = microdev_outb,
+ .mv_outw = microdev_outw,
+ .mv_outl = microdev_outl,
+
+ .mv_inb_p = microdev_inb_p,
+ .mv_inw_p = microdev_inw_p,
+ .mv_inl_p = microdev_inl_p,
+ .mv_outb_p = microdev_outb_p,
+ .mv_outw_p = microdev_outw_p,
+ .mv_outl_p = microdev_outl_p,
+
+ .mv_insb = microdev_insb,
+ .mv_insw = microdev_insw,
+ .mv_insl = microdev_insl,
+ .mv_outsb = microdev_outsb,
+ .mv_outsw = microdev_outsw,
+ .mv_outsl = microdev_outsl,
+
+ .mv_init_irq = init_microdev_irq,
+
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = microdev_heartbeat,
+#endif
+};
+ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/Makefile b/arch/sh/boards/titan/Makefile
new file mode 100644
index 00000000000..08d75370006
--- /dev/null
+++ b/arch/sh/boards/titan/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Nimble Microsystems TITAN specific parts of the kernel
+#
+
+obj-y := setup.o io.o
diff --git a/arch/sh/boards/titan/io.c b/arch/sh/boards/titan/io.c
new file mode 100644
index 00000000000..4730c1dd697
--- /dev/null
+++ b/arch/sh/boards/titan/io.c
@@ -0,0 +1,126 @@
+/*
+ * I/O routines for Titan
+ */
+#include <linux/pci.h>
+#include <asm/machvec.h>
+#include <asm/addrspace.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+static inline unsigned int port2adr(unsigned int port)
+{
+ maybebadio((unsigned long)port);
+ return port;
+}
+
+u8 titan_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inb(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inb(pci_ioaddr(port));
+ return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 titan_inb_p(unsigned long port)
+{
+ u8 v;
+
+ if (PXSEG(port))
+ v = ctrl_inb(port);
+ else if (is_pci_ioaddr(port))
+ v = ctrl_inb(pci_ioaddr(port));
+ else
+ v = ctrl_inw(port2adr(port)) & 0xff;
+ ctrl_delay();
+ return v;
+}
+
+u16 titan_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inw(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inw(pci_ioaddr(port));
+ else if (port >= 0x2000)
+ return ctrl_inw(port2adr(port));
+ else
+ maybebadio(port);
+ return 0;
+}
+
+u32 titan_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return ctrl_inl(port);
+ else if (is_pci_ioaddr(port))
+ return ctrl_inl(pci_ioaddr(port));
+ else if (port >= 0x2000)
+ return ctrl_inw(port2adr(port));
+ else
+ maybebadio(port);
+ return 0;
+}
+
+void titan_outb(u8 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+}
+
+void titan_outb_p(u8 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outb(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outb(value, pci_ioaddr(port));
+ else
+ ctrl_outw(value, port2adr(port));
+ ctrl_delay();
+}
+
+void titan_outw(u16 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outw(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outw(value, pci_ioaddr(port));
+ else if (port >= 0x2000)
+ ctrl_outw(value, port2adr(port));
+ else
+ maybebadio(port);
+}
+
+void titan_outl(u32 value, unsigned long port)
+{
+ if (PXSEG(port))
+ ctrl_outl(value, port);
+ else if (is_pci_ioaddr(port))
+ ctrl_outl(value, pci_ioaddr(port));
+ else
+ maybebadio(port);
+}
+
+void titan_insl(unsigned long port, void *dst, unsigned long count)
+{
+ maybebadio(port);
+}
+
+void titan_outsl(unsigned long port, const void *src, unsigned long count)
+{
+ maybebadio(port);
+}
+
+void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
+{
+ if (PXSEG(port) || is_pci_memaddr(port))
+ return (void __iomem *)port;
+ else if (is_pci_ioaddr(port))
+ return (void __iomem *)pci_ioaddr(port);
+
+ return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
new file mode 100644
index 00000000000..52b66d8b8d2
--- /dev/null
+++ b/arch/sh/boards/titan/setup.c
@@ -0,0 +1,48 @@
+/*
+ * Setup for Titan
+ */
+
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+extern void __init pcibios_init_platform(void);
+
+static void __init init_titan_irq(void)
+{
+ /* enable individual interrupt mode for externals */
+ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+ make_ipr_irq( TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); /* PCIRQ0 */
+ make_ipr_irq( TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); /* PCIRQ1 */
+ make_ipr_irq( TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); /* PCIRQ2 */
+ make_ipr_irq( TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); /* PCIRQ3 */
+}
+
+struct sh_machine_vector mv_titan __initmv = {
+ .mv_name = "Titan",
+
+ .mv_inb = titan_inb,
+ .mv_inw = titan_inw,
+ .mv_inl = titan_inl,
+ .mv_outb = titan_outb,
+ .mv_outw = titan_outw,
+ .mv_outl = titan_outl,
+
+ .mv_inb_p = titan_inb_p,
+ .mv_inw_p = titan_inw,
+ .mv_inl_p = titan_inl,
+ .mv_outb_p = titan_outb_p,
+ .mv_outw_p = titan_outw,
+ .mv_outl_p = titan_outl,
+
+ .mv_insl = titan_insl,
+ .mv_outsl = titan_outsl,
+
+ .mv_ioport_map = titan_ioport_map,
+
+ .mv_init_irq = init_titan_irq,
+ .mv_init_pci = pcibios_init_platform,
+};
+ALIAS_MV(titan)
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
index c5e4ed10876..1c941370a2e 100644
--- a/arch/sh/boards/unknown/setup.c
+++ b/arch/sh/boards/unknown/setup.c
@@ -14,19 +14,8 @@
*/
#include <linux/init.h>
#include <asm/machvec.h>
-#include <asm/irq.h>
struct sh_machine_vector mv_unknown __initmv = {
- .mv_nr_irqs = NR_IRQS,
+ .mv_name = "Unknown",
};
ALIAS_MV(unknown)
-
-const char *get_system_type(void)
-{
- return "Unknown";
-}
-
-void __init platform_setup(void)
-{
-}
-
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 75a6876bf6c..e5f44379007 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -18,13 +18,20 @@ endif
# Assign dummy values if these 2 variables are not defined,
# in order to suppress error message.
#
+CONFIG_PAGE_OFFSET ?= 0x80000000
CONFIG_MEMORY_START ?= 0x0c000000
CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
-IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
+
+IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET) + \
+ $(CONFIG_MEMORY_START) + \
+ $(CONFIG_BOOT_LINK_OFFSET)])
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
$(call if_changed,ld)
@:
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
index 155d139884c..0582ca8346b 100644
--- a/arch/sh/cchips/Kconfig
+++ b/arch/sh/cchips/Kconfig
@@ -65,6 +65,11 @@ config HD64461_IRQ
Do not change this unless you know what you are doing.
+config HD64461_IOBASE
+ hex "HD64461 start address"
+ depends on HD64461
+ default "0xb0000000"
+
config HD64461_ENABLER
bool "HD64461 PCMCIA enabler"
depends on HD64461
@@ -73,7 +78,6 @@ config HD64461_ENABLER
via the HD64461 companion chip.
Otherwise, say N.
-
config HD64465_IOBASE
hex "HD64465 start address"
depends on HD64465
diff --git a/arch/sh/cchips/hd6446x/hd64461/io.c b/arch/sh/cchips/hd6446x/hd64461/io.c
index ac3062671db..7909a1b7b51 100644
--- a/arch/sh/cchips/hd6446x/hd64461/io.c
+++ b/arch/sh/cchips/hd6446x/hd64461/io.c
@@ -1,11 +1,10 @@
/*
- * $Id: io.c,v 1.6 2004/03/16 00:07:50 lethal Exp $
* Copyright (C) 2000 YAEGASHI Takeshi
* Typical I/O routines for HD64461 system.
*/
#include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
#define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
@@ -54,11 +53,6 @@ static __inline__ unsigned long PORT2ADDR(unsigned long port)
return 0xa0000000 + (port & 0x1fffffff);
}
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000);
-}
-
unsigned char hd64461_inb(unsigned long port)
{
return *(volatile unsigned char*)PORT2ADDR(port);
@@ -67,7 +61,7 @@ unsigned char hd64461_inb(unsigned long port)
unsigned char hd64461_inb_p(unsigned long port)
{
unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
- delay();
+ ctrl_delay();
return v;
}
@@ -89,7 +83,7 @@ void hd64461_outb(unsigned char b, unsigned long port)
void hd64461_outb_p(unsigned char b, unsigned long port)
{
*(volatile unsigned char*)PORT2ADDR(port) = b;
- delay();
+ ctrl_delay();
}
void hd64461_outw(unsigned short b, unsigned long port)
@@ -144,13 +138,13 @@ void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
while(count--) *addr=*buf++;
}
-unsigned short hd64461_readw(unsigned long addr)
+unsigned short hd64461_readw(void __iomem *addr)
{
- return *(volatile unsigned short*)(MEM_BASE+addr);
+ return ctrl_inw(MEM_BASE+(unsigned long __force)addr);
}
-void hd64461_writew(unsigned short b, unsigned long addr)
+void hd64461_writew(unsigned short b, void __iomem *addr)
{
- *(volatile unsigned short*)(MEM_BASE+addr) = b;
+ ctrl_outw(b, MEM_BASE+(unsigned long __force)addr);
}
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c
index ad126016720..38f1e8171a3 100644
--- a/arch/sh/cchips/hd6446x/hd64461/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64461/setup.c
@@ -11,36 +11,28 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
-
#include <asm/io.h>
#include <asm/irq.h>
-
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
static void disable_hd64461_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64461_IRQBASE);
- local_irq_save(flags);
nimr = inw(HD64461_NIMR);
nimr |= mask;
outw(nimr, HD64461_NIMR);
- local_irq_restore(flags);
}
static void enable_hd64461_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64461_IRQBASE);
- local_irq_save(flags);
nimr = inw(HD64461_NIMR);
nimr &= ~mask;
outw(nimr, HD64461_NIMR);
- local_irq_restore(flags);
}
static void mask_and_ack_hd64461(unsigned int irq)
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
index d2b2851bc44..30573d3e196 100644
--- a/arch/sh/cchips/hd6446x/hd64465/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -25,31 +25,25 @@
static void disable_hd64465_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
- local_irq_save(flags);
nimr = inw(HD64465_REG_NIMR);
nimr |= mask;
outw(nimr, HD64465_REG_NIMR);
- local_irq_restore(flags);
}
static void enable_hd64465_irq(unsigned int irq)
{
- unsigned long flags;
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
- local_irq_save(flags);
nimr = inw(HD64465_REG_NIMR);
nimr &= ~mask;
outw(nimr, HD64465_REG_NIMR);
- local_irq_restore(flags);
}
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 0dc1fb8f968..392c8b12ce3 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -32,37 +32,30 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
static void disable_voyagergx_irq(unsigned int irq)
{
- unsigned long flags, val;
- unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+ unsigned long val;
+ unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
- local_irq_save(flags);
val = inl(VOYAGER_INT_MASK);
val &= ~mask;
outl(val, VOYAGER_INT_MASK);
- local_irq_restore(flags);
}
-
static void enable_voyagergx_irq(unsigned int irq)
{
- unsigned long flags, val;
- unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+ unsigned long val;
+ unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
- local_irq_save(flags);
val = inl(VOYAGER_INT_MASK);
val |= mask;
outl(val, VOYAGER_INT_MASK);
- local_irq_restore(flags);
}
-
static void mask_and_ack_voyagergx(unsigned int irq)
{
disable_voyagergx_irq(irq);
@@ -95,7 +88,8 @@ static struct hw_interrupt_type voyagergx_irq_type = {
.end = end_voyagergx_irq,
};
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
printk(KERN_INFO
"VoyagerGX: spurious interrupt, status: 0x%x\n",
@@ -103,9 +97,6 @@ static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
-
-/*====================================================*/
-
static struct {
int (*func)(int, void *);
void *dev;
diff --git a/arch/sh/cchips/voyagergx/setup.c b/arch/sh/cchips/voyagergx/setup.c
index 139ca88ac9e..66b2fedd7ad 100644
--- a/arch/sh/cchips/voyagergx/setup.c
+++ b/arch/sh/cchips/voyagergx/setup.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
static int __init setup_voyagergx(void)
{
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
new file mode 100644
index 00000000000..6b43316d03c
--- /dev/null
+++ b/arch/sh/configs/landisk_defconfig
@@ -0,0 +1,1373 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-sh
+# Sun Sep 11 13:00:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+CONFIG_SH_LANDISK=y
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+CONFIG_KEXEC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL 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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# 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=m
+CONFIG_IP_NF_AMANDA=m
+# 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=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+# CONFIG_IP_NF_MATCH_CONNBYTES is not set
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+# 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=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_TARGET_CONNMARK=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+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=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_IDEDMA_ONLYDISK=y
+CONFIG_BLK_DEV_AEC62XX=y
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# 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=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# 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_STNIC 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_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NE2000 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_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+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
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_RS5C313_RTC=y
+# CONFIG_GEN_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
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_OBSOLETE_OSS_USB_DRIVER=y
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_MIDI=m
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_PWC=m
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+CONFIG_UFS_FS=m
+CONFIG_UFS_FS_WRITE=y
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig
new file mode 100644
index 00000000000..d597fc57154
--- /dev/null
+++ b/arch/sh/configs/r7780rp_defconfig
@@ -0,0 +1,1099 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-sh
+# Sat Jan 7 19:47:53 2006
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R77703DRP is not set
+CONFIG_SH_R7780RP=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_32BIT=y
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+CONFIG_SH_STORE_QUEUES=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=6
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=128M console=ttySC0,115200 root=/dev/hda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDE_SATA=y
+CONFIG_BLK_DEV_IDEDISK=m
+CONFIG_IDEDISK_MULTI_MODE=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=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=m
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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=m
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=m
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# 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_STNIC 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
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NE2000=y
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# 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 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE 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_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# 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_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+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
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_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_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se73180_defconfig b/arch/sh/configs/se73180_defconfig
index d217e44c89a..fe19feb95ca 100644
--- a/arch/sh/configs/se73180_defconfig
+++ b/arch/sh/configs/se73180_defconfig
@@ -78,6 +78,7 @@ CONFIG_SH_73180_SOLUTION_ENGINE=y
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
# CONFIG_SH_EDOSK7705 is not set
# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
new file mode 100644
index 00000000000..948e507b52b
--- /dev/null
+++ b/arch/sh/configs/se7343_defconfig
@@ -0,0 +1,997 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug 7 20:14:44 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+CONFIG_SOLUTION_ENGINE=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+CONFIG_SH_7343_SOLUTION_ENGINE=y
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+CONFIG_CPU_SUBTYPE_SH7343=y
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_32BIT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=27000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+CONFIG_SMC91X=y
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SH7343=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 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
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SuperH devices
+#
+CONFIG_SH7343_SIU=m
+CONFIG_AK4537_CODEC=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig
new file mode 100644
index 00000000000..ec9a3034daa
--- /dev/null
+++ b/arch/sh/configs/sh7710voipgw_defconfig
@@ -0,0 +1,913 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug 7 17:07:06 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+CONFIG_SH_7710VOIPGW=y
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7710=y
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32768000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+# 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 is not set
+# 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=m
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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
+#
+CONFIG_NET_SCH_CBQ=y
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=y
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_NET_CLS_FW is not set
+CONFIG_NET_CLS_U32=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+CONFIG_MTD_SH7710VOIPGW=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP 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
+
+#
+# Telephony Support
+#
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig
new file mode 100644
index 00000000000..382b3bd3963
--- /dev/null
+++ b/arch/sh/configs/shmin_defconfig
@@ -0,0 +1,827 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Wed Aug 2 01:45:03 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PTRACE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_UID16 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+# CONFIG_SLAB is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7709_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+CONFIG_SH_SHMIN=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+CONFIG_CPU_SUBTYPE_SH7706=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00210000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 root=1f01 mtdparts=phys_mapped_flash:64k(firm)ro,-(sys) netdev=34,0x300,eth0 "
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+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_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xa0000000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+CONFIG_NE2000=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+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 is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+# CONFIG_SYSFS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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 is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UNWIND_INFO is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
new file mode 100644
index 00000000000..1db2904de9e
--- /dev/null
+++ b/arch/sh/configs/titan_defconfig
@@ -0,0 +1,1367 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-sh
+# Wed Nov 9 00:35:56 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+CONFIG_SH_TITAN=y
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08030000
+CONFIG_MEMORY_SIZE=0x7fd0000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=30000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x009e0000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+#CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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 is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+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=m
+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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_NFQUEUE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=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_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+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
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_SSFDC=y
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# 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=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NE2000 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 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139_OLD_RX_RESET=y
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# 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_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+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
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 0f15216cd39..defc13c37d4 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -11,6 +11,8 @@ config SH_DMA
config NR_ONCHIP_DMA_CHANNELS
depends on SH_DMA
int "Number of on-chip DMAC channels"
+ default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
+ default "12" if CPU_SUBTYPE_SH7780
default "4"
help
This allows you to specify the number of channels that the on-chip
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL
are dual-address capable.
endmenu
-
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index 0f866f8789f..9cb07092418 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -3,7 +3,7 @@
*
* G2 bus DMA support
*
- * Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2003 - 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-
+#include <asm/cacheflush.h>
#include <asm/mach/sysasic.h>
#include <asm/mach/dma.h>
#include <asm/dma.h>
@@ -47,17 +47,31 @@ struct g2_dma_info {
static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
+#define g2_bytes_remaining(i) \
+ ((g2_dma->channel[i].size - \
+ g2_dma->status[i].size) & 0x0fffffff)
+
static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- /* FIXME: Do some meaningful completion work here.. */
- return IRQ_HANDLED;
-}
+ int i;
-static struct irqaction g2_dma_irq = {
- .name = "g2 DMA handler",
- .handler = g2_dma_interrupt,
- .flags = IRQF_DISABLED,
-};
+ for (i = 0; i < G2_NR_DMA_CHANNELS; i++) {
+ if (g2_dma->status[i].status & 0x20000000) {
+ unsigned int bytes = g2_bytes_remaining(i);
+
+ if (likely(bytes == 0)) {
+ struct dma_info *info = dev_id;
+ struct dma_channel *chan = info->channels + i;
+
+ wake_up(&chan->wait_queue);
+
+ return IRQ_HANDLED;
+ }
+ }
+ }
+
+ return IRQ_NONE;
+}
static int g2_enable_dma(struct dma_channel *chan)
{
@@ -135,8 +149,14 @@ static int g2_xfer_dma(struct dma_channel *chan)
return 0;
}
+static int g2_get_residue(struct dma_channel *chan)
+{
+ return g2_bytes_remaining(chan->chan);
+}
+
static struct dma_ops g2_dma_ops = {
.xfer = g2_xfer_dma,
+ .get_residue = g2_get_residue,
};
static struct dma_info g2_dma_info = {
@@ -148,13 +168,22 @@ static struct dma_info g2_dma_info = {
static int __init g2_dma_init(void)
{
- setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
+ int ret;
+
+ ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+ "g2 DMA handler", &g2_dma_info);
+ if (unlikely(ret))
+ return -EINVAL;
/* Magic */
g2_dma->wait_state = 27;
g2_dma->magic = 0x4659404f;
- return register_dmac(&g2_dma_info);
+ ret = register_dmac(&g2_dma_info);
+ if (unlikely(ret != 0))
+ free_irq(HW_EVENT_G2_DMA, 0);
+
+ return ret;
}
static void __exit g2_dma_exit(void)
@@ -169,4 +198,3 @@ module_exit(g2_dma_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("G2 bus DMA driver");
MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index 30a580aa7cb..3b0b0f60bb3 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -18,8 +18,8 @@
#include <asm/dma.h>
#include <asm/io.h>
-static unsigned int xfer_complete = 0;
-static int count = 0;
+static unsigned int xfer_complete;
+static int count;
static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -107,4 +107,3 @@ module_exit(pvr2_dma_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index e028a2d2a4e..cbbe8bce3d6 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -11,14 +11,10 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-
#include <linux/init.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/dreamcast/dma.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "dma-sh.h"
@@ -84,18 +80,23 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
static int sh_dmac_request_dma(struct dma_channel *chan)
{
- char name[32];
+ if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
+ return 0;
- snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
+ chan->name = kzalloc(32, GFP_KERNEL);
+ if (unlikely(chan->name == NULL))
+ return -ENOMEM;
+ snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
chan->chan);
return request_irq(get_dmte_irq(chan->chan), dma_tei,
- IRQF_DISABLED, name, chan);
+ IRQF_DISABLED, chan->name, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
{
free_irq(get_dmte_irq(chan->chan), chan);
+ kfree(chan->name);
}
static void
@@ -259,7 +260,7 @@ static int __init sh_dmac_init(void)
#ifdef CONFIG_CPU_SH4
make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
- if (i < 0)
+ if (unlikely(i < 0))
return i;
#endif
@@ -274,7 +275,7 @@ static int __init sh_dmac_init(void)
* been set.
*/
i = dmaor_reset();
- if (i < 0)
+ if (unlikely(i != 0))
return i;
return register_dmac(info);
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 365bc16a4a8..9e00cb8a39e 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -6,7 +6,8 @@ obj-y += pci.o
obj-$(CONFIG_PCI_AUTO) += pci-auto.o
obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
dma-dreamcast.o
@@ -14,3 +15,6 @@ obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o
obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
+obj-$(CONFIG_SH_R7780RP) += ops-r7780rp.o fixups-r7780rp.o
+obj-$(CONFIG_SH_TITAN) += ops-titan.o
+obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index 63b1c6f4b8d..c0af5f7ef41 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -4,7 +4,7 @@
* PCI fixups for the Sega Dreamcast
*
* Copyright (C) 2001, 2002 M. R. Brown
- * Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2002, 2003, 2006 Paul Mundt
*
* This file originally bore the message (with enclosed-$):
* Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
@@ -45,36 +45,16 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
printk("PCI: Failed resource fixup\n");
}
}
-
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
- /*
- * We don't have any sub bus to fix up, and this is a rather
- * stupid place to put general device fixups. Don't do it.
- * Use the pcibios_fixups table or suffer the consequences.
+ /*
+ * The interrupt routing semantics here are quite trivial.
+ *
+ * We basically only support one interrupt, so we only bother
+ * updating a device's interrupt line with this single shared
+ * interrupt. Keeps routing quite simple, doesn't it?
*/
+ return GAPSPCI_IRQ;
}
-
-void __init pcibios_fixup_irqs(void)
-{
- struct pci_dev *dev = 0;
-
- for_each_pci_dev(dev) {
- /*
- * The interrupt routing semantics here are quite trivial.
- *
- * We basically only support one interrupt, so we only bother
- * updating a device's interrupt line with this single shared
- * interrupt. Keeps routing quite simple, doesn't it?
- */
- printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n",
- pci_name(dev));
-
- dev->irq = GAPSPCI_IRQ;
-
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
new file mode 100644
index 00000000000..3e321df65d2
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -0,0 +1,45 @@
+/*
+ * arch/sh/drivers/pci/fixups-r7780rp.c
+ *
+ * Highlander R7780RP-1 PCI fixups
+ *
+ * Copyright (C) 2003 Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/pci.h>
+#include "pci-sh4.h"
+#include <asm/io.h>
+
+int pci_fixup_pcic(void)
+{
+ pci_write_reg(0x000043ff, SH4_PCIINTM);
+ pci_write_reg(0x0000380f, SH4_PCIAINTM);
+
+ pci_write_reg(0xfbb00047, SH7780_PCICMD);
+ pci_write_reg(0x00000000, SH7780_PCIIBAR);
+
+ pci_write_reg(0x00011912, SH7780_PCISVID);
+ pci_write_reg(0x08000000, SH7780_PCICSCR0);
+ pci_write_reg(0x0000001b, SH7780_PCICSAR0);
+ pci_write_reg(0xfd000000, SH7780_PCICSCR1);
+ pci_write_reg(0x0000000f, SH7780_PCICSAR1);
+
+ pci_write_reg(0xfd000000, SH7780_PCIMBR0);
+ pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+ pci_write_reg(0xc0000000, SH7780_PCIMBR2);
+ pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+ /* Set IOBR for windows containing area specified in pci.h */
+ pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
+ SH7780_PCIIOBR);
+ pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
+
+ return 0;
+}
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 0c590fc7a08..e72ceb560d5 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -10,8 +10,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-#include "pci-sh7751.h"
-#include <asm/io.h>
+#include "pci-sh4.h"
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
@@ -22,22 +21,23 @@ int pci_fixup_pcic(void)
bcr1 = inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- outl(bcr1, PCI_REG(SH7751_PCIBCR1));
+ pci_write_reg(bcr1, SH4_PCIBCR1);
/* Enable all interrupts, so we known what to fix */
- outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM));
- outl(0x0000380f, PCI_REG(SH7751_PCIAINTM));
+ pci_write_reg(0x0000c3ff, SH4_PCIINTM);
+ pci_write_reg(0x0000380f, SH4_PCIAINTM);
- outl(0xfb900047, PCI_REG(SH7751_PCICONF1));
- outl(0xab000001, PCI_REG(SH7751_PCICONF4));
+ pci_write_reg(0xfb900047, SH7751_PCICONF1);
+ pci_write_reg(0xab000001, SH7751_PCICONF4);
mcr = inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- outl(mcr, PCI_REG(SH7751_PCIMCR));
+ pci_write_reg(mcr, SH4_PCIMCR);
+
+ pci_write_reg(0x0c000000, SH7751_PCICONF5);
+ pci_write_reg(0xd0000000, SH7751_PCICONF6);
+ pci_write_reg(0x0c000000, SH4_PCILAR0);
+ pci_write_reg(0x00000000, SH4_PCILAR1);
- outl(0x0c000000, PCI_REG(SH7751_PCICONF5));
- outl(0xd0000000, PCI_REG(SH7751_PCICONF6));
- outl(0x0c000000, PCI_REG(SH7751_PCILAR0));
- outl(0x00000000, PCI_REG(SH7751_PCILAR1));
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
index 57ac26c2171..2e8a18b7ee5 100644
--- a/arch/sh/drivers/pci/fixups-sh03.c
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -3,11 +3,7 @@
#include <linux/types.h>
#include <linux/pci.h>
-/*
- * IRQ functions
- */
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
@@ -17,8 +13,9 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
case 8: return 5; /* eth1 */
case 6: return 2; /* PCI bridge */
default:
- printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
- return 2;
+ printk(KERN_ERR "PCI: Bad IRQ mapping request "
+ "for slot %d\n", slot);
+ return 2;
}
} else {
switch (pin) {
@@ -32,30 +29,3 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
}
return irq;
}
-
-static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
- /* no swizzling */
- return PCI_SLOT(dev->devfn);
-}
-
-static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
- irq = pcibios_map_platform_irq(slot, pin, dev);
- if( irq < 0 ) {
- pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
- return irq;
- }
-
- pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
- return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
- pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq);
-}
diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c
index ae82c6ca05e..5da501bd77b 100644
--- a/arch/sh/drivers/pci/ops-bigsur.c
+++ b/arch/sh/drivers/pci/ops-bigsur.c
@@ -10,15 +10,12 @@
*
* PCI initialization for the Hitachi Big Sur Evaluation Board
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-
#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
#include <asm/bigsur/bigsur.h>
#define BIGSUR_PCI_IO 0x4000
@@ -41,11 +38,11 @@ static struct resource sh7751_mem_resource = {
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ 0, }
};
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS3_BASE_ADDR,
.size = BIGSUR_LSR0_SIZE,
@@ -58,7 +55,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
};
/*
- * Initialize the Big Sur PCI interface
+ * Initialize the Big Sur PCI interface
* Setup hardware to be Central Funtion
* Copy the BSR regs to the PCI interface
* Setup PCI windows into local RAM
@@ -68,15 +65,15 @@ int __init pcibios_init_platform(void)
return sh7751_pcic_init(&sh7751_pci_map);
}
-int pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
- /*
+ /*
* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
* interface is on the wrong end of the board so that it can also
* support a V320 CPI interface chip... Therefor the IRQ mapping is
* somewhat use dependent... I'l assume a linear map for now, i.e.
* INTA=slot0,pin0... INTD=slot3,pin0...
- */
+ */
int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
@@ -84,4 +81,3 @@ int pcibios_map_platform_irq(u8 slot, u8 pin)
return irq;
}
-
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/ops-landisk.c
new file mode 100644
index 00000000000..ada301c21fe
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-landisk.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/drivers/pci/ops-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = 0x4000,
+ .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+ {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
+ {NULL, NULL, NULL, 0, 0},
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = (64 << 20), /* 64MB */
+ },
+
+ .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ /*
+ * slot0: pin1-4 = irq5,6,7,8
+ * slot1: pin1-4 = irq6,7,8,5
+ * slot2: pin1-4 = irq7,8,5,6
+ * slot3: pin1-4 = irq8,5,6,7
+ */
+ int irq = ((slot + pin - 1) & 0x3) + 5;
+
+ if ((slot | (pin - 1)) > 0x3) {
+ printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+ slot, pin - 1 + 'A');
+ return -1;
+ }
+ return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
new file mode 100644
index 00000000000..554d5ed2c58
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-r7780rp.c
@@ -0,0 +1,75 @@
+/*
+ * Author: Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return IRQ_PCISLOT1; /* PCI Interrupt #1 */
+ case 1: return IRQ_PCISLOT2; /* PCI Interrupt #2 */
+ case 2: return IRQ_PCISLOT3; /* PCI Interrupt #3 */
+ case 3: return IRQ_PCISLOT4; /* PCI Interrupt E4 */
+ default:
+ printk(KERN_ERR "PCI: Bad IRQ mapping "
+ "request for slot %d, func %d\n", slot, pin-1);
+ return -1;
+ }
+}
+
+static struct resource sh7780_io_resource = {
+ .name = "SH7780_IO",
+ .start = 0x2000,
+ .end = 0x2000 + SH7780_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7780_mem_resource = {
+ .name = "SH7780_mem",
+ .start = SH7780_PCI_MEMORY_BASE,
+ .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7780_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+ .window0 = {
+ .base = SH7780_CS2_BASE_ADDR,
+ .size = 0x04000000,
+ },
+
+ .window1 = {
+ .base = SH7780_CS3_BASE_ADDR,
+ .size = 0x04000000,
+ },
+
+ .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+ return sh7780_pcic_init(&sh7780_pci_map);
+}
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
index 83171d10141..88f44e24542 100644
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ b/arch/sh/drivers/pci/ops-rts7751r2d.c
@@ -17,12 +17,11 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/module.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
switch (slot) {
case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */
@@ -52,12 +51,12 @@ static struct resource sh7751_mem_resource = {
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS3_BASE_ADDR,
.size = 0x04000000,
@@ -68,7 +67,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.size = 0x00000000, /* Unused */
},
- .flags = SH7751_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
new file mode 100644
index 00000000000..2d4371009a5
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -0,0 +1,164 @@
+/*
+ * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
+ *
+ * Copyright (C) 2002 - 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/pci.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+/*
+ * Direct access to PCI hardware...
+ */
+#define CONFIG_CMD(bus, devfn, where) \
+ P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static DEFINE_SPINLOCK(sh4_pci_lock);
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ unsigned long flags;
+ u32 data;
+
+ /*
+ * PCIPDR may only be accessed as 32 bit words,
+ * so we must do byte alignment by hand
+ */
+ spin_lock_irqsave(&sh4_pci_lock, flags);
+ pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(SH4_PCIPDR);
+ spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+ switch (size) {
+ case 1:
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ break;
+ case 2:
+ *val = (data >> ((where & 2) << 3)) & 0xffff;
+ break;
+ case 4:
+ *val = data;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since SH4 only does 32bit access we'll have to do a read,
+ * mask,write operation.
+ * We'll allow an odd byte offset, though it should be illegal.
+ */
+static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ unsigned long flags;
+ int shift;
+ u32 data;
+
+ spin_lock_irqsave(&sh4_pci_lock, flags);
+ pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(SH4_PCIPDR);
+ spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+ switch (size) {
+ case 1:
+ shift = (where & 3) << 3;
+ data &= ~(0xff << shift);
+ data |= ((val & 0xff) << shift);
+ break;
+ case 2:
+ shift = (where & 2) << 3;
+ data &= ~(0xffff << shift);
+ data |= ((val & 0xffff) << shift);
+ break;
+ case 4:
+ data = val;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ pci_write_reg(data, SH4_PCIPDR);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh4_pci_ops = {
+ .read = sh4_pci_read,
+ .write = sh4_pci_write,
+};
+
+/*
+ * Not really related to pci_ops, but it's common and not worth shoving
+ * somewhere else for now..
+ */
+static unsigned int pci_probe = PCI_PROBE_CONF1;
+
+int __init sh4_pci_check_direct(void)
+{
+ /*
+ * Check if configuration works.
+ */
+ if (pci_probe & PCI_PROBE_CONF1) {
+ unsigned int tmp = pci_read_reg(SH4_PCIPAR);
+
+ pci_write_reg(P1SEG, SH4_PCIPAR);
+
+ if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
+ pci_write_reg(tmp, SH4_PCIPAR);
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+
+ return 0;
+ }
+
+ pci_write_reg(tmp, SH4_PCIPAR);
+ }
+
+ pr_debug("PCI: pci_check_direct failed\n");
+ return -EINVAL;
+}
+
+/* Handle generic fixups */
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
+ */
+ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
+ for(i = 0; i < 4; i++) {
+ struct resource *r = &d->resource[i];
+
+ if ((r->start & ~0x80) == 0x374) {
+ r->start |= 2;
+ r->end = r->start;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+char * __init pcibios_setup(char *str)
+{
+ if (!strcmp(str, "off")) {
+ pci_probe = 0;
+ return NULL;
+ }
+
+ return str;
+}
diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c
index 3cbd14dd28f..53dd893d4e5 100644
--- a/arch/sh/drivers/pci/ops-snapgear.c
+++ b/arch/sh/drivers/pci/ops-snapgear.c
@@ -2,7 +2,7 @@
* arch/sh/drivers/pci/ops-snapgear.c
*
* Author: David McCullough <davidm@snapgear.com>
- *
+ *
* Ported to new API by Paul Mundt <lethal@linux-sh.org>
*
* Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
@@ -12,15 +12,11 @@
*
* PCI initialization for the SnapGear boards
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
#define SNAPGEAR_PCI_IO 0x4000
#define SNAPGEAR_PCI_MEM 0xfd000000
@@ -43,14 +39,12 @@ static struct resource sh7751_mem_resource = {
.flags = IORESOURCE_MEM,
};
-extern struct pci_ops sh7751_pci_ops;
-
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ 0, }
};
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS2_BASE_ADDR,
.size = SNAPGEAR_LSR0_SIZE,
@@ -61,11 +55,11 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.size = SNAPGEAR_LSR1_SIZE,
},
- .flags = SH7751_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
/*
- * Initialize the SnapGear PCI interface
+ * Initialize the SnapGear PCI interface
* Setup hardware to be Central Funtion
* Copy the BSR regs to the PCI interface
* Setup PCI windows into local RAM
@@ -75,7 +69,7 @@ int __init pcibios_init_platform(void)
return sh7751_pcic_init(&sh7751_pci_map);
}
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = -1;
@@ -98,4 +92,3 @@ void __init pcibios_fixup(void)
{
/* Nothing to fixup .. */
}
-
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c
new file mode 100644
index 00000000000..c6097bcd97f
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-titan.c
@@ -0,0 +1,83 @@
+/*
+ * arch/sh/drivers/pci/ops-titan.c
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Modified from ops-snapgear.c written by David McCullough
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Titan boards
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/titan.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */
+ case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */
+ case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */
+ case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */
+ case 4: irq = TITAN_IRQ_USB; break; /* USB */
+ default:
+ printk(KERN_INFO "PCI: Bad IRQ mapping "
+ "request for slot %d\n", slot);
+ return -1;
+ }
+
+ printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
+ slot, pin - 1 + 'A', irq);
+
+ return irq;
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751_IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751_mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS2_BASE_ADDR,
+ .size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */
+ },
+
+ .window1 = {
+ .base = SH7751_CS2_BASE_ADDR,
+ .size = SH7751_MEM_REGION_SIZE*2,
+ },
+
+ .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
index 4cef4d1d8c8..ecf16344f94 100644
--- a/arch/sh/drivers/pci/pci-auto.c
+++ b/arch/sh/drivers/pci/pci-auto.c
@@ -45,11 +45,11 @@
#include <linux/types.h>
#include <linux/pci.h>
-#undef DEBUG
-#ifdef DEBUG
+#define DEBUG
+#ifdef DEBUG
#define DBG(x...) printk(x)
#else
-#define DBG(x...)
+#define DBG(x...)
#endif
/*
@@ -102,7 +102,7 @@ static u32 pciauto_upper_iospc;
static u32 pciauto_lower_memspc;
static u32 pciauto_upper_memspc;
-static void __init
+static void __init
pciauto_setup_bars(struct pci_channel *hose,
int top_bus,
int current_bus,
@@ -116,7 +116,6 @@ pciauto_setup_bars(struct pci_channel *hose,
int found_mem64 = 0;
for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
u32 bar_addr;
/* Read the old BAR value */
@@ -125,7 +124,6 @@ pciauto_setup_bars(struct pci_channel *hose,
pci_devfn,
bar,
&bar_addr);
-#endif
/* Tickle the BAR and get the response */
early_write_config_dword(hose, top_bus,
@@ -140,8 +138,7 @@ pciauto_setup_bars(struct pci_channel *hose,
bar,
&bar_response);
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
- /*
+ /*
* Write the old BAR value back out, only update the BAR
* if we implicitly want resources to be updated, which
* is done by the generic code further down. -- PFM.
@@ -151,7 +148,6 @@ pciauto_setup_bars(struct pci_channel *hose,
pci_devfn,
bar,
bar_addr);
-#endif
/* If BAR is not implemented go to the next BAR */
if (!bar_response)
@@ -177,7 +173,7 @@ retry:
PCI_BASE_ADDRESS_MEM_TYPE_64)
found_mem64 = 1;
- addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
+ addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
upper_limit = &pciauto_upper_memspc;
lower_limit = &pciauto_lower_memspc;
DBG(" Mem");
@@ -193,22 +189,22 @@ retry:
if ((bar_value + bar_size) > *upper_limit) {
if (bar_response & PCI_BASE_ADDRESS_SPACE) {
if (io_resource_inuse->child) {
- io_resource_inuse =
+ io_resource_inuse =
io_resource_inuse->child;
- pciauto_lower_iospc =
+ pciauto_lower_iospc =
io_resource_inuse->start;
- pciauto_upper_iospc =
+ pciauto_upper_iospc =
io_resource_inuse->end + 1;
goto retry;
}
} else {
if (mem_resource_inuse->child) {
- mem_resource_inuse =
+ mem_resource_inuse =
mem_resource_inuse->child;
- pciauto_lower_memspc =
+ pciauto_lower_memspc =
mem_resource_inuse->start;
- pciauto_upper_memspc =
+ pciauto_upper_memspc =
mem_resource_inuse->end + 1;
goto retry;
}
@@ -230,7 +226,7 @@ retry:
* If we are a 64-bit decoder then increment to the
* upper 32 bits of the bar and force it to locate
* in the lower 4GB of memory.
- */
+ */
if (found_mem64) {
bar += 4;
early_write_config_dword(hose, top_bus,
@@ -362,7 +358,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
{
u32 temp;
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
/*
* [jsun] we always bump up baselines a little, so that if there
* nothing behind P2P bridge, we don't wind up overlapping IO/MEM
@@ -370,7 +365,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
*/
pciauto_lower_memspc += 1;
pciauto_lower_iospc += 1;
-#endif
/*
* Configure subordinate bus number. The PCI subsystem
@@ -396,11 +390,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
* configured by this routine to happily live behind a
* P2P bridge in a system.
*/
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
- pciauto_lower_memspc += 0x00400000;
- pciauto_lower_iospc += 0x00004000;
-#endif
-
/* Align memory and I/O to 4KB and 4 byte boundaries. */
pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
& ~(0x1000 - 1);
@@ -433,12 +422,12 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
int devfn_stop = 0xff;
sub_bus = current_bus;
-
+
if (hose->first_devfn)
devfn_start = hose->first_devfn;
if (hose->last_devfn)
devfn_stop = hose->last_devfn;
-
+
for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
if (PCI_FUNC(pci_devfn) && !found_multi)
@@ -471,9 +460,6 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
current_bus, sub_bus + 1);
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
-#endif
pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
pci_devfn, sub_bus);
DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
@@ -490,10 +476,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
/* Place CardBus Socket/ExCA registers */
pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
-
+
pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
current_bus, pci_devfn, sub_bus);
-
+
DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
sub_bus + 1,
pciauto_lower_iospc, pciauto_lower_memspc);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
new file mode 100644
index 00000000000..5a61d6041f2
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -0,0 +1,180 @@
+#ifndef __PCI_SH4_H
+#define __PCI_SH4_H
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#include "pci-sh7780.h"
+#else
+#include "pci-sh7751.h"
+#endif
+
+#include <asm/io.h>
+
+/* startup values */
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+#define SH4_PCICR 0x100 /* PCI Control Register */
+ #define SH4_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
+ #define SH4_PCICR_FTO 0x00000400 /* TRDY/IRDY Enable */
+ #define SH4_PCICR_TRSB 0x00000200 /* Target Read Single */
+ #define SH4_PCICR_BSWP 0x00000100 /* Target Byte Swap */
+ #define SH4_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */
+ #define SH4_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */
+ #define SH4_PCICR_MD 0x00000030 /* MD9 and MD10 status */
+ #define SH4_PCICR_SERR 0x00000008 /* SERR output assert */
+ #define SH4_PCICR_INTA 0x00000004 /* INTA output assert */
+ #define SH4_PCICR_PRST 0x00000002 /* PCI Reset Assert */
+ #define SH4_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */
+#define SH4_PCILSR0 0x104 /* PCI Local Space Register0 */
+#define SH4_PCILSR1 0x108 /* PCI Local Space Register1 */
+#define SH4_PCILAR0 0x10C /* PCI Local Addr Register1 */
+#define SH4_PCILAR1 0x110 /* PCI Local Addr Register1 */
+#define SH4_PCIINT 0x114 /* PCI Interrupt Register */
+ #define SH4_PCIINT_MLCK 0x00008000 /* Master Lock Error */
+ #define SH4_PCIINT_TABT 0x00004000 /* Target Abort Error */
+ #define SH4_PCIINT_TRET 0x00000200 /* Target Retry Error */
+ #define SH4_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */
+ #define SH4_PCIINT_PRTY 0x00000080 /* Address Parity Error */
+ #define SH4_PCIINT_SERR 0x00000040 /* SERR Detection Error */
+ #define SH4_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */
+ #define SH4_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Err Det. */
+ #define SH4_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */
+ #define SH4_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */
+ #define SH4_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */
+ #define SH4_PCIINT_MRPD 0x00000001 /* Master Read PERR Detect */
+#define SH4_PCIINTM 0x118 /* PCI Interrupt Mask */
+#define SH4_PCIALR 0x11C /* Error Address Register */
+#define SH4_PCICLR 0x120 /* Error Command/Data */
+ #define SH4_PCICLR_MPIO 0x80000000
+ #define SH4_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */
+ #define SH4_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */
+ #define SH4_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */
+ #define SH4_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */
+ #define SH4_PCICLR_TGT 0x04000000 /* Target Transfer Error */
+ #define SH4_PCICLR_CMDL 0x0000000F /* PCI Command at Error */
+#define SH4_PCIAINT 0x130 /* Arbiter Interrupt Register */
+ #define SH4_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */
+ #define SH4_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */
+ #define SH4_PCIAINT_MBTO 0x00001000 /* Master Bus Time Out */
+ #define SH4_PCIAINT_TABT 0x00000008 /* Target Abort */
+ #define SH4_PCIAINT_MABT 0x00000004 /* Master Abort */
+ #define SH4_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */
+ #define SH4_PCIAINT_WDPE 0x00000001 /* Write Data Parity Error */
+#define SH4_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
+#define SH4_PCIBMLR 0x138 /* Error Bus Master Register */
+ #define SH4_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */
+ #define SH4_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */
+ #define SH4_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */
+ #define SH4_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */
+ #define SH4_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */
+#define SH4_PCIDMABT 0x140 /* DMA Transfer Arb. Register */
+ #define SH4_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */
+#define SH4_PCIDPA0 0x180 /* DMA0 Transfer Addr. */
+#define SH4_PCIDLA0 0x184 /* DMA0 Local Addr. */
+#define SH4_PCIDTC0 0x188 /* DMA0 Transfer Cnt. */
+#define SH4_PCIDCR0 0x18C /* DMA0 Control Register */
+ #define SH4_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */
+ #define SH4_PCIDCR_MAST 0x00000100 /* DMA Termination Type */
+ #define SH4_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/
+ #define SH4_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */
+ #define SH4_PCIDCR_LHLD 0x00000020 /* Local Address Control */
+ #define SH4_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/
+ #define SH4_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */
+ #define SH4_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */
+ #define SH4_PCIDCR_STOP 0x00000002 /* Force DMA Stop */
+ #define SH4_PCIDCR_STRT 0x00000001 /* DMA Start */
+#define SH4_PCIDPA1 0x190 /* DMA1 Transfer Addr. */
+#define SH4_PCIDLA1 0x194 /* DMA1 Local Addr. */
+#define SH4_PCIDTC1 0x198 /* DMA1 Transfer Cnt. */
+#define SH4_PCIDCR1 0x19C /* DMA1 Control Register */
+#define SH4_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. */
+#define SH4_PCIDLA2 0x1A4 /* DMA2 Local Addr. */
+#define SH4_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. */
+#define SH4_PCIDCR2 0x1AC /* DMA2 Control Register */
+#define SH4_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. */
+#define SH4_PCIDLA3 0x1B4 /* DMA3 Local Addr. */
+#define SH4_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. */
+#define SH4_PCIDCR3 0x1BC /* DMA3 Control Register */
+#define SH4_PCIPAR 0x1C0 /* PIO Address Register */
+ #define SH4_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */
+ #define SH4_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */
+ #define SH4_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */
+ #define SH4_PCIPAR_REGAD 0x000000FC /* Register Address Number */
+#define SH4_PCIMBR 0x1C4 /* Memory Base Address */
+ #define SH4_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */
+ #define SH4_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */
+#define SH4_PCIIOBR 0x1C8 /* I/O Base Address Register */
+ #define SH4_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */
+ #define SH4_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */
+#define SH4_PCIPINT 0x1CC /* Power Mgmnt Int. Register */
+ #define SH4_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */
+ #define SH4_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */
+#define SH4_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */
+#define SH4_PCICLKR 0x1D4 /* Clock Ctrl. Register */
+ #define SH4_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */
+ #define SH4_PCICLKR_BCSTP 0x00000001 /* BCLK Clock Stop */
+/* For definitions of BCR, MCR see ... */
+#define SH4_PCIBCR1 0x1E0 /* Memory BCR1 Register */
+ #define SH4_PCIMBR0 SH4_PCIBCR1
+#define SH4_PCIBCR2 0x1E4 /* Memory BCR2 Register */
+ #define SH4_PCIMBMR0 SH4_PCIBCR2
+#define SH4_PCIWCR1 0x1E8 /* Wait Control 1 Register */
+#define SH4_PCIWCR2 0x1EC /* Wait Control 2 Register */
+#define SH4_PCIWCR3 0x1F0 /* Wait Control 3 Register */
+ #define SH4_PCIMBR2 SH4_PCIWCR3
+#define SH4_PCIMCR 0x1F4 /* Memory Control Register */
+#define SH4_PCIBCR3 0x1f8 /* Memory BCR3 Register */
+#define SH4_PCIPCTR 0x200 /* Port Control Register */
+ #define SH4_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */
+ #define SH4_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */
+ #define SH4_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */
+ #define SH4_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */
+ #define SH4_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */
+ #define SH4_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */
+ #define SH4_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */
+ #define SH4_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */
+ #define SH4_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */
+#define SH4_PCIPDTR 0x204 /* Port Data Register */
+ #define SH4_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */
+ #define SH4_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */
+ #define SH4_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */
+ #define SH4_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */
+ #define SH4_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */
+ #define SH4_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
+#define SH4_PCIPDR 0x220 /* Port IO Data Register */
+
+/* Flags */
+#define SH4_PCIC_NO_RESET 0x0001
+
+/* arch/sh/kernel/drivers/pci/ops-sh4.c */
+extern struct pci_ops sh4_pci_ops;
+int sh4_pci_check_direct(void);
+int pci_fixup_pcic(void);
+
+struct sh4_pci_address_space {
+ unsigned long base;
+ unsigned long size;
+};
+
+struct sh4_pci_address_map {
+ struct sh4_pci_address_space window0;
+ struct sh4_pci_address_space window1;
+ unsigned long flags;
+};
+
+static inline void pci_write_reg(unsigned long val, unsigned long reg)
+{
+ outl(val, PCI_REG(reg));
+}
+
+static inline unsigned long pci_read_reg(unsigned long reg)
+{
+ return inl(PCI_REG(reg));
+}
+#endif /* __PCI_SH4_H */
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 682f3dae305..dbe83788498 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -15,180 +15,14 @@
#undef DEBUG
-#include <linux/types.h>
-#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
+#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/irq.h>
#include <linux/delay.h>
-
-#include <asm/machvec.h>
+#include "pci-sh4.h"
+#include <asm/addrspace.h>
#include <asm/io.h>
-#include "pci-sh7751.h"
-
-static unsigned int pci_probe = PCI_PROBE_CONF1;
-extern int pci_fixup_pcic(void);
-
-void pcibios_fixup_irqs(void) __attribute__ ((weak));
-
-/*
- * Direct access to PCI hardware...
- */
-
-#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
-
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *val)
-{
- unsigned long flags;
- u32 data;
-
- /*
- * PCIPDR may only be accessed as 32 bit words,
- * so we must do byte alignment by hand
- */
- local_irq_save(flags);
- outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
- data = inl(PCI_REG(SH7751_PCIPDR));
- local_irq_restore(flags);
-
- switch (size) {
- case 1:
- *val = (data >> ((where & 3) << 3)) & 0xff;
- break;
- case 2:
- *val = (data >> ((where & 2) << 3)) & 0xffff;
- break;
- case 4:
- *val = data;
- break;
- default:
- return PCIBIOS_FUNC_NOT_SUPPORTED;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * Since SH7751 only does 32bit access we'll have to do a read,
- * mask,write operation.
- * We'll allow an odd byte offset, though it should be illegal.
- */
-static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- unsigned long flags;
- int shift;
- u32 data;
-
- local_irq_save(flags);
- outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
- data = inl(PCI_REG(SH7751_PCIPDR));
- local_irq_restore(flags);
-
- switch (size) {
- case 1:
- shift = (where & 3) << 3;
- data &= ~(0xff << shift);
- data |= ((val & 0xff) << shift);
- break;
- case 2:
- shift = (where & 2) << 3;
- data &= ~(0xffff << shift);
- data |= ((val & 0xffff) << shift);
- break;
- case 4:
- data = val;
- break;
- default:
- return PCIBIOS_FUNC_NOT_SUPPORTED;
- }
-
- outl(data, PCI_REG(SH7751_PCIPDR));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-#undef CONFIG_CMD
-
-struct pci_ops sh7751_pci_ops = {
- .read = sh7751_pci_read,
- .write = sh7751_pci_write,
-};
-
-static int __init pci_check_direct(void)
-{
- unsigned int tmp, id;
-
- /* check for SH7751/SH7751R hardware */
- id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0);
- if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
- id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
- pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
- return -ENODEV;
- }
-
- /*
- * Check if configuration works.
- */
- if (pci_probe & PCI_PROBE_CONF1) {
- tmp = inl (PCI_REG(SH7751_PCIPAR));
- outl (0x80000000, PCI_REG(SH7751_PCIPAR));
- if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
- outl (tmp, PCI_REG(SH7751_PCIPAR));
- printk(KERN_INFO "PCI: Using configuration type 1\n");
- request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
- return 0;
- }
- outl (tmp, PCI_REG(SH7751_PCIPAR));
- }
-
- pr_debug("PCI: pci_check_direct failed\n");
- return -EINVAL;
-}
-
-/***************************************************************************************/
-
-/*
- * Handle bus scanning and fixups ....
- */
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
-
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
- for(i=0; i<4; i++) {
- struct resource *r = &d->resource[i];
- if ((r->start & ~0x80) == 0x374) {
- r->start |= 2;
- r->end = r->start;
- }
- }
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-/*
- * Called after each bus is probed, but before its children
- * are examined.
- */
-
-void __init pcibios_fixup_bus(struct pci_bus *b)
-{
- pci_read_bridge_bases(b);
-}
/*
* Initialization. Try all known PCI access methods. Note that we support
@@ -196,25 +30,29 @@ void __init pcibios_fixup_bus(struct pci_bus *b)
* to access config space.
*
* Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
- * exitst and via the platform defined function pcibios_init_platform().
- * See pci_bigsur.c for implementation;
- *
- * The BIOS version of the pci functions is not yet implemented but it is left
- * in for completeness. Currently an error will be genereated at compile time.
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
*/
-
static int __init sh7751_pci_init(void)
{
+ unsigned int id;
int ret;
pr_debug("PCI: Starting intialization.\n");
- if ((ret = pci_check_direct()) != 0)
+
+ /* check for SH7751/SH7751R hardware */
+ id = pci_read_reg(SH7751_PCICONF0);
+ if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+ id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+ pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+ return -ENODEV;
+ }
+
+ if ((ret = sh4_pci_check_direct()) != 0)
return ret;
return pcibios_init_platform();
}
-
subsys_initcall(sh7751_pci_init);
static int __init __area_sdram_check(unsigned int area)
@@ -223,26 +61,26 @@ static int __init __area_sdram_check(unsigned int area)
word = inl(SH7751_BCR1);
/* check BCR for SDRAM in area */
- if(((word >> area) & 1) == 0) {
+ if (((word >> area) & 1) == 0) {
printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
area, word);
return 0;
}
- outl(word, PCI_REG(SH7751_PCIBCR1));
+ pci_write_reg(word, SH4_PCIBCR1);
word = (u16)inw(SH7751_BCR2);
/* check BCR2 for 32bit SDRAM interface*/
- if(((word >> (area << 1)) & 0x3) != 0x3) {
+ if (((word >> (area << 1)) & 0x3) != 0x3) {
printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
area, word);
return 0;
}
- outl(word, PCI_REG(SH7751_PCIBCR2));
+ pci_write_reg(word, SH4_PCIBCR2);
return 1;
}
-int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
+int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
{
u32 reg;
u32 word;
@@ -251,39 +89,39 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
reg = inl(SH7751_BCR1);
reg |= 0x80000;
outl(reg, SH7751_BCR1);
-
+
/* Turn the clocks back on (not done in reset)*/
- outl(0, PCI_REG(SH7751_PCICLKR));
+ pci_write_reg(0, SH4_PCICLKR);
/* Clear Powerdown IRQ's (not done in reset) */
- word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
- outl(word, PCI_REG(SH7751_PCIPINT));
+ word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
+ pci_write_reg(word, SH4_PCIPINT);
/*
* This code is unused for some boards as it is done in the
* bootloader and doing it here means the MAC addresses loaded
* by the bootloader get lost.
*/
- if (!(map->flags & SH7751_PCIC_NO_RESET)) {
+ if (!(map->flags & SH4_PCIC_NO_RESET)) {
/* toggle PCI reset pin */
- word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
- outl(word,PCI_REG(SH7751_PCICR));
+ word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+ pci_write_reg(word, SH4_PCICR);
/* Wait for a long time... not 1 sec. but long enough */
mdelay(100);
- word = SH7751_PCICR_PREFIX;
- outl(word,PCI_REG(SH7751_PCICR));
+ word = SH4_PCICR_PREFIX;
+ pci_write_reg(word, SH4_PCICR);
}
-
+
/* set the command/status bits to:
* Wait Cycle Control + Parity Enable + Bus Master +
* Mem space enable
*/
word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
- outl(word, PCI_REG(SH7751_PCICONF1));
+ pci_write_reg(word, SH7751_PCICONF1);
/* define this host as the host bridge */
- word = SH7751_PCI_HOST_BRIDGE << 24;
- outl(word, PCI_REG(SH7751_PCICONF2));
+ word = PCI_BASE_CLASS_BRIDGE << 24;
+ pci_write_reg(word, SH7751_PCICONF2);
/* Set IO and Mem windows to local address
* Make PCI and local address the same for easy 1 to 1 mapping
@@ -291,46 +129,49 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
* Window1 = map->window1.size @ cached area base = SDRAM
*/
word = map->window0.size - 1;
- outl(word, PCI_REG(SH7751_PCILSR0));
+ pci_write_reg(word, SH4_PCILSR0);
word = map->window1.size - 1;
- outl(word, PCI_REG(SH7751_PCILSR1));
+ pci_write_reg(word, SH4_PCILSR1);
/* Set the values on window 0 PCI config registers */
word = P2SEGADDR(map->window0.base);
- outl(word, PCI_REG(SH7751_PCILAR0));
- outl(word, PCI_REG(SH7751_PCICONF5));
+ pci_write_reg(word, SH4_PCILAR0);
+ pci_write_reg(word, SH7751_PCICONF5);
/* Set the values on window 1 PCI config registers */
word = PHYSADDR(map->window1.base);
- outl(word, PCI_REG(SH7751_PCILAR1));
- outl(word, PCI_REG(SH7751_PCICONF6));
+ pci_write_reg(word, SH4_PCILAR1);
+ pci_write_reg(word, SH7751_PCICONF6);
- /* Set the local 16MB PCI memory space window to
+ /* Set the local 16MB PCI memory space window to
* the lowest PCI mapped address
*/
- word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
- PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
- outl(word , PCI_REG(SH7751_PCIMBR));
+ word = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+ pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
+ pci_write_reg(word , SH4_PCIMBR);
/* Map IO space into PCI IO window
* The IO window is 64K-PCIBIOS_MIN_IO in size
- * IO addresses will be translated to the
+ * IO addresses will be translated to the
* PCI IO window base address
*/
- PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
- (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+ pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+ PCIBIOS_MIN_IO, (64 << 10),
+ SH4_PCI_IO_BASE + PCIBIOS_MIN_IO);
- /*
+ /*
* XXX: For now, leave this board-specific. In the event we have other
* boards that need to do similar work, this can be wrapped.
*/
#ifdef CONFIG_SH_BIGSUR
- bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0);
+ bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
+ SH4_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
#endif
- /* Make sure the MSB's of IO window are set to access PCI space correctly */
- word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK;
- PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
- outl(word, PCI_REG(SH7751_PCIIOBR));
-
+ /* Make sure the MSB's of IO window are set to access PCI space
+ * correctly */
+ word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+ pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
+ pci_write_reg(word, SH4_PCIIOBR);
+
/* Set PCI WCRx, BCRx's, copy from BSC locations */
/* check BCR for SDRAM in specified area */
@@ -349,13 +190,13 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
/* configure the wait control registers */
word = inl(SH7751_WCR1);
- outl(word, PCI_REG(SH7751_PCIWCR1));
+ pci_write_reg(word, SH4_PCIWCR1);
word = inl(SH7751_WCR2);
- outl(word, PCI_REG(SH7751_PCIWCR2));
+ pci_write_reg(word, SH4_PCIWCR2);
word = inl(SH7751_WCR3);
- outl(word, PCI_REG(SH7751_PCIWCR3));
+ pci_write_reg(word, SH4_PCIWCR3);
word = inl(SH7751_MCR);
- outl(word, PCI_REG(SH7751_PCIMCR));
+ pci_write_reg(word, SH4_PCIMCR);
/* NOTE: I'm ignoring the PCI error IRQs for now..
* TODO: add support for the internal error interrupts and
@@ -368,49 +209,8 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
/* SH7751 init done, set central function init complete */
/* use round robin mode to stop a device starving/overruning */
- word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
- outl(word,PCI_REG(SH7751_PCICR));
+ word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
+ pci_write_reg(word, SH4_PCICR);
return 1;
}
-
-char * __init pcibios_setup(char *str)
-{
- if (!strcmp(str, "off")) {
- pci_probe = 0;
- return NULL;
- }
-
- return str;
-}
-
-/*
- * IRQ functions
- */
-static u8 __init sh7751_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
- /* no swizzling */
- return PCI_SLOT(dev->devfn);
-}
-
-static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
- irq = pcibios_map_platform_irq(slot,pin);
- if( irq < 0 ) {
- pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
- return irq;
- }
-
- pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
- return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
- pci_fixup_irqs(sh7751_no_swizzle, sh7751_pci_lookup_irq);
-}
-
diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h
index 1fee5cae10d..68e3cb5e6be 100644
--- a/arch/sh/drivers/pci/pci-sh7751.h
+++ b/arch/sh/drivers/pci/pci-sh7751.h
@@ -3,7 +3,7 @@
*
* Dustin McIntire (dustin@sensoria.com) (c) 2001
* Paul Mundt (lethal@linux-sh.org) (c) 2003
- *
+ *
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
@@ -12,28 +12,6 @@
#ifndef _PCI_SH7751_H_
#define _PCI_SH7751_H_
-#include <linux/pci.h>
-
-/* set debug level 4=verbose...1=terse */
-//#define DEBUG_PCI 3
-#undef DEBUG_PCI
-
-#ifdef DEBUG_PCI
-#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
-#else
-#define PCIDBG(n, x...)
-#endif
-
-/* startup values */
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_SORT 0x100
-#define PCI_BIOS_SORT 0x200
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
/* Platform Specific Values */
#define SH7751_VENDOR_ID 0x1054
#define SH7751_DEVICE_ID 0x3505
@@ -128,131 +106,6 @@
#define SH7751_PCICONF17_PMEN 0x00010000 /* PME Enable */
#define SH7751_PCICONF17_PWST 0x00000003 /* Power State */
/* SH7715 Internal PCI Registers */
-#define SH7751_PCICR 0x100 /* PCI Control Register */
- #define SH7751_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
- #define SH7751_PCICR_TRSB 0x00000200 /* Target Read Single */
- #define SH7751_PCICR_BSWP 0x00000100 /* Target Byte Swap */
- #define SH7751_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */
- #define SH7751_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */
- #define SH7751_PCICR_MD 0x00000030 /* MD9 and MD10 status */
- #define SH7751_PCICR_SERR 0x00000008 /* SERR output assert */
- #define SH7751_PCICR_INTA 0x00000004 /* INTA output assert */
- #define SH7751_PCICR_PRST 0x00000002 /* PCI Reset Assert */
- #define SH7751_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */
-#define SH7751_PCILSR0 0x104 /* PCI Local Space Register0 */
-#define SH7751_PCILSR1 0x108 /* PCI Local Space Register1 */
-#define SH7751_PCILAR0 0x10C /* PCI Local Address Register1 */
-#define SH7751_PCILAR1 0x110 /* PCI Local Address Register1 */
-#define SH7751_PCIINT 0x114 /* PCI Interrupt Register */
- #define SH7751_PCIINT_MLCK 0x00008000 /* Master Lock Error */
- #define SH7751_PCIINT_TABT 0x00004000 /* Target Abort Error */
- #define SH7751_PCIINT_TRET 0x00000200 /* Target Retry Error */
- #define SH7751_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */
- #define SH7751_PCIINT_PRTY 0x00000080 /* Address Parity Error */
- #define SH7751_PCIINT_SERR 0x00000040 /* SERR Detection Error */
- #define SH7751_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */
- #define SH7751_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Error Det. */
- #define SH7751_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */
- #define SH7751_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */
- #define SH7751_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */
- #define SH7751_PCIINT_MRPD 0x00000002 /* Master Read PERR Detect */
-#define SH7751_PCIINTM 0x118 /* PCI Interrupt Mask Register */
-#define SH7751_PCIALR 0x11C /* Error Address Register */
-#define SH7751_PCICLR 0x120 /* Error Command/Data Register */
- #define SH7751_PCICLR_MPIO 0x80000000 /* Error Command/Data Register */
- #define SH7751_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */
- #define SH7751_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */
- #define SH7751_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */
- #define SH7751_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */
- #define SH7751_PCICLR_TGT 0x04000000 /* Target Transfer Error */
- #define SH7751_PCICLR_CMDL 0x0000000F /* PCI Command at Error */
-#define SH7751_PCIAINT 0x130 /* Arbiter Interrupt Register */
- #define SH7751_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */
- #define SH7751_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */
- #define SH7751_PCIAINT_MBTO 0x00001000 /* Master Bus Time Out */
- #define SH7751_PCIAINT_TABT 0x00000008 /* Target Abort */
- #define SH7751_PCIAINT_MABT 0x00000004 /* Master Abort */
- #define SH7751_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */
- #define SH7751_PCIAINT_WDPE 0x00000002 /* Write Data Parity Error */
-#define SH7751_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
-#define SH7751_PCIBMLR 0x138 /* Error Bus Master Register */
- #define SH7751_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */
- #define SH7751_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */
- #define SH7751_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */
- #define SH7751_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */
- #define SH7751_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */
-#define SH7751_PCIDMABT 0x140 /* DMA Transfer Arb. Register */
- #define SH7751_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */
-#define SH7751_PCIDPA0 0x180 /* DMA0 Transfer Addr. Register */
-#define SH7751_PCIDLA0 0x184 /* DMA0 Local Addr. Register */
-#define SH7751_PCIDTC0 0x188 /* DMA0 Transfer Cnt. Register */
-#define SH7751_PCIDCR0 0x18C /* DMA0 Control Register */
- #define SH7751_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */
- #define SH7751_PCIDCR_MAST 0x00000100 /* DMA Termination Type */
- #define SH7751_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/
- #define SH7751_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */
- #define SH7751_PCIDCR_LHLD 0x00000020 /* Local Address Control */
- #define SH7751_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/
- #define SH7751_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */
- #define SH7751_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */
- #define SH7751_PCIDCR_STOP 0x00000002 /* Force DMA Stop */
- #define SH7751_PCIDCR_STRT 0x00000001 /* DMA Start */
-#define SH7751_PCIDPA1 0x190 /* DMA1 Transfer Addr. Register */
-#define SH7751_PCIDLA1 0x194 /* DMA1 Local Addr. Register */
-#define SH7751_PCIDTC1 0x198 /* DMA1 Transfer Cnt. Register */
-#define SH7751_PCIDCR1 0x19C /* DMA1 Control Register */
-#define SH7751_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. Register */
-#define SH7751_PCIDLA2 0x1A4 /* DMA2 Local Addr. Register */
-#define SH7751_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. Register */
-#define SH7751_PCIDCR2 0x1AC /* DMA2 Control Register */
-#define SH7751_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. Register */
-#define SH7751_PCIDLA3 0x1B4 /* DMA3 Local Addr. Register */
-#define SH7751_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. Register */
-#define SH7751_PCIDCR3 0x1BC /* DMA3 Control Register */
-#define SH7751_PCIPAR 0x1C0 /* PIO Address Register */
- #define SH7751_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */
- #define SH7751_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */
- #define SH7751_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */
- #define SH7751_PCIPAR_REGAD 0x000000FC /* Register Address Number */
-#define SH7751_PCIMBR 0x1C4 /* Memory Base Address Register */
- #define SH7751_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */
- #define SH7751_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */
-#define SH7751_PCIIOBR 0x1C8 /* I/O Base Address Register */
- #define SH7751_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */
- #define SH7751_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */
-#define SH7751_PCIPINT 0x1CC /* Power Mgmnt Int. Register */
- #define SH7751_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */
- #define SH7751_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */
-#define SH7751_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */
-#define SH7751_PCICLKR 0x1D4 /* Clock Ctrl. Register */
- #define SH7751_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */
- #define SH7751_PCICLKR_BCSTP 0x00000002 /* BCLK Clock Stop */
-/* For definitions of BCR, MCR see ... */
-#define SH7751_PCIBCR1 0x1E0 /* Memory BCR1 Register */
-#define SH7751_PCIBCR2 0x1E4 /* Memory BCR2 Register */
-#define SH7751_PCIWCR1 0x1E8 /* Wait Control 1 Register */
-#define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */
-#define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */
-#define SH7751_PCIMCR 0x1F4 /* Memory Control Register */
-#define SH7751_PCIBCR3 0x1f8 /* Memory BCR3 Register */
-#define SH7751_PCIPCTR 0x200 /* Port Control Register */
- #define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */
- #define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */
- #define SH7751_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */
- #define SH7751_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */
- #define SH7751_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */
- #define SH7751_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */
- #define SH7751_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */
- #define SH7751_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */
- #define SH7751_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */
-#define SH7751_PCIPDTR 0x204 /* Port Data Register */
- #define SH7751_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */
- #define SH7751_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */
- #define SH7751_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */
- #define SH7751_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */
- #define SH7751_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */
- #define SH7751_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
-#define SH7751_PCIPDR 0x220 /* Port IO Data Register */
/* Memory Control Registers */
#define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */
@@ -274,30 +127,9 @@
#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
-/* General PCI values */
-#define SH7751_PCI_HOST_BRIDGE 0x6
-
-/* Flags */
-#define SH7751_PCIC_NO_RESET 0x0001
-
-/* External functions defined per platform i.e. Big Sur, SE... (these could be routed
- * through the machine vectors... */
-extern int pcibios_init_platform(void);
-extern int pcibios_map_platform_irq(u8 slot, u8 pin);
-
-struct sh7751_pci_address_space {
- unsigned long base;
- unsigned long size;
-};
-
-struct sh7751_pci_address_map {
- struct sh7751_pci_address_space window0;
- struct sh7751_pci_address_space window1;
- unsigned long flags;
-};
+struct sh4_pci_address_map;
/* arch/sh/drivers/pci/pci-sh7751.c */
-extern int sh7751_pcic_init(struct sh7751_pci_address_map *map);
+int sh7751_pcic_init(struct sh4_pci_address_map *map);
#endif /* _PCI_SH7751_H_ */
-
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
new file mode 100644
index 00000000000..bd3064a8208
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -0,0 +1,139 @@
+/*
+ * Low-Level PCI Support for the SH7780
+ *
+ * Dustin McIntire (dustin@sensoria.com)
+ * Derived from arch/i386/kernel/pci-*.c which bore the message:
+ * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
+ * With cleanup by Paul van Gool <pvangool@mimotech.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include "pci-sh4.h"
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ *
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
+ */
+static int __init sh7780_pci_init(void)
+{
+ unsigned int id;
+ int ret;
+
+ pr_debug("PCI: Starting intialization.\n");
+
+ outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
+
+ /* check for SH7780/SH7780R hardware */
+ id = pci_read_reg(SH7780_PCIVID);
+ if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) &&
+ (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) {
+ printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+ return -ENODEV;
+ }
+
+ /* Setup the INTC */
+ ctrl_outl(0x00200000, INTC_ICR0); /* INTC SH-4 Mode */
+ ctrl_outl(0x00078000, INTC_INT2MSKCR); /* enable PCIINTA - PCIINTD */
+ ctrl_outl(0x40000000, INTC_INTMSK1); /* disable IRL4-7 Interrupt */
+ ctrl_outl(0x0000fffe, INTC_INTMSK2); /* disable IRL4-7 Interrupt */
+ ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */
+ ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */
+
+ if ((ret = sh4_pci_check_direct()) != 0)
+ return ret;
+
+ return pcibios_init_platform();
+}
+core_initcall(sh7780_pci_init);
+
+int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
+{
+ u32 word;
+
+ /*
+ * This code is unused for some boards as it is done in the
+ * bootloader and doing it here means the MAC addresses loaded
+ * by the bootloader get lost.
+ */
+ if (!(map->flags & SH4_PCIC_NO_RESET)) {
+ /* toggle PCI reset pin */
+ word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+ pci_write_reg(word, SH4_PCICR);
+ /* Wait for a long time... not 1 sec. but long enough */
+ mdelay(100);
+ word = SH4_PCICR_PREFIX;
+ pci_write_reg(word, SH4_PCICR);
+ }
+
+ /* set the command/status bits to:
+ * Wait Cycle Control + Parity Enable + Bus Master +
+ * Mem space enable
+ */
+ pci_write_reg(0x00000046, SH7780_PCICMD);
+
+ /* define this host as the host bridge */
+ word = PCI_BASE_CLASS_BRIDGE << 24;
+ pci_write_reg(word, SH7780_PCIRID);
+
+ /* Set IO and Mem windows to local address
+ * Make PCI and local address the same for easy 1 to 1 mapping
+ * Window0 = map->window0.size @ non-cached area base = SDRAM
+ * Window1 = map->window1.size @ cached area base = SDRAM
+ */
+ word = ((map->window0.size - 1) & 0x1ff00001) | 0x01;
+ pci_write_reg(0x07f00001, SH4_PCILSR0);
+ word = ((map->window1.size - 1) & 0x1ff00001) | 0x01;
+ pci_write_reg(0x00000001, SH4_PCILSR1);
+ /* Set the values on window 0 PCI config registers */
+ word = P2SEGADDR(map->window0.base);
+ pci_write_reg(0xa8000000, SH4_PCILAR0);
+ pci_write_reg(0x08000000, SH7780_PCIMBAR0);
+ /* Set the values on window 1 PCI config registers */
+ word = P2SEGADDR(map->window1.base);
+ pci_write_reg(0x00000000, SH4_PCILAR1);
+ pci_write_reg(0x00000000, SH7780_PCIMBAR1);
+
+ /* Map IO space into PCI IO window
+ * The IO window is 64K-PCIBIOS_MIN_IO in size
+ * IO addresses will be translated to the
+ * PCI IO window base address
+ */
+ pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+ PCIBIOS_MIN_IO, (64 << 10),
+ SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+
+ /* NOTE: I'm ignoring the PCI error IRQs for now..
+ * TODO: add support for the internal error interrupts and
+ * DMA interrupts...
+ */
+
+#ifdef CONFIG_SH_R7780RP
+ pci_fixup_pcic();
+#endif
+
+ /* SH7780 init done, set central function init complete */
+ /* use round robin mode to stop a device starving/overruning */
+ word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
+ pci_write_reg(word, SH4_PCICR);
+
+ return 1;
+}
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
new file mode 100644
index 00000000000..f02d2180a4b
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -0,0 +1,94 @@
+/*
+ * Low-Level PCI Support for SH7780 targets
+ *
+ * Dustin McIntire (dustin@sensoria.com) (c) 2001
+ * Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7780_H_
+#define _PCI_SH7780_H_
+
+/* Platform Specific Values */
+#define SH7780_VENDOR_ID 0x1912
+#define SH7780_DEVICE_ID 0x0002
+#define SH7781_DEVICE_ID 0x0001
+
+/* SH7780 Control Registers */
+#define SH7780_PCI_VCR0 0xFE000000
+#define SH7780_PCI_VCR1 0xFE000004
+#define SH7780_PCI_VCR2 0xFE000008
+
+/* SH7780 Specific Values */
+#define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
+#define SH7780_PCI_CONFIG_SIZE 0x01000000 /* Config space size */
+
+#define SH7780_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */
+#define SH7780_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */
+
+#define SH7780_PCI_IO_BASE 0xFE400000 /* IO space base address */
+#define SH7780_PCI_IO_SIZE 0x00400000 /* Size of IO window */
+
+#define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */
+#define PCI_REG(n) (SH7780_PCIREG_BASE+n)
+
+/* SH7780 PCI Config Registers */
+#define SH7780_PCIVID 0x000 /* Vendor ID */
+#define SH7780_PCIDID 0x002 /* Device ID */
+#define SH7780_PCICMD 0x004 /* Command */
+#define SH7780_PCISTATUS 0x006 /* Status */
+#define SH7780_PCIRID 0x008 /* Revision ID */
+#define SH7780_PCIPIF 0x009 /* Program Interface */
+#define SH7780_PCISUB 0x00a /* Sub class code */
+#define SH7780_PCIBCC 0x00b /* Base class code */
+#define SH7780_PCICLS 0x00c /* Cache line size */
+#define SH7780_PCILTM 0x00d /* latency timer */
+#define SH7780_PCIHDR 0x00e /* Header type */
+#define SH7780_PCIBIST 0x00f /* BIST */
+#define SH7780_PCIIBAR 0x010 /* IO Base address */
+#define SH7780_PCIMBAR0 0x014 /* Memory base address0 */
+#define SH7780_PCIMBAR1 0x018 /* Memory base address1 */
+#define SH7780_PCISVID 0x02c /* Sub system vendor ID */
+#define SH7780_PCISID 0x02e /* Sub system ID */
+#define SH7780_PCICP 0x034
+#define SH7780_PCIINTLINE 0x03c /* Interrupt line */
+#define SH7780_PCIINTPIN 0x03d /* Interrupt pin */
+#define SH7780_PCIMINGNT 0x03e /* Minumum grand */
+#define SH7780_PCIMAXLAT 0x03f /* Maxmum latency */
+#define SH7780_PCICID 0x040
+#define SH7780_PCINIP 0x041
+#define SH7780_PCIPMC 0x042
+#define SH7780_PCIPMCSR 0x044
+#define SH7780_PCIPMCSR_BSE 0x046
+#define SH7780_PCICDD 0x047
+
+#define SH7780_PCIMBR0 0x1E0
+#define SH7780_PCIMBMR0 0x1E4
+#define SH7780_PCIMBR2 0x1F0
+#define SH7780_PCIMBMR2 0x1F4
+#define SH7780_PCIIOBR 0x1F8
+#define SH7780_PCIIOBMR 0x1FC
+#define SH7780_PCICSCR0 0x210 /* Cache Snoop1 Cnt. Register */
+#define SH7780_PCICSCR1 0x214 /* Cache Snoop2 Cnt. Register */
+#define SH7780_PCICSAR0 0x218 /* Cache Snoop1 Addr. Register */
+#define SH7780_PCICSAR1 0x21C /* Cache Snoop2 Addr. Register */
+
+/* General Memory Config Addresses */
+#define SH7780_CS0_BASE_ADDR 0x0
+#define SH7780_MEM_REGION_SIZE 0x04000000
+#define SH7780_CS1_BASE_ADDR (SH7780_CS0_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS2_BASE_ADDR (SH7780_CS1_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS3_BASE_ADDR (SH7780_CS2_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS4_BASE_ADDR (SH7780_CS3_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS5_BASE_ADDR (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS6_BASE_ADDR (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+
+struct sh4_pci_address_map;
+
+/* arch/sh/drivers/pci/pci-sh7780.c */
+int sh7780_pcic_init(struct sh4_pci_address_map *map);
+
+#endif /* _PCI_SH7780_H_ */
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 7c81b8b65bb..4ab5ea6b35f 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -70,12 +70,6 @@
static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
unsigned long pciOffset, unsigned long regionSize);
-/*
- * The pcibios_map_platform_irq function is defined in the appropriate
- * board specific code and referenced here
- */
-extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
-
static __init void SetPCIPLL(void)
{
{
@@ -422,13 +416,6 @@ struct pci_ops st40pci_config_ops = {
/* Everything hangs off this */
static struct pci_bus *pci_root_bus;
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
- return PCI_SLOT(dev->devfn);
-}
-
-
static int __init pcibios_init(void)
{
extern unsigned long memory_start, memory_end;
@@ -465,17 +452,11 @@ static int __init pcibios_init(void)
/* ok, do the scan man */
pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
pci_assign_unassigned_resources();
- pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
return 0;
}
-
subsys_initcall(pcibios_init);
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
/*
* Publish a region of local address space over the PCI bus
* to other devices.
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 3d546ba329c..d439336d2e1 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -1,21 +1,45 @@
-/* arch/sh/kernel/pci.c
- * $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $
+/*
+ * arch/sh/drivers/pci/pci.c
*
* Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
- *
- *
+ * Copyright (c) 2004 - 2006 Paul Mundt <lethal@linux-sh.org>
+ *
* These functions are collected here to reduce duplication of common
* code amongst the many platform-specific PCI support code files.
- *
+ *
* These routines require the following board-specific routines:
* void pcibios_fixup_irqs();
*
* See include/asm-sh/pci.h for more information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*/
-
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <asm/io.h>
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+ return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 __init simple_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ u8 pin = *pinp;
+
+ while (dev->bus->parent) {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ }
+ *pinp = pin;
+
+ /* The slot is the slot of the last bridge. */
+ return PCI_SLOT(dev->devfn);
+}
static int __init pcibios_init(void)
{
@@ -26,26 +50,32 @@ static int __init pcibios_init(void)
#ifdef CONFIG_PCI_AUTO
/* assign resources */
busno = 0;
- for (p = board_pci_channels; p->pci_ops != NULL; p++) {
+ for (p = board_pci_channels; p->pci_ops != NULL; p++)
busno = pciauto_assign_resources(busno, p) + 1;
- }
#endif
/* scan the buses */
busno = 0;
- for (p= board_pci_channels; p->pci_ops != NULL; p++) {
+ for (p = board_pci_channels; p->pci_ops != NULL; p++) {
bus = pci_scan_bus(busno, p->pci_ops, p);
- busno = bus->subordinate+1;
+ busno = bus->subordinate + 1;
}
- /* board-specific fixups */
- pcibios_fixup_irqs();
+ pci_fixup_irqs(simple_swizzle, pcibios_map_platform_irq);
return 0;
}
-
subsys_initcall(pcibios_init);
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+ pci_read_bridge_bases(bus);
+}
+
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
@@ -61,13 +91,17 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
- /* Somebody might have asked allocation of a non-standard resource */
+ /*
+ * Somebody might have asked allocation of a non-standard
+ * resource
+ */
return;
}
-
+
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+ if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
+ PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
@@ -145,7 +179,8 @@ void pcibios_set_master(struct pci_dev *dev)
lat = pcibios_max_latency;
else
return;
- printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+ printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n",
+ pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
@@ -153,3 +188,39 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (unlikely(!len || !start))
+ return NULL;
+ if (maxlen && len > maxlen)
+ len = maxlen;
+
+ /*
+ * Presently the IORESOURCE_MEM case is a bit special, most
+ * SH7751 style PCI controllers have PCI memory at a fixed
+ * location in the address space where no remapping is desired
+ * (typically at 0xfd000000, but is_pci_memaddr() will know
+ * best). With the IORESOURCE_MEM case more care has to be taken
+ * to inhibit page table mapping for legacy cores, but this is
+ * punted off to __ioremap().
+ * -- PFM.
+ */
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM)
+ return ioremap(start, len);
+
+ return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index f05cd96f886..5da88a43d35 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -6,9 +6,10 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o setup.o time.o sys_sh.o semaphore.o \
- io.o io_generic.o sh_ksyms.o
+ io.o io_generic.o sh_ksyms.o syscalls.o
obj-y += cpu/ timers/
+obj-$(CONFIG_VSYSCALL) += vsyscall/
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
@@ -18,3 +19,5 @@ obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_APM) += apm.o
+obj-$(CONFIG_PM) += pm.o
diff --git a/arch/sh/kernel/apm.c b/arch/sh/kernel/apm.c
new file mode 100644
index 00000000000..871e7d64000
--- /dev/null
+++ b/arch/sh/kernel/apm.c
@@ -0,0 +1,539 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * based on ARM APM driver by
+ * Jamey Hicks <jamey@crl.dec.com>
+ *
+ * adapted from the APM BIOS driver for Linux by
+ * Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ * Intel Corporation, Microsoft Corporation. Advanced Power Management
+ * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/pm.h>
+#include <linux/pm_legacy.h>
+#include <asm/apm.h>
+
+#define MODNAME "apm"
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV 134
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS 16
+
+struct apm_queue {
+ unsigned int event_head;
+ unsigned int event_tail;
+ apm_event_t events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+ struct list_head list;
+
+ unsigned int suser: 1;
+ unsigned int writer: 1;
+ unsigned int reader: 1;
+
+ int suspend_result;
+ unsigned int suspend_state;
+#define SUSPEND_NONE 0 /* no suspend pending */
+#define SUSPEND_PENDING 1 /* suspend pending read */
+#define SUSPEND_READ 2 /* suspend read, pending ack */
+#define SUSPEND_ACKED 3 /* suspend acked */
+#define SUSPEND_DONE 4 /* suspend completed */
+
+ struct apm_queue queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info. kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+int apm_suspended;
+EXPORT_SYMBOL(apm_suspended);
+
+/* Platform-specific apm_read_proc(). */
+int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
+EXPORT_SYMBOL(apm_get_info);
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+ return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+ q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+ return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+ q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+ if (q->event_head == q->event_tail) {
+ static int notified;
+
+ if (notified++ == 0)
+ printk(KERN_ERR "apm: an event queue overflowed\n");
+
+ q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+ }
+ q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+ if (as->suser && as->writer) {
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ /*
+ * If this user already has a suspend pending,
+ * don't queue another one.
+ */
+ if (as->suspend_state != SUSPEND_NONE)
+ return;
+
+ as->suspend_state = SUSPEND_PENDING;
+ suspends_pending++;
+ break;
+ }
+ }
+ queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+ struct apm_user *as;
+
+ down_read(&user_list_lock);
+
+ list_for_each_entry(as, &apm_user_list, list)
+ if (as != sender && as->reader)
+ queue_event_one_user(as, event);
+
+ up_read(&user_list_lock);
+ wake_up_interruptible(&apm_waitqueue);
+}
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action. Only a subset of events are handled:
+ * %APM_LOW_BATTERY
+ * %APM_POWER_STATUS_CHANGE
+ * %APM_USER_SUSPEND
+ * %APM_SYS_SUSPEND
+ * %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+ spin_lock_irq(&kapmd_queue_lock);
+ queue_add_event(&kapmd_queue, event);
+ spin_unlock_irq(&kapmd_queue_lock);
+
+ wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
+
+static void apm_suspend(void)
+{
+ struct apm_user *as;
+ int err;
+
+ apm_suspended = 1;
+ err = pm_suspend(PM_SUSPEND_MEM);
+
+ /*
+ * Anyone on the APM queues will think we're still suspended.
+ * Send a message so everyone knows we're now awake again.
+ */
+ queue_event(APM_NORMAL_RESUME, NULL);
+
+ /*
+ * Finally, wake up anyone who is sleeping on the suspend.
+ */
+ down_read(&user_list_lock);
+ list_for_each_entry(as, &apm_user_list, list) {
+ as->suspend_result = err;
+ as->suspend_state = SUSPEND_DONE;
+ }
+ up_read(&user_list_lock);
+
+ wake_up(&apm_suspend_waitqueue);
+ apm_suspended = 0;
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct apm_user *as = fp->private_data;
+ apm_event_t event;
+ int i = count, ret = 0;
+
+ if (count < sizeof(apm_event_t))
+ return -EINVAL;
+
+ if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+ while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+ event = queue_get_event(&as->queue);
+
+ ret = -EFAULT;
+ if (copy_to_user(buf, &event, sizeof(event)))
+ break;
+
+ if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+ as->suspend_state = SUSPEND_READ;
+
+ buf += sizeof(event);
+ i -= sizeof(event);
+ }
+
+ if (i < count)
+ ret = count - i;
+
+ return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+ struct apm_user *as = fp->private_data;
+
+ poll_wait(fp, &apm_waitqueue, wait);
+ return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ * This IOCTL is overloaded, and performs two functions. It is used to:
+ * - initiate a suspend
+ * - acknowledge a suspend read from /dev/apm_bios.
+ * Only when everyone who has opened /dev/apm_bios with write permission
+ * has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+ struct apm_user *as = filp->private_data;
+ unsigned long flags;
+ int err = -EINVAL;
+
+ if (!as->suser || !as->writer)
+ return -EPERM;
+
+ switch (cmd) {
+ case APM_IOC_SUSPEND:
+ as->suspend_result = -EINTR;
+
+ if (as->suspend_state == SUSPEND_READ) {
+ /*
+ * If we read a suspend command from /dev/apm_bios,
+ * then the corresponding APM_IOC_SUSPEND ioctl is
+ * interpreted as an acknowledge.
+ */
+ as->suspend_state = SUSPEND_ACKED;
+ suspends_pending--;
+ } else {
+ /*
+ * Otherwise it is a request to suspend the system.
+ * Queue an event for all readers, and expect an
+ * acknowledge from all writers who haven't already
+ * acknowledged.
+ */
+ queue_event(APM_USER_SUSPEND, as);
+ }
+
+ /*
+ * If there are no further acknowledges required, suspend
+ * the system.
+ */
+ if (suspends_pending == 0)
+ apm_suspend();
+
+ /*
+ * Wait for the suspend/resume to complete. If there are
+ * pending acknowledges, we wait here for them.
+ *
+ * Note that we need to ensure that the PM subsystem does
+ * not kick us out of the wait when it suspends the threads.
+ */
+ flags = current->flags;
+ current->flags |= PF_NOFREEZE;
+
+ /*
+ * Note: do not allow a thread which is acking the suspend
+ * to escape until the resume is complete.
+ */
+ if (as->suspend_state == SUSPEND_ACKED)
+ wait_event(apm_suspend_waitqueue,
+ as->suspend_state == SUSPEND_DONE);
+ else
+ wait_event_interruptible(apm_suspend_waitqueue,
+ as->suspend_state == SUSPEND_DONE);
+
+ current->flags = flags;
+ err = as->suspend_result;
+ as->suspend_state = SUSPEND_NONE;
+ break;
+ }
+
+ return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+ struct apm_user *as = filp->private_data;
+ filp->private_data = NULL;
+
+ down_write(&user_list_lock);
+ list_del(&as->list);
+ up_write(&user_list_lock);
+
+ /*
+ * We are now unhooked from the chain. As far as new
+ * events are concerned, we no longer exist. However, we
+ * need to balance suspends_pending, which means the
+ * possibility of sleeping.
+ */
+ if (as->suspend_state != SUSPEND_NONE) {
+ suspends_pending -= 1;
+ if (suspends_pending == 0)
+ apm_suspend();
+ }
+
+ kfree(as);
+ return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+ struct apm_user *as;
+
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
+ if (as) {
+ /*
+ * XXX - this is a tiny bit broken, when we consider BSD
+ * process accounting. If the device is opened by root, we
+ * instantly flag that we used superuser privs. Who knows,
+ * we might close the device immediately without doing a
+ * privileged operation -- cevans
+ */
+ as->suser = capable(CAP_SYS_ADMIN);
+ as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+ as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+ down_write(&user_list_lock);
+ list_add(&as->list, &apm_user_list);
+ up_write(&user_list_lock);
+
+ filp->private_data = as;
+ }
+
+ return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+ .owner = THIS_MODULE,
+ .read = apm_read,
+ .poll = apm_poll,
+ .ioctl = apm_ioctl,
+ .open = apm_open,
+ .release = apm_release,
+};
+
+static struct miscdevice apm_device = {
+ .minor = APM_MINOR_DEV,
+ .name = "apm_bios",
+ .fops = &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ * 0) Linux driver version (this will change if format changes)
+ * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
+ * 2) APM flags from APM Installation Check (0x00):
+ * bit 0: APM_16_BIT_SUPPORT
+ * bit 1: APM_32_BIT_SUPPORT
+ * bit 2: APM_IDLE_SLOWS_CLOCK
+ * bit 3: APM_BIOS_DISABLED
+ * bit 4: APM_BIOS_DISENGAGED
+ * 3) AC line status
+ * 0x00: Off-line
+ * 0x01: On-line
+ * 0x02: On backup power (BIOS >= 1.1 only)
+ * 0xff: Unknown
+ * 4) Battery status
+ * 0x00: High
+ * 0x01: Low
+ * 0x02: Critical
+ * 0x03: Charging
+ * 0x04: Selected battery not present (BIOS >= 1.2 only)
+ * 0xff: Unknown
+ * 5) Battery flag
+ * bit 0: High
+ * bit 1: Low
+ * bit 2: Critical
+ * bit 3: Charging
+ * bit 7: No system battery
+ * 0xff: Unknown
+ * 6) Remaining battery life (percentage of charge):
+ * 0-100: valid
+ * -1: Unknown
+ * 7) Remaining battery life (time units):
+ * Number of remaining minutes or seconds
+ * -1: Unknown
+ * 8) min = minutes; sec = seconds
+ */
+static int apm_read_proc(char *buf, char **start, off_t fpos, int length)
+{
+ if (likely(apm_get_info))
+ return apm_get_info(buf, start, fpos, length);
+
+ return -EINVAL;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+ daemonize("kapmd");
+ current->flags |= PF_NOFREEZE;
+
+ do {
+ apm_event_t event;
+
+ wait_event_interruptible(kapmd_wait,
+ !queue_empty(&kapmd_queue) || !pm_active);
+
+ if (!pm_active)
+ break;
+
+ spin_lock_irq(&kapmd_queue_lock);
+ event = 0;
+ if (!queue_empty(&kapmd_queue))
+ event = queue_get_event(&kapmd_queue);
+ spin_unlock_irq(&kapmd_queue_lock);
+
+ switch (event) {
+ case 0:
+ break;
+
+ case APM_LOW_BATTERY:
+ case APM_POWER_STATUS_CHANGE:
+ queue_event(event, NULL);
+ break;
+
+ case APM_USER_SUSPEND:
+ case APM_SYS_SUSPEND:
+ queue_event(event, NULL);
+ if (suspends_pending == 0)
+ apm_suspend();
+ break;
+
+ case APM_CRITICAL_SUSPEND:
+ apm_suspend();
+ break;
+ }
+ } while (1);
+
+ complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+ int ret;
+
+ pm_active = 1;
+
+ ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+ if (unlikely(ret < 0)) {
+ pm_active = 0;
+ return ret;
+ }
+
+ create_proc_info_entry("apm", 0, NULL, apm_read_proc);
+
+ ret = misc_register(&apm_device);
+ if (unlikely(ret != 0)) {
+ remove_proc_entry("apm", NULL);
+
+ pm_active = 0;
+ wake_up(&kapmd_wait);
+ wait_for_completion(&kapmd_exit);
+ }
+
+ return ret;
+}
+
+static void __exit apm_exit(void)
+{
+ misc_deregister(&apm_device);
+ remove_proc_entry("apm", NULL);
+
+ pm_active = 0;
+ wake_up(&kapmd_wait);
+ wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell, Andriy Skulysh");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index f1f9ab87f0b..3e5fa1e24df 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -10,7 +10,8 @@
*/
#include <linux/init.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -32,8 +33,6 @@
/* SH4 can't access PCMCIA interface through P2 area.
* we must remap it with appropreate attribute bit of the page set.
* this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
#if defined(CONFIG_CF_AREA6)
#define slot_no 0
@@ -41,9 +40,6 @@
#define slot_no 1
#endif
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
/* use this pointer to access to directly connected compact flash io area*/
void *cf_io_base;
@@ -62,7 +58,7 @@ static int __init allocate_cf_area(void)
return -ENOMEM;
}
/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n",
- paddrbase, psize, prot.pgprot, cf_io_base);*/
+ paddrbase, psize, prot.pgprot, cf_io_base);*/
/* XXX : do we need attribute and common-memory area also? */
@@ -87,7 +83,7 @@ static int __init cf_init_default(void)
}
#if defined(CONFIG_SH_SOLUTION_ENGINE)
-#include <asm/se/se.h>
+#include <asm/se.h>
/*
* SolutionEngine
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 59d5b748752..fb5dac06938 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -8,6 +8,5 @@ obj-$(CONFIG_CPU_SH2) += sh2/
obj-$(CONFIG_CPU_SH3) += sh3/
obj-$(CONFIG_CPU_SH4) += sh4/
-obj-$(CONFIG_SH_RTC) += rtc.o
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 97fa37f42b8..51ec64cdf34 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -1,7 +1,7 @@
/*
* arch/sh/kernel/cpu/clock.c - SuperH clock framework
*
- * Copyright (C) 2005 Paul Mundt
+ * Copyright (C) 2005, 2006 Paul Mundt
*
* This clock framework is derived from the OMAP version by:
*
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/seq_file.h>
@@ -24,7 +25,7 @@
static LIST_HEAD(clock_list);
static DEFINE_SPINLOCK(clock_lock);
-static DECLARE_MUTEX(clock_list_sem);
+static DEFINE_MUTEX(clock_list_sem);
/*
* Each subtype is expected to define the init routines for these clocks,
@@ -140,21 +141,21 @@ void clk_disable(struct clk *clk)
int clk_register(struct clk *clk)
{
- down(&clock_list_sem);
+ mutex_lock(&clock_list_sem);
list_add(&clk->node, &clock_list);
kref_init(&clk->kref);
- up(&clock_list_sem);
+ mutex_unlock(&clock_list_sem);
return 0;
}
void clk_unregister(struct clk *clk)
{
- down(&clock_list_sem);
+ mutex_lock(&clock_list_sem);
list_del(&clk->node);
- up(&clock_list_sem);
+ mutex_unlock(&clock_list_sem);
}
inline unsigned long clk_get_rate(struct clk *clk)
@@ -198,14 +199,14 @@ struct clk *clk_get(const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clock_list_sem);
+ mutex_lock(&clock_list_sem);
list_for_each_entry(p, &clock_list, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clock_list_sem);
+ mutex_unlock(&clock_list_sem);
return clk;
}
@@ -225,7 +226,7 @@ int __init clk_init(void)
{
int i, ret = 0;
- BUG_ON(unlikely(!master_clk.rate));
+ BUG_ON(!master_clk.rate);
for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
struct clk *clk = onchip_clocks[i];
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 868e68b2888..bfb90eb0b7a 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -4,6 +4,7 @@
* CPU init code
*
* Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -13,6 +14,7 @@
#include <linux/kernel.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/page.h>
#include <asm/system.h>
#include <asm/cacheflush.h>
#include <asm/cache.h>
@@ -51,7 +53,15 @@ static void __init cache_init(void)
ccr = ctrl_inl(CCR);
/*
- * If the cache is already enabled .. flush it.
+ * At this point we don't know whether the cache is enabled or not - a
+ * bootloader may have enabled it. There are at least 2 things that
+ * could be dirty in the cache at this point:
+ * 1. kernel command line set up by boot loader
+ * 2. spilled registers from the prolog of this function
+ * => before re-initialising the cache, we must do a purge of the whole
+ * cache out to memory for safety. As long as nothing is spilled
+ * during the loop to lines that have already been done, this is safe.
+ * - RPC
*/
if (ccr & CCR_CACHE_ENABLE) {
unsigned long ways, waysize, addrstart;
@@ -98,6 +108,8 @@ static void __init cache_init(void)
/* Force EMODE if possible */
if (cpu_data->dcache.ways > 1)
flags |= CCR_CACHE_EMODE;
+ else
+ flags &= ~CCR_CACHE_EMODE;
#endif
#ifdef CONFIG_SH_WRITETHROUGH
@@ -112,6 +124,9 @@ static void __init cache_init(void)
/* Turn on OCRAM -- halve the OC */
flags |= CCR_CACHE_ORA;
cpu_data->dcache.sets >>= 1;
+
+ cpu_data->dcache.way_size = cpu_data->dcache.sets *
+ cpu_data->dcache.linesz;
#endif
ctrl_outl(flags, CCR);
@@ -184,6 +199,10 @@ asmlinkage void __init sh_cpu_init(void)
/* Init the cache */
cache_init();
+ shm_align_mask = max_t(unsigned long,
+ cpu_data->dcache.way_size - 1,
+ PAGE_SIZE - 1);
+
/* Disable the FPU */
if (fpu_disabled) {
printk("FPU Disabled\n");
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index e3cccea15e1..1c034c283f5 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -3,5 +3,6 @@
#
obj-y += ipr.o imask.o
-obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
-obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
+obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
+obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
+obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index 30064bf6e15..e30e4b7aa70 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -241,9 +241,9 @@ static struct intc2_init {
/* 110-111 reserved/unused */
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
{ TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
-#ifdef CONFIG_SH_RTC
- { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-#endif
+ { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+ { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+ { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
{ SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 0f545941fb4..f785822cd5d 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -57,31 +57,27 @@ static struct hw_interrupt_type ipr_irq_type = {
static void disable_ipr_irq(unsigned int irq)
{
- unsigned long val, flags;
+ unsigned long val;
unsigned int addr = ipr_data[irq].addr;
unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
/* Set the priority in IPR to 0 */
- local_irq_save(flags);
val = ctrl_inw(addr);
val &= mask;
ctrl_outw(val, addr);
- local_irq_restore(flags);
}
static void enable_ipr_irq(unsigned int irq)
{
- unsigned long val, flags;
+ unsigned long val;
unsigned int addr = ipr_data[irq].addr;
int priority = ipr_data[irq].priority;
unsigned short value = (priority << ipr_data[irq].shift);
/* Set priority in IPR back to original value */
- local_irq_save(flags);
val = ctrl_inw(addr);
val |= value;
ctrl_outw(val, addr);
- local_irq_restore(flags);
}
static void mask_and_ack_ipr(unsigned int irq)
@@ -89,6 +85,7 @@ static void mask_and_ack_ipr(unsigned int irq)
disable_ipr_irq(irq);
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
/* This is needed when we use edge triggered setting */
/* XXX: Is it really needed? */
@@ -123,7 +120,7 @@ void __init init_IRQ(void)
#ifndef CONFIG_CPU_SUBTYPE_SH7780
make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
-#if defined(CONFIG_SH_RTC)
+#ifdef RTC_IRQ
make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
#endif
@@ -162,6 +159,7 @@ void __init init_IRQ(void)
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
/*
* Initialize the Interrupt Controller (INTC)
@@ -192,6 +190,8 @@ void __init init_IRQ(void)
/* Perform the machine specific initialisation */
if (sh_mv.mv_init_irq != NULL)
sh_mv.mv_init_irq();
+
+ irq_ctx_init(smp_processor_id());
}
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c
index 4b2abe5eb16..492db31b3ca 100644
--- a/arch/sh/boards/adx/irq_maskreg.c
+++ b/arch/sh/kernel/cpu/irq/maskreg.c
@@ -1,30 +1,23 @@
/*
- * linux/arch/sh/kernel/irq_maskreg.c
+ * Interrupt handling for Simple external interrupt mask register
*
* Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
*
- * This file may be copied or modified under the terms of the GNU
- * General Public License. See linux/COPYING for more information.
- *
- * Interrupt handling for Simple external interrupt mask register
- *
* This is for the machine which have single 16 bit register
* for masking external IRQ individually.
- * Each bit of the register is for masking each interrupt.
+ * Each bit of the register is for masking each interrupt.
+ *
+ * This file may be copied or modified under the terms of the GNU
+ * General Public License. See linux/COPYING for more information.
*/
-
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
-
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/machvec.h>
-/* address of external interrupt mask register
- * address must be set prior to use these (maybe in init_XXX_irq())
- * XXX : is it better to use .config than specifying it in code? */
-unsigned short *irq_mask_register = 0;
+/* address of external interrupt mask register */
+unsigned long irq_mask_register;
/* forward declaration */
static unsigned int startup_maskreg_irq(unsigned int irq);
@@ -36,7 +29,7 @@ static void end_maskreg_irq(unsigned int irq);
/* hw_interrupt_type */
static struct hw_interrupt_type maskreg_irq_type = {
- .typename = " Mask Register",
+ .typename = "Mask Register",
.startup = startup_maskreg_irq,
.shutdown = shutdown_maskreg_irq,
.enable = enable_maskreg_irq,
@@ -47,7 +40,7 @@ static struct hw_interrupt_type maskreg_irq_type = {
/* actual implementatin */
static unsigned int startup_maskreg_irq(unsigned int irq)
-{
+{
enable_maskreg_irq(irq);
return 0; /* never anything pending */
}
@@ -59,32 +52,26 @@ static void shutdown_maskreg_irq(unsigned int irq)
static void disable_maskreg_irq(unsigned int irq)
{
- if (irq_mask_register) {
- unsigned long flags;
- unsigned short val, mask = 0x01 << irq;
+ unsigned short val, mask = 0x01 << irq;
+
+ BUG_ON(!irq_mask_register);
- /* Set "irq"th bit */
- local_irq_save(flags);
- val = ctrl_inw((unsigned long)irq_mask_register);
- val |= mask;
- ctrl_outw(val, (unsigned long)irq_mask_register);
- local_irq_restore(flags);
- }
+ /* Set "irq"th bit */
+ val = ctrl_inw(irq_mask_register);
+ val |= mask;
+ ctrl_outw(val, irq_mask_register);
}
static void enable_maskreg_irq(unsigned int irq)
{
- if (irq_mask_register) {
- unsigned long flags;
- unsigned short val, mask = ~(0x01 << irq);
+ unsigned short val, mask = ~(0x01 << irq);
+
+ BUG_ON(!irq_mask_register);
- /* Clear "irq"th bit */
- local_irq_save(flags);
- val = ctrl_inw((unsigned long)irq_mask_register);
- val &= mask;
- ctrl_outw(val, (unsigned long)irq_mask_register);
- local_irq_restore(flags);
- }
+ /* Clear "irq"th bit */
+ val = ctrl_inw(irq_mask_register);
+ val &= mask;
+ ctrl_outw(val, irq_mask_register);
}
static void mask_and_ack_maskreg(unsigned int irq)
@@ -101,6 +88,6 @@ static void end_maskreg_irq(unsigned int irq)
void make_maskreg_irq(unsigned int irq)
{
disable_irq_nosync(irq);
- irq_desc[irq].chip = &maskreg_irq_type;
+ irq_desc[irq].handler = &maskreg_irq_type;
disable_maskreg_irq(irq);
}
diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c
index 80cd8108d36..17f47b373d6 100644
--- a/arch/sh/kernel/cpu/irq/pint.c
+++ b/arch/sh/kernel/cpu/irq/pint.c
@@ -48,26 +48,22 @@ static struct hw_interrupt_type pint_irq_type = {
static void disable_pint_irq(unsigned int irq)
{
- unsigned long val, flags;
+ unsigned long val;
- local_irq_save(flags);
val = ctrl_inw(INTC_INTER);
val &= ~(1 << (irq - PINT_IRQ_BASE));
ctrl_outw(val, INTC_INTER); /* disable PINTn */
portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
- local_irq_restore(flags);
}
static void enable_pint_irq(unsigned int irq)
{
- unsigned long val, flags;
+ unsigned long val;
- local_irq_save(flags);
val = ctrl_inw(INTC_INTER);
val |= 1 << (irq - PINT_IRQ_BASE);
ctrl_outw(val, INTC_INTER); /* enable PINTn */
portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
- local_irq_restore(flags);
}
static void mask_and_ack_pint(unsigned int irq)
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
deleted file mode 100644
index 4304cf75cfa..00000000000
--- a/arch/sh/kernel/cpu/rtc.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/io.h>
-#include <asm/rtc.h>
-
-void sh_rtc_gettimeofday(struct timespec *ts)
-{
- unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
- unsigned long flags;
-
- again:
- do {
- local_irq_save(flags);
- ctrl_outb(0, RCR1); /* Clear CF-bit */
- sec128 = ctrl_inb(R64CNT);
- sec = ctrl_inb(RSECCNT);
- min = ctrl_inb(RMINCNT);
- hr = ctrl_inb(RHRCNT);
- wk = ctrl_inb(RWKCNT);
- day = ctrl_inb(RDAYCNT);
- mon = ctrl_inb(RMONCNT);
-#if defined(CONFIG_CPU_SH4)
- yr = ctrl_inw(RYRCNT);
- yr100 = (yr >> 8);
- yr &= 0xff;
-#else
- yr = ctrl_inb(RYRCNT);
- yr100 = (yr == 0x99) ? 0x19 : 0x20;
-#endif
- sec2 = ctrl_inb(R64CNT);
- cf_bit = ctrl_inb(RCR1) & RCR1_CF;
- local_irq_restore(flags);
- } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
-
- BCD_TO_BIN(yr100);
- BCD_TO_BIN(yr);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hr);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
-
- if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
- hr > 23 || min > 59 || sec > 59) {
- printk(KERN_ERR
- "SH RTC: invalid value, resetting to 1 Jan 2000\n");
- local_irq_save(flags);
- ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */
- ctrl_outb(0, RSECCNT);
- ctrl_outb(0, RMINCNT);
- ctrl_outb(0, RHRCNT);
- ctrl_outb(6, RWKCNT);
- ctrl_outb(1, RDAYCNT);
- ctrl_outb(1, RMONCNT);
-#if defined(CONFIG_CPU_SH4)
- ctrl_outw(0x2000, RYRCNT);
-#else
- ctrl_outb(0, RYRCNT);
-#endif
- ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */
- goto again;
- }
-
-#if RTC_BIT_INVERTED != 0
- if ((sec128 & RTC_BIT_INVERTED))
- sec--;
-#endif
-
- ts->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
- ts->tv_nsec = ((sec128 * 1000000) / 128) * 1000;
-}
-
-/*
- * Changed to only care about tv_sec, and not the full timespec struct
- * (i.e. tv_nsec). It can easily be switched to timespec for future cpus
- * that support setting usec or nsec RTC values.
- */
-int sh_rtc_settimeofday(const time_t secs)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned long flags;
-
- local_irq_save(flags);
- ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */
-
- cmos_minutes = ctrl_inb(RMINCNT);
- BCD_TO_BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = secs % 60;
- real_minutes = secs / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
- ctrl_outb(real_seconds, RSECCNT);
- ctrl_outb(real_minutes, RMINCNT);
- } else {
- printk(KERN_WARNING
- "set_rtc_time: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
- retval = -1;
- }
-
- ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */
- local_irq_restore(flags);
-
- return retval;
-}
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index b54dbb9a0c8..58d3815695f 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -4,10 +4,21 @@
obj-y := ex.o probe.o
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707) += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708) += setup-sh7708.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7300) += setup-sh7300.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710) += setup-sh7710.o
+
+# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SH3) := clock-sh3.o
clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o
clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7706) := clock-sh7706.o
clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7710) := clock-sh7300.o
obj-y += $(clock-y)
-
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
new file mode 100644
index 00000000000..0cf96f9833b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
@@ -0,0 +1,84 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7706.c
+ *
+ * SH7706 support for the clock framework
+ *
+ * Copyright (C) 2006 Takashi YOSHII
+ *
+ * Based on arch/sh/kernel/cpu/sh3/clock-sh7709.c
+ * Copyright (C) 2005 Andriy Skulysh
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int stc_multipliers[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
+static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate *= pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
+
+ clk->rate = clk->parent->rate / stc_multipliers[idx];
+}
+
+static struct clk_ops sh7706_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
+
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7706_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7706_clk_ops[] = {
+ &sh7706_master_clk_ops,
+ &sh7706_module_clk_ops,
+ &sh7706_bus_clk_ops,
+ &sh7706_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7706_clk_ops))
+ *ops = sh7706_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index cc04e9e239f..44daf44833f 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -84,8 +84,12 @@ ENTRY(interrupt_table)
.long do_IRQ ! rovi
.long do_IRQ
.long do_IRQ /* 5E0 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
- defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7710)
.long do_IRQ ! 32 IRQ irq0 /* 600 */
.long do_IRQ ! 33 irq1
.long do_IRQ ! 34 irq2
@@ -147,6 +151,51 @@ ENTRY(interrupt_table)
.long do_IRQ ! 62 PCC pcc0i
.long do_IRQ ! 63 pcc1i /* 9E0 */
#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+ .long exception_none ! 61 /* 9A0 */
+ .long exception_none ! 62
+ .long exception_none ! 63
+ .long exception_none ! 64 /* A00 */
+ .long exception_none ! 65
+ .long exception_none ! 66
+ .long exception_none ! 67
+ .long exception_none ! 68
+ .long exception_none ! 69
+ .long exception_none ! 70
+ .long exception_none ! 71
+ .long exception_none ! 72 /* B00 */
+ .long exception_none ! 73
+ .long exception_none ! 74
+ .long exception_none ! 75
+ .long do_IRQ ! 76 DMAC2 dei4 /* B80 */
+ .long do_IRQ ! 77 DMAC2 dei5
+ .long exception_none ! 78
+ .long do_IRQ ! 79 IPSEC ipseci /* BE0 */
+ .long do_IRQ ! 80 EDMAC eint0 /* C00 */
+ .long do_IRQ ! 81 EDMAC eint1
+ .long do_IRQ ! 82 EDMAC eint2
+ .long exception_none ! 83 /* C60 */
+ .long exception_none ! 84
+ .long exception_none ! 85
+ .long exception_none ! 86
+ .long exception_none ! 87
+ .long exception_none ! 88 /* D00 */
+ .long exception_none ! 89
+ .long exception_none ! 90
+ .long exception_none ! 91
+ .long exception_none ! 92
+ .long exception_none ! 93
+ .long exception_none ! 94
+ .long exception_none ! 95
+ .long do_IRQ ! 96 SIOF eri0 /* E00 */
+ .long do_IRQ ! 97 txi0
+ .long do_IRQ ! 98 rxi0
+ .long do_IRQ ! 99 cci0
+ .long do_IRQ ! 100 eri1 /* E80 */
+ .long do_IRQ ! 101 txi1
+ .long do_IRQ ! 102 rxi2
+ .long do_IRQ ! 103 cci3
+#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
.long do_IRQ ! 64
.long do_IRQ ! 65
@@ -195,4 +244,3 @@ ENTRY(interrupt_table)
.long do_IRQ ! 108
#endif
#endif
-
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
index 5cdc8863860..e6709883629 100644
--- a/arch/sh/kernel/cpu/sh3/probe.c
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -72,6 +72,12 @@ int __init detect_cpu_and_cache_system(void)
cpu_data->dcache.sets = 256;
cpu_data->type = CPU_SH7729;
+#if defined(CONFIG_CPU_SUBTYPE_SH7706)
+ cpu_data->type = CPU_SH7706;
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+ cpu_data->type = CPU_SH7710;
+#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7705)
cpu_data->type = CPU_SH7705;
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7300.c b/arch/sh/kernel/cpu/sh3/setup-sh7300.c
new file mode 100644
index 00000000000..ab4d204bfba
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7300.c
@@ -0,0 +1,43 @@
+/*
+ * SH7300 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xa4430000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCI,
+ .irqs = { 80, 80, 80, 80 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7300_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7300_devices_setup(void)
+{
+ return platform_add_devices(sh7300_devices,
+ ARRAY_SIZE(sh7300_devices));
+}
+__initcall(sh7300_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
new file mode 100644
index 00000000000..a8e41c5241f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -0,0 +1,48 @@
+/*
+ * SH7705 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xa4400000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 52, 53, 55, 54 },
+ }, {
+ .mapbase = 0xa4410000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 56, 57, 59, 58 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7705_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7705_devices_setup(void)
+{
+ return platform_add_devices(sh7705_devices,
+ ARRAY_SIZE(sh7705_devices));
+}
+__initcall(sh7705_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7708.c b/arch/sh/kernel/cpu/sh3/setup-sh7708.c
new file mode 100644
index 00000000000..f933723911c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7708.c
@@ -0,0 +1,43 @@
+/*
+ * SH7708 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xfffffe80,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCI,
+ .irqs = { 23, 24, 25, 0 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7708_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7708_devices_setup(void)
+{
+ return platform_add_devices(sh7708_devices,
+ ARRAY_SIZE(sh7708_devices));
+}
+__initcall(sh7708_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
new file mode 100644
index 00000000000..ff43ef2a1f0
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -0,0 +1,53 @@
+/*
+ * SH7707/SH7709 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xfffffe80,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCI,
+ .irqs = { 23, 24, 25, 0 },
+ }, {
+ .mapbase = 0xa4000150,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 56, 57, 59, 58 },
+ }, {
+ .mapbase = 0xa4000140,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_IRDA,
+ .irqs = { 52, 53, 55, 54 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7709_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7709_devices_setup(void)
+{
+ return platform_add_devices(sh7709_devices,
+ ARRAY_SIZE(sh7709_devices));
+}
+__initcall(sh7709_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
new file mode 100644
index 00000000000..895f99ee6a9
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -0,0 +1,43 @@
+/*
+ * SH7710 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xa4400000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 52, 53, 55, 54 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7710_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7710_devices_setup(void)
+{
+ return platform_add_devices(sh7710_devices,
+ ARRAY_SIZE(sh7710_devices));
+}
+__initcall(sh7710_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 3d5cafc71ae..8dbf3895ece 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -7,6 +7,16 @@ obj-y := ex.o probe.o
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
+
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SH4) := clock-sh4.o
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
index 26a27df0650..7146893a6cc 100644
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ b/arch/sh/kernel/cpu/sh4/ex.S
@@ -72,6 +72,7 @@ ENTRY(interrupt_table)
.long do_IRQ ! 1110
.long exception_error
! Internal hardware
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
.long do_IRQ ! TMU0 tuni0 /* 400 */
.long do_IRQ ! TMU1 tuni1
.long do_IRQ ! TMU2 tuni2
@@ -122,6 +123,13 @@ ENTRY(interrupt_table)
.long do_IRQ ! 45 dmte5
.long do_IRQ ! 46 dmte6
.long do_IRQ ! 47 dmte7 /* 7E0 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+ .long do_IRQ ! 44 IIC1 ali /* 780 */
+ .long do_IRQ ! 45 tacki
+ .long do_IRQ ! 46 waiti
+ .long do_IRQ ! 47 dtei /* 7E0 */
+ .long do_IRQ ! 48 DMAC dei0 /* 800 */
+ .long do_IRQ ! 49 dei1 /* 820 */
#else
.long exception_error ! 44 /* 780 */
.long exception_error ! 45
@@ -131,7 +139,8 @@ ENTRY(interrupt_table)
#if defined(CONFIG_SH_FPU)
.long do_fpu_state_restore ! 48 /* 800 */
.long do_fpu_state_restore ! 49 /* 820 */
-#else
+#elif !defined(CONFIG_CPU_SUBTYPE_SH7343) && \
+ !defined(CONFIG_CPU_SUBTYPE_SH73180)
.long exception_error
.long exception_error
#endif
@@ -224,7 +233,7 @@ ENTRY(interrupt_table)
.long exception_error
.long do_IRQ ! ADC adi
.long do_IRQ ! CMT cmti /* FA0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
+#elif defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7343)
.long do_IRQ ! 50 0x840
.long do_IRQ ! 51 0x860
.long do_IRQ ! 52 0x880
@@ -379,5 +388,168 @@ ENTRY(interrupt_table)
.long exception_error ! 141 0x13a0
.long exception_error ! 142 0x13c0
.long exception_error ! 143 0x13e0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+ .long do_IRQ ! 50 0x840
+ .long do_IRQ ! 51 0x860
+ .long do_IRQ ! 52 0x880
+ .long do_IRQ ! 53 0x8a0
+ .long do_IRQ ! 54 0x8c0
+ .long do_IRQ ! 55 0x8e0
+ .long do_IRQ ! 56 0x900
+ .long do_IRQ ! 57 0x920
+ .long do_IRQ ! 58 0x940
+ .long do_IRQ ! 59 0x960
+ .long do_IRQ ! 60 0x980
+ .long do_IRQ ! 61 0x9a0
+ .long do_IRQ ! 62 0x9c0
+ .long do_IRQ ! 63 0x9e0
+ .long do_IRQ ! 64 0xa00
+ .long do_IRQ ! 65 0xa20
+ .long do_IRQ ! 66 0xa4d
+ .long do_IRQ ! 67 0xa60
+ .long do_IRQ ! 68 0xa80
+ .long do_IRQ ! 69 0xaa0
+ .long do_IRQ ! 70 0xac0
+ .long do_IRQ ! 71 0xae0
+ .long do_IRQ ! 72 0xb00
+ .long do_IRQ ! 73 0xb20
+ .long do_IRQ ! 74 0xb40
+ .long do_IRQ ! 75 0xb60
+ .long do_IRQ ! 76 0xb80
+ .long do_IRQ ! 77 0xba0
+ .long do_IRQ ! 78 0xbc0
+ .long do_IRQ ! 79 0xbe0
+ .long do_IRQ ! 80 0xc00
+ .long do_IRQ ! 81 0xc20
+ .long do_IRQ ! 82 0xc40
+ .long do_IRQ ! 83 0xc60
+ .long do_IRQ ! 84 0xc80
+ .long do_IRQ ! 85 0xca0
+ .long do_IRQ ! 86 0xcc0
+ .long do_IRQ ! 87 0xce0
+ .long do_IRQ ! 88 0xd00
+ .long do_IRQ ! 89 0xd20
+ .long do_IRQ ! 90 0xd40
+ .long do_IRQ ! 91 0xd60
+ .long do_IRQ ! 92 0xd80
+ .long do_IRQ ! 93 0xda0
+ .long do_IRQ ! 94 0xdc0
+ .long do_IRQ ! 95 0xde0
+ .long do_IRQ ! 96 0xe00
+ .long do_IRQ ! 97 0xe20
+ .long do_IRQ ! 98 0xe40
+ .long do_IRQ ! 99 0xe60
+ .long do_IRQ ! 100 0xe80
+ .long do_IRQ ! 101 0xea0
+ .long do_IRQ ! 102 0xec0
+ .long do_IRQ ! 103 0xee0
+ .long do_IRQ ! 104 0xf00
+ .long do_IRQ ! 105 0xf20
+ .long do_IRQ ! 106 0xf40
+ .long do_IRQ ! 107 0xf60
+ .long do_IRQ ! 108 0xf80
+#endif
+#else
+ .long exception_error /* 400 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! RTC ati
+ .long do_IRQ ! pri
+ .long do_IRQ ! cui
+ .long exception_error
+ .long exception_error /* 500 */
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! WDT iti /* 560 */
+ .long do_IRQ ! TMU-ch0
+ .long do_IRQ ! TMU-ch1
+ .long do_IRQ ! TMU-ch2
+ .long do_IRQ ! ticpi2 /* 5E0 */
+ .long do_IRQ ! 32 Hitachi UDI /* 600 */
+ .long exception_error
+ .long do_IRQ ! 34 DMAC dmte0
+ .long do_IRQ ! 35 dmte1
+ .long do_IRQ ! 36 dmte2
+ .long do_IRQ ! 37 dmte3
+ .long do_IRQ ! 38 dmae
+ .long exception_error ! 39 /* 6E0 */
+ .long do_IRQ ! 40 SCIF-ch0 eri /* 700 */
+ .long do_IRQ ! 41 rxi
+ .long do_IRQ ! 42 bri
+ .long do_IRQ ! 43 txi
+ .long do_IRQ ! 44 DMAC dmte4 /* 780 */
+ .long do_IRQ ! 45 dmte5
+ .long do_IRQ ! 46 dmte6
+ .long do_IRQ ! 47 dmte7 /* 7E0 */
+#if defined(CONFIG_SH_FPU)
+ .long do_fpu_state_restore ! 48 /* 800 */
+ .long do_fpu_state_restore ! 49 /* 820 */
+#else
+ .long exception_error
+ .long exception_error
+#endif
+ .long exception_error /* 840 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! 56 CMT /* 900 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! 60 HAC
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! PCI serr /* A00 */
+ .long do_IRQ ! INTA
+ .long do_IRQ ! INTB
+ .long do_IRQ ! INTC
+ .long do_IRQ ! INTD
+ .long do_IRQ ! err
+ .long do_IRQ ! pwd3
+ .long do_IRQ ! pwd2
+ .long do_IRQ ! pwd1 /* B00 */
+ .long do_IRQ ! pwd0
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! SCIF-ch1 eri /* B80 */
+ .long do_IRQ ! rxi
+ .long do_IRQ ! bri
+ .long do_IRQ ! txi
+ .long do_IRQ ! SIOF /* C00 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! HSPI /* C80 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! MMCIF fatat /* D00 */
+ .long do_IRQ ! tran
+ .long do_IRQ ! err
+ .long do_IRQ ! frdy
+ .long do_IRQ ! DMAC dmint8 /* D80 */
+ .long do_IRQ ! dmint9
+ .long do_IRQ ! dmint10
+ .long do_IRQ ! dmint11
+ .long do_IRQ ! TMU-ch3 /* E00 */
+ .long do_IRQ ! TMU-ch4
+ .long do_IRQ ! TMU-ch5
+ .long exception_error
+ .long do_IRQ ! SSI
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! FLCTL flste /* F00 */
+ .long do_IRQ ! fltend
+ .long do_IRQ ! fltrq0
+ .long do_IRQ ! fltrq1
+ .long do_IRQ ! GPIO gpioi0 /* F80 */
+ .long do_IRQ ! gpioi1
+ .long do_IRQ ! gpioi2
+ .long do_IRQ ! gpioi3
#endif
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 42427b79697..c294de1e14a 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -3,7 +3,7 @@
*
* CPU Subtype Probing for SH-4.
*
- * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2001 - 2006 Paul Mundt
* Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -29,7 +29,7 @@ int __init detect_cpu_and_cache_system(void)
[9] = (1 << 16)
};
- pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+ pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
cvr = (ctrl_inl(CCN_CVR));
@@ -38,7 +38,6 @@ int __init detect_cpu_and_cache_system(void)
*/
cpu_data->icache.way_incr = (1 << 13);
cpu_data->icache.entry_shift = 5;
- cpu_data->icache.entry_mask = 0x1fe0;
cpu_data->icache.sets = 256;
cpu_data->icache.ways = 1;
cpu_data->icache.linesz = L1_CACHE_BYTES;
@@ -48,13 +47,29 @@ int __init detect_cpu_and_cache_system(void)
*/
cpu_data->dcache.way_incr = (1 << 14);
cpu_data->dcache.entry_shift = 5;
- cpu_data->dcache.entry_mask = 0x3fe0;
cpu_data->dcache.sets = 512;
cpu_data->dcache.ways = 1;
cpu_data->dcache.linesz = L1_CACHE_BYTES;
- /* Set the FPU flag, virtually all SH-4's have one */
- cpu_data->flags |= CPU_HAS_FPU;
+ /*
+ * Setup some generic flags we can probe
+ * (L2 and DSP detection only work on SH-4A)
+ */
+ if (((pvr >> 16) & 0xff) == 0x10) {
+ if ((cvr & 0x02000000) == 0)
+ cpu_data->flags |= CPU_HAS_L2_CACHE;
+ if ((cvr & 0x10000000) == 0)
+ cpu_data->flags |= CPU_HAS_DSP;
+
+ cpu_data->flags |= CPU_HAS_LLSC;
+ }
+
+ /* FPU detection works for everyone */
+ if ((cvr & 0x20000000) == 1)
+ cpu_data->flags |= CPU_HAS_FPU;
+
+ /* Mask off the upper chip ID */
+ pvr &= 0xffff;
/*
* Probe the underlying processor version/revision and
@@ -63,56 +78,101 @@ int __init detect_cpu_and_cache_system(void)
switch (pvr) {
case 0x205:
cpu_data->type = CPU_SH7750;
- cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+ cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+ CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
break;
case 0x206:
cpu_data->type = CPU_SH7750S;
- cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+ cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+ CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
break;
case 0x1100:
cpu_data->type = CPU_SH7751;
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
break;
case 0x2000:
cpu_data->type = CPU_SH73180;
cpu_data->icache.ways = 4;
cpu_data->dcache.ways = 4;
- cpu_data->flags &= ~CPU_HAS_FPU;
+ cpu_data->flags |= CPU_HAS_LLSC;
+ break;
+ case 0x2001:
+ case 0x2004:
+ cpu_data->type = CPU_SH7770;
+ cpu_data->icache.ways = 4;
+ cpu_data->dcache.ways = 4;
+
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
+ break;
+ case 0x2006:
+ case 0x200A:
+ if (prr == 0x61)
+ cpu_data->type = CPU_SH7781;
+ else
+ cpu_data->type = CPU_SH7780;
+
+ cpu_data->icache.ways = 4;
+ cpu_data->dcache.ways = 4;
+
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+ CPU_HAS_LLSC;
+ break;
+ case 0x3000:
+ case 0x3003:
+ cpu_data->type = CPU_SH7343;
+ cpu_data->icache.ways = 4;
+ cpu_data->dcache.ways = 4;
+ cpu_data->flags |= CPU_HAS_LLSC;
break;
case 0x8000:
cpu_data->type = CPU_ST40RA;
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
break;
case 0x8100:
cpu_data->type = CPU_ST40GX1;
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
break;
case 0x700:
cpu_data->type = CPU_SH4_501;
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
-
- /* No FPU on the SH4-500 series.. */
- cpu_data->flags &= ~CPU_HAS_FPU;
+ cpu_data->flags |= CPU_HAS_PTEA;
break;
case 0x600:
cpu_data->type = CPU_SH4_202;
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
break;
case 0x500 ... 0x501:
switch (prr) {
- case 0x10: cpu_data->type = CPU_SH7750R; break;
- case 0x11: cpu_data->type = CPU_SH7751R; break;
- case 0x50: cpu_data->type = CPU_SH7760; break;
+ case 0x10:
+ cpu_data->type = CPU_SH7750R;
+ break;
+ case 0x11:
+ cpu_data->type = CPU_SH7751R;
+ break;
+ case 0x50 ... 0x5f:
+ cpu_data->type = CPU_SH7760;
+ break;
}
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
+ cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+
break;
default:
cpu_data->type = CPU_SH_NONE;
break;
}
+#ifdef CONFIG_SH_DIRECT_MAPPED
+ cpu_data->icache.ways = 1;
+ cpu_data->dcache.ways = 1;
+#endif
+
/*
* On anything that's not a direct-mapped cache, look to the CVR
* for I/D-cache specifics.
@@ -121,18 +181,56 @@ int __init detect_cpu_and_cache_system(void)
size = sizes[(cvr >> 20) & 0xf];
cpu_data->icache.way_incr = (size >> 1);
cpu_data->icache.sets = (size >> 6);
- cpu_data->icache.entry_mask =
- (cpu_data->icache.way_incr - (1 << 5));
+
}
+ /* Setup the rest of the I-cache info */
+ cpu_data->icache.entry_mask = cpu_data->icache.way_incr -
+ cpu_data->icache.linesz;
+
+ cpu_data->icache.way_size = cpu_data->icache.sets *
+ cpu_data->icache.linesz;
+
+ /* And the rest of the D-cache */
if (cpu_data->dcache.ways > 1) {
size = sizes[(cvr >> 16) & 0xf];
cpu_data->dcache.way_incr = (size >> 1);
cpu_data->dcache.sets = (size >> 6);
- cpu_data->dcache.entry_mask =
- (cpu_data->dcache.way_incr - (1 << 5));
+ }
+
+ cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr -
+ cpu_data->dcache.linesz;
+
+ cpu_data->dcache.way_size = cpu_data->dcache.sets *
+ cpu_data->dcache.linesz;
+
+ /*
+ * Setup the L2 cache desc
+ *
+ * SH-4A's have an optional PIPT L2.
+ */
+ if (cpu_data->flags & CPU_HAS_L2_CACHE) {
+ /*
+ * Size calculation is much more sensible
+ * than it is for the L1.
+ *
+ * Sizes are 128KB, 258KB, 512KB, and 1MB.
+ */
+ size = (cvr & 0xf) << 17;
+
+ BUG_ON(!size);
+
+ cpu_data->scache.way_incr = (1 << 16);
+ cpu_data->scache.entry_shift = 5;
+ cpu_data->scache.ways = 4;
+ cpu_data->scache.linesz = L1_CACHE_BYTES;
+ cpu_data->scache.entry_mask =
+ (cpu_data->scache.way_incr - cpu_data->scache.linesz);
+ cpu_data->scache.sets = size /
+ (cpu_data->scache.linesz * cpu_data->scache.ways);
+ cpu_data->scache.way_size =
+ (cpu_data->scache.sets * cpu_data->scache.linesz);
}
return 0;
}
-
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
new file mode 100644
index 00000000000..6e4e9654135
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -0,0 +1,43 @@
+/*
+ * SH4-202 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe80000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 40, 41, 43, 42 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh4202_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh4202_devices_setup(void)
+{
+ return platform_add_devices(sh4202_devices,
+ ARRAY_SIZE(sh4202_devices));
+}
+__initcall(sh4202_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4/setup-sh73180.c
new file mode 100644
index 00000000000..cc9ea1e2e5d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh73180.c
@@ -0,0 +1,43 @@
+/*
+ * SH73180 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe80000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 80, 81, 83, 82 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh73180_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh73180_devices_setup(void)
+{
+ return platform_add_devices(sh73180_devices,
+ ARRAY_SIZE(sh73180_devices));
+}
+__initcall(sh73180_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4/setup-sh7343.c
new file mode 100644
index 00000000000..91d61cf91ba
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7343.c
@@ -0,0 +1,43 @@
+/*
+ * SH7343 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 80, 81, 83, 82 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7343_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7343_devices_setup(void)
+{
+ return platform_add_devices(sh7343_devices,
+ ARRAY_SIZE(sh7343_devices));
+}
+__initcall(sh7343_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
new file mode 100644
index 00000000000..50812d57c1c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -0,0 +1,48 @@
+/*
+ * SH7750/SH7751 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCI,
+ .irqs = { 23, 24, 25, 0 },
+ }, {
+ .mapbase = 0xffe80000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 40, 41, 43, 42 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7750_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7750_devices_setup(void)
+{
+ return platform_add_devices(sh7750_devices,
+ ARRAY_SIZE(sh7750_devices));
+}
+__initcall(sh7750_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
new file mode 100644
index 00000000000..97f1c9af35d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -0,0 +1,53 @@
+/*
+ * SH7760 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xfe600000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 52, 53, 55, 54 },
+ }, {
+ .mapbase = 0xfe610000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 72, 73, 75, 74 },
+ }, {
+ .mapbase = 0xfe620000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 76, 77, 79, 78 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7760_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7760_devices_setup(void)
+{
+ return platform_add_devices(sh7760_devices,
+ ARRAY_SIZE(sh7760_devices));
+}
+__initcall(sh7760_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4/setup-sh7770.c
new file mode 100644
index 00000000000..6a04cc5f5ac
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7770.c
@@ -0,0 +1,53 @@
+/*
+ * SH7770 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xff923000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 61, 61, 61, 61 },
+ }, {
+ .mapbase = 0xff924000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 62, 62, 62, 62 },
+ }, {
+ .mapbase = 0xff925000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 63, 63, 63, 63 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7770_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7770_devices_setup(void)
+{
+ return platform_add_devices(sh7770_devices,
+ ARRAY_SIZE(sh7770_devices));
+}
+__initcall(sh7770_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
new file mode 100644
index 00000000000..72493f259ed
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
@@ -0,0 +1,79 @@
+/*
+ * SH7780 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xffe80000,
+ .end = 0xffe80000 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = 21,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = 22,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = 23,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 40, 41, 43, 42 },
+ }, {
+ .mapbase = 0xffe10000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 76, 77, 79, 78 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7780_devices[] __initdata = {
+ &rtc_device,
+ &sci_device,
+};
+
+static int __init sh7780_devices_setup(void)
+{
+ return platform_add_devices(sh7780_devices,
+ ARRAY_SIZE(sh7780_devices));
+}
+__initcall(sh7780_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index b09805f3ee2..7bcc73f9b8d 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -1,49 +1,52 @@
/*
- * arch/sh/kernel/cpu/sq.c
+ * arch/sh/kernel/cpu/sh4/sq.c
*
* General management API for SH-4 integrated Store Queues
*
- * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2001 - 2006 Paul Mundt
* Copyright (C) 2001, 2002 M. R. Brown
*
- * Some of this code has been adopted directly from the old arch/sh/mm/sq.c
- * hack that was part of the LinuxDC project. For all intents and purposes,
- * this is a completely new interface that really doesn't have much in common
- * with the old zone-based approach at all. In fact, it's only listed here for
- * general completeness.
- *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/bitmap.h>
+#include <linux/sysdev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
#include <linux/vmalloc.h>
-
+#include <linux/mm.h>
#include <asm/io.h>
#include <asm/page.h>
-#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
#include <asm/cpu/sq.h>
-static LIST_HEAD(sq_mapping_list);
+struct sq_mapping;
+
+struct sq_mapping {
+ const char *name;
+
+ unsigned long sq_addr;
+ unsigned long addr;
+ unsigned int size;
+
+ struct sq_mapping *next;
+};
+
+static struct sq_mapping *sq_mapping_list;
static DEFINE_SPINLOCK(sq_mapping_lock);
+static kmem_cache_t *sq_cache;
+static unsigned long *sq_bitmap;
-/**
- * sq_flush - Flush (prefetch) the store queue cache
- * @addr: the store queue address to flush
- *
- * Executes a prefetch instruction on the specified store queue cache,
- * so that the cached data is written to physical memory.
- */
-inline void sq_flush(void *addr)
-{
- __asm__ __volatile__ ("pref @%0" : : "r" (addr) : "memory");
-}
+#define store_queue_barrier() \
+do { \
+ (void)ctrl_inl(P4SEG_STORE_QUE); \
+ ctrl_outl(0, P4SEG_STORE_QUE + 0); \
+ ctrl_outl(0, P4SEG_STORE_QUE + 8); \
+} while (0);
/**
* sq_flush_range - Flush (prefetch) a specific SQ range
@@ -56,152 +59,73 @@ inline void sq_flush(void *addr)
void sq_flush_range(unsigned long start, unsigned int len)
{
volatile unsigned long *sq = (unsigned long *)start;
- unsigned long dummy;
/* Flush the queues */
for (len >>= 5; len--; sq += 8)
- sq_flush((void *)sq);
+ prefetchw((void *)sq);
/* Wait for completion */
- dummy = ctrl_inl(P4SEG_STORE_QUE);
-
- ctrl_outl(0, P4SEG_STORE_QUE + 0);
- ctrl_outl(0, P4SEG_STORE_QUE + 8);
+ store_queue_barrier();
}
-static struct sq_mapping *__sq_alloc_mapping(unsigned long virt, unsigned long phys, unsigned long size, const char *name)
+static inline void sq_mapping_list_add(struct sq_mapping *map)
{
- struct sq_mapping *map;
-
- if (virt + size > SQ_ADDRMAX)
- return ERR_PTR(-ENOSPC);
-
- map = kmalloc(sizeof(struct sq_mapping), GFP_KERNEL);
- if (!map)
- return ERR_PTR(-ENOMEM);
+ struct sq_mapping **p, *tmp;
- INIT_LIST_HEAD(&map->list);
+ spin_lock_irq(&sq_mapping_lock);
- map->sq_addr = virt;
- map->addr = phys;
- map->size = size + 1;
- map->name = name;
+ p = &sq_mapping_list;
+ while ((tmp = *p) != NULL)
+ p = &tmp->next;
- list_add(&map->list, &sq_mapping_list);
+ map->next = tmp;
+ *p = map;
- return map;
+ spin_unlock_irq(&sq_mapping_lock);
}
-static unsigned long __sq_get_next_addr(void)
+static inline void sq_mapping_list_del(struct sq_mapping *map)
{
- if (!list_empty(&sq_mapping_list)) {
- struct list_head *pos, *tmp;
-
- /*
- * Read one off the list head, as it will have the highest
- * mapped allocation. Set the next one up right above it.
- *
- * This is somewhat sub-optimal, as we don't look at
- * gaps between allocations or anything lower then the
- * highest-level allocation.
- *
- * However, in the interest of performance and the general
- * lack of desire to do constant list rebalancing, we don't
- * worry about it.
- */
- list_for_each_safe(pos, tmp, &sq_mapping_list) {
- struct sq_mapping *entry;
-
- entry = list_entry(pos, typeof(*entry), list);
-
- return entry->sq_addr + entry->size;
+ struct sq_mapping **p, *tmp;
+
+ spin_lock_irq(&sq_mapping_lock);
+
+ for (p = &sq_mapping_list; (tmp = *p); p = &tmp->next)
+ if (tmp == map) {
+ *p = tmp->next;
+ break;
}
- }
- return P4SEG_STORE_QUE;
+ spin_unlock_irq(&sq_mapping_lock);
}
-/**
- * __sq_remap - Perform a translation from the SQ to a phys addr
- * @map: sq mapping containing phys and store queue addresses.
- *
- * Maps the store queue address specified in the mapping to the physical
- * address specified in the mapping.
- */
-static struct sq_mapping *__sq_remap(struct sq_mapping *map)
+static int __sq_remap(struct sq_mapping *map, unsigned long flags)
{
- unsigned long flags, pteh, ptel;
+#if defined(CONFIG_MMU)
struct vm_struct *vma;
- pgprot_t pgprot;
-
- /*
- * Without an MMU (or with it turned off), this is much more
- * straightforward, as we can just load up each queue's QACR with
- * the physical address appropriately masked.
- */
-
- ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
- ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
-#ifdef CONFIG_MMU
- /*
- * With an MMU on the other hand, things are slightly more involved.
- * Namely, we have to have a direct mapping between the SQ addr and
- * the associated physical address in the UTLB by way of setting up
- * a virt<->phys translation by hand. We do this by simply specifying
- * the SQ addr in UTLB.VPN and the associated physical address in
- * UTLB.PPN.
- *
- * Notably, even though this is a special case translation, and some
- * of the configuration bits are meaningless, we're still required
- * to have a valid ASID context in PTEH.
- *
- * We could also probably get by without explicitly setting PTEA, but
- * we do it here just for good measure.
- */
- spin_lock_irqsave(&sq_mapping_lock, flags);
-
- pteh = map->sq_addr;
- ctrl_outl((pteh & MMU_VPN_MASK) | get_asid(), MMU_PTEH);
-
- ptel = map->addr & PAGE_MASK;
- ctrl_outl(((ptel >> 28) & 0xe) | (ptel & 0x1), MMU_PTEA);
-
- pgprot = pgprot_noncached(PAGE_KERNEL);
-
- ptel &= _PAGE_FLAGS_HARDWARE_MASK;
- ptel |= pgprot_val(pgprot);
- ctrl_outl(ptel, MMU_PTEL);
-
- __asm__ __volatile__ ("ldtlb" : : : "memory");
-
- spin_unlock_irqrestore(&sq_mapping_lock, flags);
-
- /*
- * Next, we need to map ourselves in the kernel page table, so that
- * future accesses after a TLB flush will be handled when we take a
- * page fault.
- *
- * Theoretically we could just do this directly and not worry about
- * setting up the translation by hand ahead of time, but for the
- * cases where we want a one-shot SQ mapping followed by a quick
- * writeout before we hit the TLB flush, we do it anyways. This way
- * we at least save ourselves the initial page fault overhead.
- */
vma = __get_vm_area(map->size, VM_ALLOC, map->sq_addr, SQ_ADDRMAX);
if (!vma)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
vma->phys_addr = map->addr;
if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
- map->size, pgprot_val(pgprot))) {
+ map->size, flags)) {
vunmap(vma->addr);
- return NULL;
+ return -EAGAIN;
}
-#endif /* CONFIG_MMU */
+#else
+ /*
+ * Without an MMU (or with it turned off), this is much more
+ * straightforward, as we can just load up each queue's QACR with
+ * the physical address appropriately masked.
+ */
+ ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+ ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+#endif
- return map;
+ return 0;
}
/**
@@ -209,42 +133,65 @@ static struct sq_mapping *__sq_remap(struct sq_mapping *map)
* @phys: Physical address of mapping.
* @size: Length of mapping.
* @name: User invoking mapping.
+ * @flags: Protection flags.
*
* Remaps the physical address @phys through the next available store queue
* address of @size length. @name is logged at boot time as well as through
- * the procfs interface.
- *
- * A pre-allocated and filled sq_mapping pointer is returned, and must be
- * cleaned up with a call to sq_unmap() when the user is done with the
- * mapping.
+ * the sysfs interface.
*/
-struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name)
+unsigned long sq_remap(unsigned long phys, unsigned int size,
+ const char *name, unsigned long flags)
{
struct sq_mapping *map;
- unsigned long virt, end;
+ unsigned long end;
unsigned int psz;
+ int ret, page;
/* Don't allow wraparound or zero size */
end = phys + size - 1;
- if (!size || end < phys)
- return NULL;
+ if (unlikely(!size || end < phys))
+ return -EINVAL;
/* Don't allow anyone to remap normal memory.. */
- if (phys < virt_to_phys(high_memory))
- return NULL;
+ if (unlikely(phys < virt_to_phys(high_memory)))
+ return -EINVAL;
phys &= PAGE_MASK;
+ size = PAGE_ALIGN(end + 1) - phys;
+
+ map = kmem_cache_alloc(sq_cache, GFP_KERNEL);
+ if (unlikely(!map))
+ return -ENOMEM;
+
+ map->addr = phys;
+ map->size = size;
+ map->name = name;
+
+ page = bitmap_find_free_region(sq_bitmap, 0x04000000,
+ get_order(map->size));
+ if (unlikely(page < 0)) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
+
+ ret = __sq_remap(map, flags);
+ if (unlikely(ret != 0))
+ goto out;
+
+ psz = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ pr_info("sqremap: %15s [%4d page%s] va 0x%08lx pa 0x%08lx\n",
+ likely(map->name) ? map->name : "???",
+ psz, psz == 1 ? " " : "s",
+ map->sq_addr, map->addr);
- size = PAGE_ALIGN(end + 1) - phys;
- virt = __sq_get_next_addr();
- psz = (size + (PAGE_SIZE - 1)) / PAGE_SIZE;
- map = __sq_alloc_mapping(virt, phys, size, name);
+ sq_mapping_list_add(map);
- printk("sqremap: %15s [%4d page%s] va 0x%08lx pa 0x%08lx\n",
- map->name ? map->name : "???",
- psz, psz == 1 ? " " : "s",
- map->sq_addr, map->addr);
+ return map->sq_addr;
- return __sq_remap(map);
+out:
+ kmem_cache_free(sq_cache, map);
+ return ret;
}
/**
@@ -255,188 +202,198 @@ struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *n
* sq_remap(). Also frees up the pte that was previously inserted into
* the kernel page table and discards the UTLB translation.
*/
-void sq_unmap(struct sq_mapping *map)
+void sq_unmap(unsigned long vaddr)
{
- if (map->sq_addr > (unsigned long)high_memory)
- vfree((void *)(map->sq_addr & PAGE_MASK));
+ struct sq_mapping **p, *map;
+ struct vm_struct *vma;
+ int page;
- list_del(&map->list);
- kfree(map);
-}
+ for (p = &sq_mapping_list; (map = *p); p = &map->next)
+ if (map->sq_addr == vaddr)
+ break;
-/**
- * sq_clear - Clear a store queue range
- * @addr: Address to start clearing from.
- * @len: Length to clear.
- *
- * A quick zero-fill implementation for clearing out memory that has been
- * remapped through the store queues.
- */
-void sq_clear(unsigned long addr, unsigned int len)
-{
- int i;
+ if (unlikely(!map)) {
+ printk("%s: bad store queue address 0x%08lx\n",
+ __FUNCTION__, vaddr);
+ return;
+ }
- /* Clear out both queues linearly */
- for (i = 0; i < 8; i++) {
- ctrl_outl(0, addr + i + 0);
- ctrl_outl(0, addr + i + 8);
+ page = (map->sq_addr - P4SEG_STORE_QUE) >> PAGE_SHIFT;
+ bitmap_release_region(sq_bitmap, page, get_order(map->size));
+
+#ifdef CONFIG_MMU
+ vma = remove_vm_area((void *)(map->sq_addr & PAGE_MASK));
+ if (!vma) {
+ printk(KERN_ERR "%s: bad address 0x%08lx\n",
+ __FUNCTION__, map->sq_addr);
+ return;
}
+#endif
+
+ sq_mapping_list_del(map);
- sq_flush_range(addr, len);
+ kmem_cache_free(sq_cache, map);
}
-/**
- * sq_vma_unmap - Unmap a VMA range
- * @area: VMA containing range.
- * @addr: Start of range.
- * @len: Length of range.
+/*
+ * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
+ * there is any other easy way to add things on a per-cpu basis without
+ * putting the directory entries somewhere stupid and having to create
+ * links in sysfs by hand back in to the per-cpu directories.
*
- * Searches the sq_mapping_list for a mapping matching the sq addr @addr,
- * and subsequently frees up the entry. Further cleanup is done by generic
- * code.
+ * Some day we may want to have an additional abstraction per store
+ * queue, but considering the kobject hell we already have to deal with,
+ * it's simply not worth the trouble.
*/
-static void sq_vma_unmap(struct vm_area_struct *area,
- unsigned long addr, size_t len)
-{
- struct list_head *pos, *tmp;
+static struct kobject *sq_kobject[NR_CPUS];
- list_for_each_safe(pos, tmp, &sq_mapping_list) {
- struct sq_mapping *entry;
+struct sq_sysfs_attr {
+ struct attribute attr;
+ ssize_t (*show)(char *buf);
+ ssize_t (*store)(const char *buf, size_t count);
+};
- entry = list_entry(pos, typeof(*entry), list);
+#define to_sq_sysfs_attr(attr) container_of(attr, struct sq_sysfs_attr, attr)
- if (entry->sq_addr == addr) {
- /*
- * We could probably get away without doing the tlb flush
- * here, as generic code should take care of most of this
- * when unmapping the rest of the VMA range for us. Leave
- * it in for added sanity for the time being..
- */
- __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK);
+static ssize_t sq_sysfs_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
- list_del(&entry->list);
- kfree(entry);
+ if (likely(sattr->show))
+ return sattr->show(buf);
- return;
- }
- }
+ return -EIO;
}
-/**
- * sq_vma_sync - Sync a VMA range
- * @area: VMA containing range.
- * @start: Start of range.
- * @len: Length of range.
- * @flags: Additional flags.
- *
- * Synchronizes an sq mapped range by flushing the store queue cache for
- * the duration of the mapping.
- *
- * Used internally for user mappings, which must use msync() to prefetch
- * the store queue cache.
- */
-static int sq_vma_sync(struct vm_area_struct *area,
- unsigned long start, size_t len, unsigned int flags)
+static ssize_t sq_sysfs_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
{
- sq_flush_range(start, len);
+ struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
- return 0;
+ if (likely(sattr->store))
+ return sattr->store(buf, count);
+
+ return -EIO;
}
-static struct vm_operations_struct sq_vma_ops = {
- .unmap = sq_vma_unmap,
- .sync = sq_vma_sync,
-};
+static ssize_t mapping_show(char *buf)
+{
+ struct sq_mapping **list, *entry;
+ char *p = buf;
-/**
- * sq_mmap - mmap() for /dev/cpu/sq
- * @file: unused.
- * @vma: VMA to remap.
- *
- * Remap the specified vma @vma through the store queues, and setup associated
- * information for the new mapping. Also build up the page tables for the new
- * area.
- */
-static int sq_mmap(struct file *file, struct vm_area_struct *vma)
+ for (list = &sq_mapping_list; (entry = *list); list = &entry->next)
+ p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n",
+ entry->sq_addr, entry->sq_addr + entry->size,
+ entry->addr, entry->name);
+
+ return p - buf;
+}
+
+static ssize_t mapping_store(const char *buf, size_t count)
{
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long size = vma->vm_end - vma->vm_start;
- struct sq_mapping *map;
+ unsigned long base = 0, len = 0;
- /*
- * We're not interested in any arbitrary virtual address that has
- * been stuck in the VMA, as we already know what addresses we
- * want. Save off the size, and reposition the VMA to begin at
- * the next available sq address.
- */
- vma->vm_start = __sq_get_next_addr();
- vma->vm_end = vma->vm_start + size;
+ sscanf(buf, "%lx %lx", &base, &len);
+ if (!base)
+ return -EIO;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (likely(len)) {
+ int ret = sq_remap(base, len, "Userspace",
+ pgprot_val(PAGE_SHARED));
+ if (ret < 0)
+ return ret;
+ } else
+ sq_unmap(base);
- vma->vm_flags |= VM_IO | VM_RESERVED;
+ return count;
+}
- map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace");
+static struct sq_sysfs_attr mapping_attr =
+ __ATTR(mapping, 0644, mapping_show, mapping_store);
- if (io_remap_pfn_range(vma, map->sq_addr, map->addr >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- return -EAGAIN;
+static struct attribute *sq_sysfs_attrs[] = {
+ &mapping_attr.attr,
+ NULL,
+};
- vma->vm_ops = &sq_vma_ops;
+static struct sysfs_ops sq_sysfs_ops = {
+ .show = sq_sysfs_show,
+ .store = sq_sysfs_store,
+};
- return 0;
-}
+static struct kobj_type ktype_percpu_entry = {
+ .sysfs_ops = &sq_sysfs_ops,
+ .default_attrs = sq_sysfs_attrs,
+};
-#ifdef CONFIG_PROC_FS
-static int sq_mapping_read_proc(char *buf, char **start, off_t off,
- int len, int *eof, void *data)
+static int __devinit sq_sysdev_add(struct sys_device *sysdev)
{
- struct list_head *pos;
- char *p = buf;
+ unsigned int cpu = sysdev->id;
+ struct kobject *kobj;
- list_for_each_prev(pos, &sq_mapping_list) {
- struct sq_mapping *entry;
+ sq_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (unlikely(!sq_kobject[cpu]))
+ return -ENOMEM;
- entry = list_entry(pos, typeof(*entry), list);
+ kobj = sq_kobject[cpu];
+ kobj->parent = &sysdev->kobj;
+ kobject_set_name(kobj, "%s", "sq");
+ kobj->ktype = &ktype_percpu_entry;
- p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr,
- entry->sq_addr + entry->size - 1, entry->addr,
- entry->name);
- }
-
- return p - buf;
+ return kobject_register(kobj);
}
-#endif
-static struct file_operations sq_fops = {
- .owner = THIS_MODULE,
- .mmap = sq_mmap,
-};
+static int __devexit sq_sysdev_remove(struct sys_device *sysdev)
+{
+ unsigned int cpu = sysdev->id;
+ struct kobject *kobj = sq_kobject[cpu];
-static struct miscdevice sq_dev = {
- .minor = STORE_QUEUE_MINOR,
- .name = "sq",
- .fops = &sq_fops,
+ kobject_unregister(kobj);
+ return 0;
+}
+
+static struct sysdev_driver sq_sysdev_driver = {
+ .add = sq_sysdev_add,
+ .remove = __devexit_p(sq_sysdev_remove),
};
static int __init sq_api_init(void)
{
- int ret;
+ unsigned int nr_pages = 0x04000000 >> PAGE_SHIFT;
+ unsigned int size = (nr_pages + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+ int ret = -ENOMEM;
+
printk(KERN_NOTICE "sq: Registering store queue API.\n");
- create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
+ sq_cache = kmem_cache_create("store_queue_cache",
+ sizeof(struct sq_mapping), 0, 0,
+ NULL, NULL);
+ if (unlikely(!sq_cache))
+ return ret;
- ret = misc_register(&sq_dev);
- if (ret)
- remove_proc_entry("sq_mapping", NULL);
+ sq_bitmap = kzalloc(size, GFP_KERNEL);
+ if (unlikely(!sq_bitmap))
+ goto out;
+
+ ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver);
+ if (unlikely(ret != 0))
+ goto out;
+
+ return 0;
+
+out:
+ kfree(sq_bitmap);
+ kmem_cache_destroy(sq_cache);
return ret;
}
static void __exit sq_api_exit(void)
{
- misc_deregister(&sq_dev);
- remove_proc_entry("sq_mapping", NULL);
+ sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver);
+ kfree(sq_bitmap);
+ kmem_cache_destroy(sq_cache);
}
module_init(sq_api_init);
@@ -445,11 +402,7 @@ module_exit(sq_api_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(STORE_QUEUE_MINOR);
EXPORT_SYMBOL(sq_remap);
EXPORT_SYMBOL(sq_unmap);
-EXPORT_SYMBOL(sq_clear);
-EXPORT_SYMBOL(sq_flush);
EXPORT_SYMBOL(sq_flush_range);
-
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 1378db375e1..a00022722e9 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1999, 2000 Niibe Yutaka
* Copyright (C) 2002 M. R. Brown
- * Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2004 - 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -49,7 +49,7 @@ static int __init sh_console_setup(struct console *co, char *options)
return 0;
}
-static struct console early_console = {
+static struct console bios_console = {
.name = "bios",
.write = sh_console_write,
.setup = sh_console_setup,
@@ -59,34 +59,43 @@ static struct console early_console = {
#endif
#ifdef CONFIG_EARLY_SCIF_CONSOLE
+#include <linux/serial_core.h>
+#include "../../../drivers/serial/sh-sci.h"
+
+#ifdef CONFIG_CPU_SH4
#define SCIF_REG 0xffe80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
+#define SCIF_REG 0xfffe9800
+#else
+#error "Undefined SCIF for this subtype"
+#endif
+
+static struct uart_port scif_port = {
+ .mapbase = SCIF_REG,
+ .membase = (char __iomem *)SCIF_REG,
+};
static void scif_sercon_putc(int c)
{
- while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+ while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
+ ;
- ctrl_outb(c, SCIF_REG + 12);
- ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+ sci_out(&scif_port, SCxTDR, c);
+ sci_in(&scif_port, SCxSR);
+ sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+
+ while ((sci_in(&scif_port, SCxSR) & 0x40) == 0);
+ ;
if (c == '\n')
scif_sercon_putc('\r');
}
-static void scif_sercon_flush(void)
-{
- ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-
- while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
-
- ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-}
-
-static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+static void scif_sercon_write(struct console *con, const char *s,
+ unsigned count)
{
while (count-- > 0)
scif_sercon_putc(*s++);
-
- scif_sercon_flush();
}
static int __init scif_sercon_setup(struct console *con, char *options)
@@ -96,7 +105,7 @@ static int __init scif_sercon_setup(struct console *con, char *options)
return 0;
}
-static struct console early_console = {
+static struct console scif_console = {
.name = "sercon",
.write = scif_sercon_write,
.setup = scif_sercon_setup,
@@ -104,7 +113,7 @@ static struct console early_console = {
.index = -1,
};
-void scif_sercon_init(int baud)
+static void scif_sercon_init(int baud)
{
ctrl_outw(0, SCIF_REG + 8);
ctrl_outw(0, SCIF_REG);
@@ -122,16 +131,61 @@ void scif_sercon_init(int baud)
}
#endif
-void __init enable_early_printk(void)
+/*
+ * Setup a default console, if more than one is compiled in, rely on the
+ * earlyprintk= parsing to give priority.
+ */
+static struct console *early_console =
+#ifdef CONFIG_SH_STANDARD_BIOS
+ &bios_console
+#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
+ &scif_console
+#else
+ NULL
+#endif
+ ;
+
+static int __initdata keep_early;
+
+int __init setup_early_printk(char *opt)
{
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
- scif_sercon_init(115200);
+ char *space;
+ char buf[256];
+
+ strlcpy(buf, opt, sizeof(buf));
+ space = strchr(buf, ' ');
+ if (space)
+ *space = 0;
+
+ if (strstr(buf, "keep"))
+ keep_early = 1;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+ if (!strncmp(buf, "bios", 4))
+ early_console = &bios_console;
+#endif
+#if defined(CONFIG_EARLY_SCIF_CONSOLE)
+ if (!strncmp(buf, "serial", 6)) {
+ early_console = &scif_console;
+
+#ifdef CONFIG_CPU_SH4
+ scif_sercon_init(115200);
+#endif
+ }
#endif
- register_console(&early_console);
+
+ if (likely(early_console))
+ register_console(early_console);
+
+ return 1;
}
+__setup("earlyprintk=", setup_early_printk);
-void disable_early_printk(void)
+void __init disable_early_printk(void)
{
- unregister_console(&early_console);
+ if (!keep_early) {
+ printk("disabling early console\n");
+ unregister_console(early_console);
+ } else
+ printk("keeping early console\n");
}
-
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 7dfd2ba75f7..fe8221855b2 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -18,24 +18,6 @@
#include <asm/cpu/mmu_context.h>
#include <asm/unistd.h>
-#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
-#define sys_nfsservctl sys_ni_syscall
-#endif
-
-#if !defined(CONFIG_MMU)
-#define sys_madvise sys_ni_syscall
-#define sys_readahead sys_ni_syscall
-#define sys_mprotect sys_ni_syscall
-#define sys_msync sys_ni_syscall
-#define sys_mlock sys_ni_syscall
-#define sys_munlock sys_ni_syscall
-#define sys_mlockall sys_ni_syscall
-#define sys_munlockall sys_ni_syscall
-#define sys_mremap sys_ni_syscall
-#define sys_mincore sys_ni_syscall
-#define sys_remap_file_pages sys_ni_syscall
-#endif
-
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
! to be jumped is too far, but it causes illegal slot exception.
@@ -326,7 +308,7 @@ ENTRY(exception_error)
.align 2
ret_from_exception:
preempt_stop()
-ret_from_irq:
+ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
@@ -389,11 +371,12 @@ work_pending:
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
- tst #_TIF_SIGPENDING, r0
+ tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
work_notifysig:
bt/s restore_all
mov r15, r4
- mov #0, r5
+ mov r12, r5 ! set arg1(save_r0)
+ mov r0, r6
mov.l 2f, r1
mova restore_all, r0
jmp @r1
@@ -431,7 +414,7 @@ work_resched:
.align 2
1: .long schedule
-2: .long do_signal
+2: .long do_notify_resume
.align 2
syscall_exit_work:
@@ -552,6 +535,7 @@ syscall_call:
mov.l @r9, r8
jsr @r8 ! jump to specific syscall handler
nop
+ mov.l @(OFF_R0,r15), r12 ! save r0
mov.l r0, @(OFF_R0,r15) ! save the return value
!
syscall_exit:
@@ -644,7 +628,7 @@ skip_restore:
!
#if defined(CONFIG_KGDB_NMI)
! Clear in_nmi
- mov.l 4f, k0
+ mov.l 6f, k0
mov #0, k1
mov.b k1, @k0
#endif
@@ -722,7 +706,7 @@ interrupt:
!
!
.align 2
-handle_exception:
+ENTRY(handle_exception)
! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
! save all registers onto stack.
!
@@ -732,8 +716,8 @@ handle_exception:
bt/s 1f ! It's a kernel to kernel transition.
mov r15, k0 ! save original stack to k0
/* User space to kernel */
- mov #0x20, k1
- shll8 k1 ! k1 := 8192 (== THREAD_SIZE)
+ mov #(THREAD_SIZE >> 8), k1
+ shll8 k1 ! k1 := THREAD_SIZE
add current, k1
mov k1, r15 ! change to kernel stack
!
@@ -838,300 +822,3 @@ ENTRY(exception_none)
rts
nop
- .data
-ENTRY(sys_call_table)
- .long sys_ni_syscall /* 0 - old "setup()" system call*/
- .long sys_exit
- .long sys_fork
- .long sys_read
- .long sys_write
- .long sys_open /* 5 */
- .long sys_close
- .long sys_waitpid
- .long sys_creat
- .long sys_link
- .long sys_unlink /* 10 */
- .long sys_execve
- .long sys_chdir
- .long sys_time
- .long sys_mknod
- .long sys_chmod /* 15 */
- .long sys_lchown16
- .long sys_ni_syscall /* old break syscall holder */
- .long sys_stat
- .long sys_lseek
- .long sys_getpid /* 20 */
- .long sys_mount
- .long sys_oldumount
- .long sys_setuid16
- .long sys_getuid16
- .long sys_stime /* 25 */
- .long sys_ptrace
- .long sys_alarm
- .long sys_fstat
- .long sys_pause
- .long sys_utime /* 30 */
- .long sys_ni_syscall /* old stty syscall holder */
- .long sys_ni_syscall /* old gtty syscall holder */
- .long sys_access
- .long sys_nice
- .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
- .long sys_sync
- .long sys_kill
- .long sys_rename
- .long sys_mkdir
- .long sys_rmdir /* 40 */
- .long sys_dup
- .long sys_pipe
- .long sys_times
- .long sys_ni_syscall /* old prof syscall holder */
- .long sys_brk /* 45 */
- .long sys_setgid16
- .long sys_getgid16
- .long sys_signal
- .long sys_geteuid16
- .long sys_getegid16 /* 50 */
- .long sys_acct
- .long sys_umount /* recycled never used phys() */
- .long sys_ni_syscall /* old lock syscall holder */
- .long sys_ioctl
- .long sys_fcntl /* 55 */
- .long sys_ni_syscall /* old mpx syscall holder */
- .long sys_setpgid
- .long sys_ni_syscall /* old ulimit syscall holder */
- .long sys_ni_syscall /* sys_olduname */
- .long sys_umask /* 60 */
- .long sys_chroot
- .long sys_ustat
- .long sys_dup2
- .long sys_getppid
- .long sys_getpgrp /* 65 */
- .long sys_setsid
- .long sys_sigaction
- .long sys_sgetmask
- .long sys_ssetmask
- .long sys_setreuid16 /* 70 */
- .long sys_setregid16
- .long sys_sigsuspend
- .long sys_sigpending
- .long sys_sethostname
- .long sys_setrlimit /* 75 */
- .long sys_old_getrlimit
- .long sys_getrusage
- .long sys_gettimeofday
- .long sys_settimeofday
- .long sys_getgroups16 /* 80 */
- .long sys_setgroups16
- .long sys_ni_syscall /* sys_oldselect */
- .long sys_symlink
- .long sys_lstat
- .long sys_readlink /* 85 */
- .long sys_uselib
- .long sys_swapon
- .long sys_reboot
- .long old_readdir
- .long old_mmap /* 90 */
- .long sys_munmap
- .long sys_truncate
- .long sys_ftruncate
- .long sys_fchmod
- .long sys_fchown16 /* 95 */
- .long sys_getpriority
- .long sys_setpriority
- .long sys_ni_syscall /* old profil syscall holder */
- .long sys_statfs
- .long sys_fstatfs /* 100 */
- .long sys_ni_syscall /* ioperm */
- .long sys_socketcall
- .long sys_syslog
- .long sys_setitimer
- .long sys_getitimer /* 105 */
- .long sys_newstat
- .long sys_newlstat
- .long sys_newfstat
- .long sys_uname
- .long sys_ni_syscall /* 110 */ /* iopl */
- .long sys_vhangup
- .long sys_ni_syscall /* idle */
- .long sys_ni_syscall /* vm86old */
- .long sys_wait4
- .long sys_swapoff /* 115 */
- .long sys_sysinfo
- .long sys_ipc
- .long sys_fsync
- .long sys_sigreturn
- .long sys_clone /* 120 */
- .long sys_setdomainname
- .long sys_newuname
- .long sys_ni_syscall /* sys_modify_ldt */
- .long sys_adjtimex
- .long sys_mprotect /* 125 */
- .long sys_sigprocmask
- .long sys_ni_syscall /* old "create_module" */
- .long sys_init_module
- .long sys_delete_module
- .long sys_ni_syscall /* 130: old "get_kernel_syms" */
- .long sys_quotactl
- .long sys_getpgid
- .long sys_fchdir
- .long sys_bdflush
- .long sys_sysfs /* 135 */
- .long sys_personality
- .long sys_ni_syscall /* for afs_syscall */
- .long sys_setfsuid16
- .long sys_setfsgid16
- .long sys_llseek /* 140 */
- .long sys_getdents
- .long sys_select
- .long sys_flock
- .long sys_msync
- .long sys_readv /* 145 */
- .long sys_writev
- .long sys_getsid
- .long sys_fdatasync
- .long sys_sysctl
- .long sys_mlock /* 150 */
- .long sys_munlock
- .long sys_mlockall
- .long sys_munlockall
- .long sys_sched_setparam
- .long sys_sched_getparam /* 155 */
- .long sys_sched_setscheduler
- .long sys_sched_getscheduler
- .long sys_sched_yield
- .long sys_sched_get_priority_max
- .long sys_sched_get_priority_min /* 160 */
- .long sys_sched_rr_get_interval
- .long sys_nanosleep
- .long sys_mremap
- .long sys_setresuid16
- .long sys_getresuid16 /* 165 */
- .long sys_ni_syscall /* vm86 */
- .long sys_ni_syscall /* old "query_module" */
- .long sys_poll
- .long sys_nfsservctl
- .long sys_setresgid16 /* 170 */
- .long sys_getresgid16
- .long sys_prctl
- .long sys_rt_sigreturn
- .long sys_rt_sigaction
- .long sys_rt_sigprocmask /* 175 */
- .long sys_rt_sigpending
- .long sys_rt_sigtimedwait
- .long sys_rt_sigqueueinfo
- .long sys_rt_sigsuspend
- .long sys_pread_wrapper /* 180 */
- .long sys_pwrite_wrapper
- .long sys_chown16
- .long sys_getcwd
- .long sys_capget
- .long sys_capset /* 185 */
- .long sys_sigaltstack
- .long sys_sendfile
- .long sys_ni_syscall /* streams1 */
- .long sys_ni_syscall /* streams2 */
- .long sys_vfork /* 190 */
- .long sys_getrlimit
- .long sys_mmap2
- .long sys_truncate64
- .long sys_ftruncate64
- .long sys_stat64 /* 195 */
- .long sys_lstat64
- .long sys_fstat64
- .long sys_lchown
- .long sys_getuid
- .long sys_getgid /* 200 */
- .long sys_geteuid
- .long sys_getegid
- .long sys_setreuid
- .long sys_setregid
- .long sys_getgroups /* 205 */
- .long sys_setgroups
- .long sys_fchown
- .long sys_setresuid
- .long sys_getresuid
- .long sys_setresgid /* 210 */
- .long sys_getresgid
- .long sys_chown
- .long sys_setuid
- .long sys_setgid
- .long sys_setfsuid /* 215 */
- .long sys_setfsgid
- .long sys_pivot_root
- .long sys_mincore
- .long sys_madvise
- .long sys_getdents64 /* 220 */
- .long sys_fcntl64
- .long sys_ni_syscall /* reserved for TUX */
- .long sys_ni_syscall /* Reserved for Security */
- .long sys_gettid
- .long sys_readahead /* 225 */
- .long sys_setxattr
- .long sys_lsetxattr
- .long sys_fsetxattr
- .long sys_getxattr
- .long sys_lgetxattr /* 230 */
- .long sys_fgetxattr
- .long sys_listxattr
- .long sys_llistxattr
- .long sys_flistxattr
- .long sys_removexattr /* 235 */
- .long sys_lremovexattr
- .long sys_fremovexattr
- .long sys_tkill
- .long sys_sendfile64
- .long sys_futex /* 240 */
- .long sys_sched_setaffinity
- .long sys_sched_getaffinity
- .long sys_ni_syscall
- .long sys_ni_syscall
- .long sys_io_setup /* 245 */
- .long sys_io_destroy
- .long sys_io_getevents
- .long sys_io_submit
- .long sys_io_cancel
- .long sys_fadvise64 /* 250 */
- .long sys_ni_syscall
- .long sys_exit_group
- .long sys_lookup_dcookie
- .long sys_epoll_create
- .long sys_epoll_ctl /* 255 */
- .long sys_epoll_wait
- .long sys_remap_file_pages
- .long sys_set_tid_address
- .long sys_timer_create
- .long sys_timer_settime /* 260 */
- .long sys_timer_gettime
- .long sys_timer_getoverrun
- .long sys_timer_delete
- .long sys_clock_settime
- .long sys_clock_gettime /* 265 */
- .long sys_clock_getres
- .long sys_clock_nanosleep
- .long sys_statfs64
- .long sys_fstatfs64
- .long sys_tgkill /* 270 */
- .long sys_utimes
- .long sys_fadvise64_64_wrapper
- .long sys_ni_syscall /* Reserved for vserver */
- .long sys_ni_syscall /* Reserved for mbind */
- .long sys_ni_syscall /* 275 - get_mempolicy */
- .long sys_ni_syscall /* set_mempolicy */
- .long sys_mq_open
- .long sys_mq_unlink
- .long sys_mq_timedsend
- .long sys_mq_timedreceive /* 280 */
- .long sys_mq_notify
- .long sys_mq_getsetattr
- .long sys_ni_syscall /* Reserved for kexec */
- .long sys_waitid
- .long sys_add_key /* 285 */
- .long sys_request_key
- .long sys_keyctl
- .long sys_ioprio_set
- .long sys_ioprio_get
- .long sys_inotify_init /* 290 */
- .long sys_inotify_add_watch
- .long sys_inotify_rm_watch
-
-/* End of entry.S */
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index 9b9e6ef626c..f5f53d14f24 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -11,6 +11,18 @@
* Head.S contains the SH exception handlers and startup code.
*/
#include <linux/linkage.h>
+#include <asm/thread_info.h>
+
+#ifdef CONFIG_CPU_SH4A
+#define SYNCO() synco
+
+#define PREFI(label, reg) \
+ mov.l label, reg; \
+ prefi @reg
+#else
+#define SYNCO()
+#define PREFI(label, reg)
+#endif
.section .empty_zero_page, "aw"
ENTRY(empty_zero_page)
@@ -42,18 +54,25 @@ ENTRY(_stext)
! Initialize global interrupt mask
mov #0, r0
ldc r0, r6_bank
+
+ /*
+ * Prefetch if possible to reduce cache miss penalty.
+ *
+ * We do this early on for SH-4A as a micro-optimization,
+ * as later on we will have speculative execution enabled
+ * and this will become less of an issue.
+ */
+ PREFI(5f, r0)
+ PREFI(6f, r0)
+
!
mov.l 2f, r0
mov r0, r15 ! Set initial r15 (stack pointer)
- mov #0x20, r1 !
- shll8 r1 ! r1 = 8192
+ mov #(THREAD_SIZE >> 8), r1
+ shll8 r1 ! r1 = THREAD_SIZE
sub r1, r0 !
ldc r0, r7_bank ! ... and initial thread_info
- !
- ! Additional CPU initialization
- mov.l 6f, r0
- jsr @r0
- nop
+
! Clear BSS area
mov.l 3f, r1
add #4, r1
@@ -62,6 +81,14 @@ ENTRY(_stext)
9: cmp/hs r2, r1
bf/s 9b ! while (r1 < r2)
mov.l r0,@-r2
+
+ ! Additional CPU initialization
+ mov.l 6f, r0
+ jsr @r0
+ nop
+
+ SYNCO() ! Wait for pending instructions..
+
! Start kernel
mov.l 5f, r0
jmp @r0
@@ -69,7 +96,7 @@ ENTRY(_stext)
.balign 4
1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
-2: .long stack
+2: .long init_thread_union+THREAD_SIZE
3: .long __bss_start
4: .long _end
5: .long start_kernel
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
index 71c9fde2fd9..501fe03e371 100644
--- a/arch/sh/kernel/io.c
+++ b/arch/sh/kernel/io.c
@@ -61,6 +61,73 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
}
EXPORT_SYMBOL(memset_io);
+void __raw_readsl(unsigned long addr, void *datap, int len)
+{
+ u32 *data;
+
+ for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--)
+ *data++ = ctrl_inl(addr);
+
+ if (likely(len >= (0x20 >> 2))) {
+ int tmp2, tmp3, tmp4, tmp5, tmp6;
+
+ __asm__ __volatile__(
+ "1: \n\t"
+ "mov.l @%7, r0 \n\t"
+ "mov.l @%7, %2 \n\t"
+#ifdef CONFIG_CPU_SH4
+ "movca.l r0, @%0 \n\t"
+#else
+ "mov.l r0, @%0 \n\t"
+#endif
+ "mov.l @%7, %3 \n\t"
+ "mov.l @%7, %4 \n\t"
+ "mov.l @%7, %5 \n\t"
+ "mov.l @%7, %6 \n\t"
+ "mov.l @%7, r7 \n\t"
+ "mov.l @%7, r0 \n\t"
+ "mov.l %2, @(0x04,%0) \n\t"
+ "mov #0x20>>2, %2 \n\t"
+ "mov.l %3, @(0x08,%0) \n\t"
+ "sub %2, %1 \n\t"
+ "mov.l %4, @(0x0c,%0) \n\t"
+ "cmp/hi %1, %2 ! T if 32 > len \n\t"
+ "mov.l %5, @(0x10,%0) \n\t"
+ "mov.l %6, @(0x14,%0) \n\t"
+ "mov.l r7, @(0x18,%0) \n\t"
+ "mov.l r0, @(0x1c,%0) \n\t"
+ "bf.s 1b \n\t"
+ " add #0x20, %0 \n\t"
+ : "=&r" (data), "=&r" (len),
+ "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
+ "=&r" (tmp5), "=&r" (tmp6)
+ : "r"(addr), "0" (data), "1" (len)
+ : "r0", "r7", "t", "memory");
+ }
+
+ for (; len != 0; len--)
+ *data++ = ctrl_inl(addr);
+}
+EXPORT_SYMBOL(__raw_readsl);
+
+void __raw_writesl(unsigned long addr, const void *data, int len)
+{
+ if (likely(len != 0)) {
+ int tmp1;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "mov.l @%0+, %1 \n\t"
+ "dt %3 \n\t"
+ "bf.s 1b \n\t"
+ " mov.l %1, @%4 \n\t"
+ : "=&r" (data), "=&r" (tmp1)
+ : "0" (data), "r" (len), "r"(addr)
+ : "t", "memory");
+ }
+}
+EXPORT_SYMBOL(__raw_writesl);
+
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
return sh_mv.mv_ioport_map(port, nr);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index c2e07f7f349..c7ebd6aec95 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -1,5 +1,4 @@
-/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $
- *
+/*
* linux/arch/sh/kernel/irq.c
*
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
@@ -7,13 +6,15 @@
*
* SuperH version: Copyright (C) 1999 Niibe Yutaka
*/
-
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/thread_info.h>
#include <asm/cpu/mmu_context.h>
/*
@@ -60,15 +61,46 @@ unlock:
}
#endif
+#ifdef CONFIG_4KSTACKS
+/*
+ * per-CPU IRQ handling contexts (thread information and stack)
+ */
+union irq_ctx {
+ struct thread_info tinfo;
+ u32 stack[THREAD_SIZE/sizeof(u32)];
+};
+
+static union irq_ctx *hardirq_ctx[NR_CPUS];
+static union irq_ctx *softirq_ctx[NR_CPUS];
+#endif
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
int irq = r4;
+#ifdef CONFIG_4KSTACKS
+ union irq_ctx *curctx, *irqctx;
+#endif
irq_enter();
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /* Debugging check for stack overflow: is there less than 1KB free? */
+ {
+ long sp;
+
+ __asm__ __volatile__ ("and r15, %0" :
+ "=r" (sp) : "0" (THREAD_SIZE - 1));
+
+ if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+ printk("do_IRQ: stack overflow: %ld\n",
+ sp - sizeof(struct thread_info));
+ dump_stack();
+ }
+ }
+#endif
+
#ifdef CONFIG_CPU_HAS_INTEVT
__asm__ __volatile__ (
#ifdef CONFIG_CPU_HAS_SR_RB
@@ -87,7 +119,135 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif
irq = irq_demux(irq);
- __do_IRQ(irq, &regs);
+
+#ifdef CONFIG_4KSTACKS
+ curctx = (union irq_ctx *)current_thread_info();
+ irqctx = hardirq_ctx[smp_processor_id()];
+
+ /*
+ * this is where we switch to the IRQ stack. However, if we are
+ * already using the IRQ stack (because we interrupted a hardirq
+ * handler) we can't do that and just have to keep using the
+ * current stack (which is the irq stack already after all)
+ */
+ if (curctx != irqctx) {
+ u32 *isp;
+
+ isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+ irqctx->tinfo.task = curctx->tinfo.task;
+ irqctx->tinfo.previous_sp = current_stack_pointer;
+
+ __asm__ __volatile__ (
+ "mov %0, r4 \n"
+ "mov %1, r5 \n"
+ "mov r15, r9 \n"
+ "jsr @%2 \n"
+ /* swith to the irq stack */
+ " mov %3, r15 \n"
+ /* restore the stack (ring zero) */
+ "mov r9, r15 \n"
+ : /* no outputs */
+ : "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
+ /* XXX: A somewhat excessive clobber list? -PFM */
+ : "memory", "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "r8", "t", "pr"
+ );
+ } else
+#endif
+ __do_IRQ(irq, &regs);
+
irq_exit();
+
return 1;
}
+
+#ifdef CONFIG_4KSTACKS
+/*
+ * These should really be __section__(".bss.page_aligned") as well, but
+ * gcc's 3.0 and earlier don't handle that correctly.
+ */
+static char softirq_stack[NR_CPUS * THREAD_SIZE]
+ __attribute__((__aligned__(THREAD_SIZE)));
+
+static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+ __attribute__((__aligned__(THREAD_SIZE)));
+
+/*
+ * allocate per-cpu stacks for hardirq and for softirq processing
+ */
+void irq_ctx_init(int cpu)
+{
+ union irq_ctx *irqctx;
+
+ if (hardirq_ctx[cpu])
+ return;
+
+ irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE];
+ irqctx->tinfo.task = NULL;
+ irqctx->tinfo.exec_domain = NULL;
+ irqctx->tinfo.cpu = cpu;
+ irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
+ irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
+
+ hardirq_ctx[cpu] = irqctx;
+
+ irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE];
+ irqctx->tinfo.task = NULL;
+ irqctx->tinfo.exec_domain = NULL;
+ irqctx->tinfo.cpu = cpu;
+ irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET;
+ irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
+
+ softirq_ctx[cpu] = irqctx;
+
+ printk("CPU %u irqstacks, hard=%p soft=%p\n",
+ cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
+}
+
+void irq_ctx_exit(int cpu)
+{
+ hardirq_ctx[cpu] = NULL;
+}
+
+extern asmlinkage void __do_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+ unsigned long flags;
+ struct thread_info *curctx;
+ union irq_ctx *irqctx;
+ u32 *isp;
+
+ if (in_interrupt())
+ return;
+
+ local_irq_save(flags);
+
+ if (local_softirq_pending()) {
+ curctx = current_thread_info();
+ irqctx = softirq_ctx[smp_processor_id()];
+ irqctx->tinfo.task = curctx->task;
+ irqctx->tinfo.previous_sp = current_stack_pointer;
+
+ /* build the stack frame on the softirq stack */
+ isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+
+ __asm__ __volatile__ (
+ "mov r15, r9 \n"
+ "jsr @%0 \n"
+ /* switch to the softirq stack */
+ " mov %1, r15 \n"
+ /* restore the thread stack */
+ "mov r9, r15 \n"
+ : /* no outputs */
+ : "r" (__do_softirq), "r" (isp)
+ /* XXX: A somewhat excessive clobber list? -PFM */
+ : "memory", "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
+ );
+ }
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(do_softirq);
+#endif
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index 42638b92b51..9c6315f0335 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -101,16 +101,17 @@
#include <linux/linkage.h>
#include <linux/init.h>
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
#include <asm/system.h>
#include <asm/current.h>
#include <asm/signal.h>
#include <asm/pgtable.h>
#include <asm/ptrace.h>
#include <asm/kgdb.h>
-
-#ifdef CONFIG_SH_KGDB_CONSOLE
-#include <linux/console.h>
-#endif
+#include <asm/io.h>
/* Function pointers for linkage */
kgdb_debug_hook_t *kgdb_debug_hook;
@@ -240,7 +241,6 @@ static jmp_buf rem_com_env;
/* Misc static */
static int stepped_address;
static short stepped_opcode;
-static const char hexchars[] = "0123456789abcdef";
static char in_buffer[BUFMAX];
static char out_buffer[OUTBUFMAX];
@@ -253,29 +253,6 @@ typedef unsigned char threadref[8];
#define BUF_THREAD_ID_SIZE 16
#endif
-/* Return addr as a real volatile address */
-static inline unsigned int ctrl_inl(const unsigned long addr)
-{
- return *(volatile unsigned long *) addr;
-}
-
-/* Correctly set *addr using volatile */
-static inline void ctrl_outl(const unsigned int b, unsigned long addr)
-{
- *(volatile unsigned long *) addr = b;
-}
-
-/* Get high hex bits */
-static char highhex(const int x)
-{
- return hexchars[(x >> 4) & 0xf];
-}
-
-/* Get low hex bits */
-static char lowhex(const int x)
-{
- return hexchars[x & 0xf];
-}
/* Convert ch to hex */
static int hex(const char ch)
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 6bcd8d92399..08587cdb64d 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -29,12 +29,6 @@ extern const unsigned char relocate_new_kernel[];
extern const unsigned int relocate_new_kernel_size;
extern void *gdb_vbr_vector;
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-void *crash_notes = NULL;
-
void machine_shutdown(void)
{
}
diff --git a/arch/sh/kernel/pm.c b/arch/sh/kernel/pm.c
new file mode 100644
index 00000000000..10ab62c9aed
--- /dev/null
+++ b/arch/sh/kernel/pm.c
@@ -0,0 +1,88 @@
+/*
+ * Generic Power Management Routine
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/suspend.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+#include <asm/watchdog.h>
+#include <asm/pm.h>
+
+#define INTR_OFFSET 0x600
+
+#define STBCR 0xffffff82
+#define STBCR2 0xffffff88
+
+#define STBCR_STBY 0x80
+#define STBCR_MSTP2 0x04
+
+#define MCR 0xffffff68
+#define RTCNT 0xffffff70
+
+#define MCR_RMODE 2
+#define MCR_RFSH 4
+
+void pm_enter(void)
+{
+ u8 stbcr, csr;
+ u16 frqcr, mcr;
+ u32 vbr_new, vbr_old;
+
+ set_bl_bit();
+
+ /* set wdt */
+ csr = sh_wdt_read_csr();
+ csr &= ~WTCSR_TME;
+ csr |= WTCSR_CKS_4096;
+ sh_wdt_write_csr(csr);
+ csr = sh_wdt_read_csr();
+ sh_wdt_write_cnt(0);
+
+ /* disable PLL1 */
+ frqcr = ctrl_inw(FRQCR);
+ frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
+ ctrl_outw(frqcr, FRQCR);
+
+ /* enable standby */
+ stbcr = ctrl_inb(STBCR);
+ ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
+
+ /* set self-refresh */
+ mcr = ctrl_inw(MCR);
+ ctrl_outw(mcr & ~MCR_RFSH, MCR);
+
+ /* set interrupt handler */
+ asm volatile("stc vbr, %0" : "=r" (vbr_old));
+ vbr_new = get_zeroed_page(GFP_ATOMIC);
+ udelay(50);
+ memcpy((void*)(vbr_new + INTR_OFFSET),
+ &wakeup_start, &wakeup_end - &wakeup_start);
+ asm volatile("ldc %0, vbr" : : "r" (vbr_new));
+
+ ctrl_outw(0, RTCNT);
+ ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR);
+
+ cpu_sleep();
+
+ asm volatile("ldc %0, vbr" : : "r" (vbr_old));
+
+ free_page(vbr_new);
+
+ /* enable PLL1 */
+ frqcr = ctrl_inw(FRQCR);
+ frqcr |= FRQCR_PSTBY;
+ ctrl_outw(frqcr, FRQCR);
+ udelay(50);
+ frqcr |= FRQCR_PLLEN;
+ ctrl_outw(frqcr, FRQCR);
+
+ ctrl_outb(stbcr, STBCR);
+
+ clear_bl_bit();
+}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index f2031314cb2..0b1d5dd7a93 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -81,16 +81,6 @@ void cpu_idle(void)
void machine_restart(char * __unused)
{
-
-#ifdef CONFIG_KEXEC
- struct kimage *image;
- image = xchg(&kexec_image, 0);
- if (image) {
- machine_shutdown();
- machine_kexec(image);
- }
-#endif
-
/* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
asm volatile("ldc %0, sr\n\t"
"mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
@@ -263,6 +253,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
+ struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs;
#if defined(CONFIG_SH_FPU)
struct task_struct *tsk = current;
@@ -277,8 +268,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if (user_mode(regs)) {
childregs->regs[15] = usp;
+ ti->addr_limit = USER_DS;
} else {
childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+ ti->addr_limit = KERNEL_DS;
}
if (clone_flags & CLONE_SETTLS) {
childregs->gbr = childregs->regs[0];
@@ -299,13 +292,15 @@ ubc_set_tracing(int asid, unsigned long pc)
{
ctrl_outl(pc, UBC_BARA);
+#ifdef CONFIG_MMU
/* We don't have any ASID settings for the SH-2! */
if (cpu_data->type != CPU_SH7604)
ctrl_outb(asid, UBC_BASRA);
+#endif
ctrl_outl(0, UBC_BAMRA);
- if (cpu_data->type == CPU_SH7729) {
+ if (cpu_data->type == CPU_SH7729 || cpu_data->type == CPU_SH7710) {
ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
} else {
@@ -344,6 +339,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
}
#endif
+#ifdef CONFIG_MMU
/*
* Restore the kernel mode register
* k7 (r7_bank1)
@@ -351,19 +347,21 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
asm volatile("ldc %0, r7_bank"
: /* no output */
: "r" (task_thread_info(next)));
+#endif
-#ifdef CONFIG_MMU
/* If no tasks are using the UBC, we're done */
if (ubc_usercnt == 0)
/* If no tasks are using the UBC, we're done */;
else if (next->thread.ubc_pc && next->mm) {
- ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK,
- next->thread.ubc_pc);
+ int asid = 0;
+#ifdef CONFIG_MMU
+ asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;
+#endif
+ ubc_set_tracing(asid, next->thread.ubc_pc);
} else {
ctrl_outw(0, UBC_BBRA);
ctrl_outw(0, UBC_BBRB);
}
-#endif
return prev;
}
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index f7eebbde329..04ca13a041c 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -224,7 +224,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_SETDSPREGS: {
unsigned long dp;
- int i;
ret = -EIO;
dp = ((unsigned long) child) + THREAD_SIZE -
diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
index a3c24dcbf01..184119eeae5 100644
--- a/arch/sh/kernel/semaphore.c
+++ b/arch/sh/kernel/semaphore.c
@@ -14,7 +14,7 @@
#include <asm/semaphore.h>
#include <asm/semaphore-helper.h>
-spinlock_t semaphore_wake_lock;
+DEFINE_SPINLOCK(semaphore_wake_lock);
/*
* Semaphores are implemented using a two-way counter:
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index e75189cb1db..5f587332234 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -43,27 +43,14 @@ extern void * __rd_start, * __rd_end;
* The bigger value means no problem.
*/
struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+#ifdef CONFIG_VT
struct screen_info screen_info;
+#endif
#if defined(CONFIG_SH_UNKNOWN)
struct sh_machine_vector sh_mv;
#endif
-/* We need this to satisfy some external references. */
-struct screen_info screen_info = {
- 0, 25, /* orig-x, orig-y */
- 0, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 80, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 25, /* orig-video-lines */
- 0, /* orig-video-isVGA */
- 16 /* orig-video-points */
-};
-
-extern void platform_setup(void);
-extern char *get_system_type(void);
extern int root_mountflags;
#define MV_NAME_SIZE 32
@@ -90,29 +77,8 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name);
static char command_line[COMMAND_LINE_SIZE] = { 0, };
-struct resource standard_io_resources[] = {
- { "dma1", 0x00, 0x1f },
- { "pic1", 0x20, 0x3f },
- { "timer", 0x40, 0x5f },
- { "keyboard", 0x60, 0x6f },
- { "dma page reg", 0x80, 0x8f },
- { "pic2", 0xa0, 0xbf },
- { "dma2", 0xc0, 0xdf },
- { "fpu", 0xf0, 0xff }
-};
-
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
-/* System RAM - interrupted by the 640kB-1M hole */
-#define code_resource (ram_resources[3])
-#define data_resource (ram_resources[4])
-static struct resource ram_resources[] = {
- { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
- { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
- { "Video RAM area", 0x0a0000, 0x0bffff },
- { "Kernel code", 0x100000, 0 },
- { "Kernel data", 0, 0 }
-};
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
unsigned long memory_start, memory_end;
@@ -145,6 +111,24 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
memory_end = memory_start + mem_size;
}
}
+
+#ifdef CONFIG_EARLY_PRINTK
+ if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
+ char *ep_end;
+
+ if (to != command_line)
+ to--;
+
+ from += 12;
+ ep_end = strchr(from, ' ');
+
+ setup_early_printk(from);
+ printk("early console enabled\n");
+
+ from = ep_end;
+ }
+#endif
+
if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
char* mv_end;
char* mv_comma;
@@ -237,6 +221,9 @@ static int __init sh_mv_setup(char **cmdline_p)
__set_io_port_base(mv_io_base);
#endif
+ if (!sh_mv.mv_nr_irqs)
+ sh_mv.mv_nr_irqs = NR_IRQS;
+
return 0;
}
@@ -245,11 +232,6 @@ void __init setup_arch(char **cmdline_p)
unsigned long bootmap_size;
unsigned long start_pfn, max_pfn, max_low_pfn;
-#ifdef CONFIG_EARLY_PRINTK
- extern void enable_early_printk(void);
-
- enable_early_printk();
-#endif
#ifdef CONFIG_CMDLINE_BOOL
strcpy(COMMAND_LINE, CONFIG_CMDLINE);
#endif
@@ -368,14 +350,14 @@ void __init setup_arch(char **cmdline_p)
#endif
/* Perform the machine specific initialisation */
- platform_setup();
+ if (likely(sh_mv.mv_setup))
+ sh_mv.mv_setup(cmdline_p);
paging_init();
}
struct sh_machine_vector* __init get_mv_byname(const char* name)
{
- extern int strcasecmp(const char *, const char *);
extern long __machvec_start, __machvec_end;
struct sh_machine_vector *all_vecs =
(struct sh_machine_vector *)&__machvec_start;
@@ -410,25 +392,18 @@ static int __init topology_init(void)
subsys_initcall(topology_init);
static const char *cpu_name[] = {
- [CPU_SH7604] = "SH7604",
- [CPU_SH7705] = "SH7705",
- [CPU_SH7708] = "SH7708",
- [CPU_SH7729] = "SH7729",
- [CPU_SH7300] = "SH7300",
- [CPU_SH7750] = "SH7750",
- [CPU_SH7750S] = "SH7750S",
- [CPU_SH7750R] = "SH7750R",
- [CPU_SH7751] = "SH7751",
- [CPU_SH7751R] = "SH7751R",
- [CPU_SH7760] = "SH7760",
- [CPU_SH73180] = "SH73180",
- [CPU_ST40RA] = "ST40RA",
- [CPU_ST40GX1] = "ST40GX1",
- [CPU_SH4_202] = "SH4-202",
- [CPU_SH4_501] = "SH4-501",
- [CPU_SH7770] = "SH7770",
- [CPU_SH7780] = "SH7780",
- [CPU_SH7781] = "SH7781",
+ [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
+ [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
+ [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
+ [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710",
+ [CPU_SH7729] = "SH7729", [CPU_SH7750] = "SH7750",
+ [CPU_SH7750S] = "SH7750S", [CPU_SH7750R] = "SH7750R",
+ [CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R",
+ [CPU_SH7760] = "SH7760", [CPU_SH73180] = "SH73180",
+ [CPU_ST40RA] = "ST40RA", [CPU_ST40GX1] = "ST40GX1",
+ [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
+ [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
+ [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH_NONE] = "Unknown"
};
@@ -438,8 +413,10 @@ const char *get_cpu_subtype(void)
}
#ifdef CONFIG_PROC_FS
+/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
static const char *cpu_flags[] = {
- "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL
+ "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+ "ptea", "llsc", "l2", NULL
};
static void show_cpuflags(struct seq_file *m)
@@ -460,7 +437,8 @@ static void show_cpuflags(struct seq_file *m)
seq_printf(m, "\n");
}
-static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_info info)
+static void show_cacheinfo(struct seq_file *m, const char *type,
+ struct cache_info info)
{
unsigned int cache_size;
@@ -493,7 +471,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
* unified cache on the SH-2 and SH-3, as well as the harvard
* style cache on the SH-4.
*/
- if (test_bit(SH_CACHE_COMBINED, &(boot_cpu_data.icache.flags))) {
+ if (boot_cpu_data.icache.flags & SH_CACHE_COMBINED) {
seq_printf(m, "unified\n");
show_cacheinfo(m, "cache", boot_cpu_data.icache);
} else {
@@ -502,6 +480,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
}
+ /* Optional secondary cache */
+ if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
+ show_cacheinfo(m, "scache", boot_cpu_data.scache);
+
seq_printf(m, "bogomips\t: %lu.%02lu\n",
boot_cpu_data.loops_per_jiffy/(500000/HZ),
(boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
@@ -617,4 +599,3 @@ static int __init kgdb_parse_options(char *options)
}
__setup("kgdb=", kgdb_parse_options);
#endif /* CONFIG_SH_KGDB */
-
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 245ed8f945e..d3cbfa2ad4a 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -27,21 +27,11 @@ EXPORT_SYMBOL(sh_mv);
/* platform dependent support */
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(probe_irq_mask);
EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(no_irq_type);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
/* PCI exports */
#ifdef CONFIG_PCI
@@ -52,13 +42,8 @@ EXPORT_SYMBOL(pci_free_consistent);
/* mem exports */
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memcpy_fromio);
-EXPORT_SYMBOL(memcpy_toio);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memset_io);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(__copy_user);
EXPORT_SYMBOL(boot_cpu_data);
@@ -94,7 +79,9 @@ EXPORT_SYMBOL(strcpy);
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);
DECLARE_EXPORT(__movstrSI12_i4);
+#endif
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
/* needed by some modules */
EXPORT_SYMBOL(flush_cache_all);
EXPORT_SYMBOL(flush_cache_range);
@@ -102,11 +89,9 @@ EXPORT_SYMBOL(flush_dcache_page);
EXPORT_SYMBOL(__flush_purge_region);
#endif
-#if defined(CONFIG_SH7705_CACHE_32KB)
-EXPORT_SYMBOL(flush_cache_all);
-EXPORT_SYMBOL(flush_cache_range);
-EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(__flush_purge_region);
+#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \
+ defined(CONFIG_SH7705_CACHE_32KB))
+EXPORT_SYMBOL(clear_user_page);
#endif
EXPORT_SYMBOL(flush_tlb_page);
@@ -116,7 +101,12 @@ EXPORT_SYMBOL(__down_trylock);
EXPORT_SYMBOL(synchronize_irq);
#endif
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(pm_suspend);
+#endif
+
EXPORT_SYMBOL(csum_partial);
+#ifdef CONFIG_IPV6
EXPORT_SYMBOL(csum_ipv6_magic);
-EXPORT_SYMBOL(consistent_sync);
+#endif
EXPORT_SYMBOL(clear_page);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index b475c4d2405..5213f5bc6ce 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -8,7 +8,6 @@
* SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
*
*/
-
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -21,6 +20,7 @@
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/tty.h>
+#include <linux/elf.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
@@ -29,12 +29,8 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
@@ -43,51 +39,17 @@ sys_sigsuspend(old_sigset_t mask,
unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs.regs[0] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
- unsigned long r6, unsigned long r7,
- struct pt_regs regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs.regs[0] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&regs, &saveset))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage int
@@ -348,7 +310,12 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
return (void __user *)((sp - frame_size) & -8ul);
}
-static void setup_frame(int sig, struct k_sigaction *ka,
+/* These symbols are defined with the addresses in the vsyscall page.
+ See vsyscall-trapa.S. */
+extern void __user __kernel_sigreturn;
+extern void __user __kernel_rt_sigreturn;
+
+static int setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
struct sigframe __user *frame;
@@ -368,15 +335,18 @@ static void setup_frame(int sig, struct k_sigaction *ka,
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
- if (_NSIG_WORDS > 1) {
+ if (_NSIG_WORDS > 1)
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
- }
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+ } else if (likely(current->mm->context.vdso)) {
+ regs->pr = VDSO_SYM(&__kernel_sigreturn);
+#endif
} else {
/* Generate return code (system call to sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -402,21 +372,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
set_fs(USER_DS);
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
- current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+ pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+ current->comm, current->pid, frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
+
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
- return;
+
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
@@ -452,6 +423,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+ } else if (likely(current->mm->context.vdso)) {
+ regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
+#endif
} else {
/* Generate return code (system call to rt_sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -477,28 +452,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
set_fs(USER_DS);
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
- current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+ pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+ current->comm, current->pid, frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
+
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
- return;
+
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
-static void
+static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
+ int ret;
+
/* Are we from a system call? */
if (regs->tra >= 0) {
/* If so, check system call restarting.. */
@@ -539,19 +517,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ return ret;
}
/*
@@ -563,11 +545,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs, unsigned int save_r0)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
+ sigset_t *oldset;
/*
* We want the common case to go fast, which
@@ -576,19 +559,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* if so.
*/
if (!user_mode(regs))
- return 1;
+ return;
if (try_to_freeze())
goto no_signal;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, oldset, regs);
- return 1;
+ if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
}
no_signal:
@@ -597,10 +588,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* Restart the system call - no handlers present */
if (regs->regs[0] == -ERESTARTNOHAND ||
regs->regs[0] == -ERESTARTSYS ||
- regs->regs[0] == -ERESTARTNOINTR ||
- regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+ regs->regs[0] == -ERESTARTNOINTR) {
+ regs->regs[0] = save_r0;
+ regs->pc -= 2;
+ } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
regs->pc -= 2;
+ regs->regs[3] = __NR_restart_syscall;
}
}
- return 0;
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
+ __u32 thread_info_flags)
+{
+ /* deal with pending signal delivery */
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs, save_r0);
}
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 917b2f32f26..b68ff705f06 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -21,7 +21,8 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
-
+#include <linux/module.h>
+#include <asm/cacheflush.h>
#include <asm/uaccess.h>
#include <asm/ipc.h>
@@ -44,11 +45,16 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
return error;
}
-#if defined(HAVE_ARCH_UNMAPPED_AREA)
+unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
+
+EXPORT_SYMBOL(shm_align_mask);
+
/*
- * To avoid cache alias, we map the shard page with same color.
+ * To avoid cache aliases, we map the shared page with same color.
*/
-#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+#define COLOUR_ALIGN(addr, pgoff) \
+ ((((addr) + shm_align_mask) & ~shm_align_mask) + \
+ (((pgoff) << PAGE_SHIFT) & shm_align_mask))
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -56,43 +62,52 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned long start_addr;
+ int do_colour_align;
if (flags & MAP_FIXED) {
/* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
*/
- if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+ if ((flags & MAP_SHARED) && (addr & shm_align_mask))
return -EINVAL;
return addr;
}
- if (len > TASK_SIZE)
+ if (unlikely(len > TASK_SIZE))
return -ENOMEM;
+ do_colour_align = 0;
+ if (filp || (flags & MAP_SHARED))
+ do_colour_align = 1;
+
if (addr) {
- if (flags & MAP_PRIVATE)
- addr = PAGE_ALIGN(addr);
+ if (do_colour_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
else
- addr = COLOUR_ALIGN(addr);
+ addr = PAGE_ALIGN(addr);
+
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start))
return addr;
}
- if (len <= mm->cached_hole_size) {
+
+ if (len > mm->cached_hole_size) {
+ start_addr = addr = mm->free_area_cache;
+ } else {
mm->cached_hole_size = 0;
- mm->free_area_cache = TASK_UNMAPPED_BASE;
+ start_addr = addr = TASK_UNMAPPED_BASE;
}
- if (flags & MAP_PRIVATE)
- addr = PAGE_ALIGN(mm->free_area_cache);
- else
- addr = COLOUR_ALIGN(mm->free_area_cache);
- start_addr = addr;
full_search:
+ if (do_colour_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(mm->free_area_cache);
+
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
- if (TASK_SIZE - len < addr) {
+ if (unlikely(TASK_SIZE - len < addr)) {
/*
* Start a new search - just in case we missed
* some holes.
@@ -104,7 +119,7 @@ full_search:
}
return -ENOMEM;
}
- if (!vma || addr + len <= vma->vm_start) {
+ if (likely(!vma || addr + len <= vma->vm_start)) {
/*
* Remember the place where we stopped the search:
*/
@@ -115,11 +130,10 @@ full_search:
mm->cached_hole_size = vma->vm_start - addr;
addr = vma->vm_end;
- if (!(flags & MAP_PRIVATE))
- addr = COLOUR_ALIGN(addr);
+ if (do_colour_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
}
}
-#endif
static inline long
do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
new file mode 100644
index 00000000000..768334e9507
--- /dev/null
+++ b/arch/sh/kernel/syscalls.S
@@ -0,0 +1,353 @@
+/*
+ * arch/sh/kernel/syscalls.S
+ *
+ * System call table for SuperH
+ *
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise sys_ni_syscall
+#define sys_readahead sys_ni_syscall
+#define sys_mprotect sys_ni_syscall
+#define sys_msync sys_ni_syscall
+#define sys_mlock sys_ni_syscall
+#define sys_munlock sys_ni_syscall
+#define sys_mlockall sys_ni_syscall
+#define sys_munlockall sys_ni_syscall
+#define sys_mremap sys_ni_syscall
+#define sys_mincore sys_ni_syscall
+#define sys_remap_file_pages sys_ni_syscall
+#endif
+
+ .data
+ENTRY(sys_call_table)
+ .long sys_restart_syscall /* 0 - old "setup()" system call*/
+ .long sys_exit
+ .long sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_lchown16
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_stat
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid16
+ .long sys_getuid16
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_fstat
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid16
+ .long sys_getgid16
+ .long sys_signal
+ .long sys_geteuid16
+ .long sys_getegid16 /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_ni_syscall /* sys_olduname */
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid16 /* 70 */
+ .long sys_setregid16
+ .long sys_sigsuspend
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_old_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups16 /* 80 */
+ .long sys_setgroups16
+ .long sys_ni_syscall /* sys_oldselect */
+ .long sys_symlink
+ .long sys_lstat
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_swapon
+ .long sys_reboot
+ .long old_readdir
+ .long old_mmap /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown16 /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall /* ioperm */
+ .long sys_socketcall
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_uname
+ .long sys_ni_syscall /* 110 */ /* iopl */
+ .long sys_vhangup
+ .long sys_ni_syscall /* idle */
+ .long sys_ni_syscall /* vm86old */
+ .long sys_wait4
+ .long sys_swapoff /* 115 */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn
+ .long sys_clone /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_ni_syscall /* sys_modify_ldt */
+ .long sys_adjtimex
+ .long sys_mprotect /* 125 */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old "create_module" */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* for afs_syscall */
+ .long sys_setfsuid16
+ .long sys_setfsgid16
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long sys_select
+ .long sys_flock
+ .long sys_msync
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_mremap
+ .long sys_setresuid16
+ .long sys_getresuid16 /* 165 */
+ .long sys_ni_syscall /* vm86 */
+ .long sys_ni_syscall /* old "query_module" */
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_setresgid16 /* 170 */
+ .long sys_getresgid16
+ .long sys_prctl
+ .long sys_rt_sigreturn
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask /* 175 */
+ .long sys_rt_sigpending
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long sys_rt_sigsuspend
+ .long sys_pread_wrapper /* 180 */
+ .long sys_pwrite_wrapper
+ .long sys_chown16
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset /* 185 */
+ .long sys_sigaltstack
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
+ .long sys_vfork /* 190 */
+ .long sys_getrlimit
+ .long sys_mmap2
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_lchown
+ .long sys_getuid
+ .long sys_getgid /* 200 */
+ .long sys_geteuid
+ .long sys_getegid
+ .long sys_setreuid
+ .long sys_setregid
+ .long sys_getgroups /* 205 */
+ .long sys_setgroups
+ .long sys_fchown
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setresgid /* 210 */
+ .long sys_getresgid
+ .long sys_chown
+ .long sys_setuid
+ .long sys_setgid
+ .long sys_setfsuid /* 215 */
+ .long sys_setfsgid
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64 /* 220 */
+ .long sys_fcntl64
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_ni_syscall /* Reserved for Security */
+ .long sys_gettid
+ .long sys_readahead /* 225 */
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr /* 230 */
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr /* 235 */
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill
+ .long sys_sendfile64
+ .long sys_futex /* 240 */
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall
+ .long sys_ni_syscall
+ .long sys_io_setup /* 245 */
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel
+ .long sys_fadvise64 /* 250 */
+ .long sys_ni_syscall
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
+ .long sys_fadvise64_64_wrapper
+ .long sys_ni_syscall /* Reserved for vserver */
+ .long sys_ni_syscall /* Reserved for mbind */
+ .long sys_ni_syscall /* 275 - get_mempolicy */
+ .long sys_ni_syscall /* set_mempolicy */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 280 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_kexec_load
+ .long sys_waitid
+ .long sys_ni_syscall /* 285 */
+ .long sys_add_key
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get /* 290 */
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_migrate_pages
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64 /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index a1589f85499..149d9713edd 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -3,13 +3,12 @@
*
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
+ * Copyright (C) 2002 - 2006 Paul Mundt
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
*
* Some code taken from i386 version.
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -26,15 +25,20 @@ struct sys_timer *sys_timer;
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
-/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want
- * these routines anywhere... */
-#ifdef CONFIG_SH_RTC
-void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday;
-int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday;
-#else
-void (*rtc_get_time)(struct timespec *);
-int (*rtc_set_time)(const time_t);
-#endif
+/* Dummy RTC ops */
+static void null_rtc_get_time(struct timespec *tv)
+{
+ tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+ tv->tv_nsec = 0;
+}
+
+static int null_rtc_set_time(const time_t secs)
+{
+ return 0;
+}
+
+void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
+int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
/*
* Scheduler clock - returns current time in nanosec units.
@@ -70,7 +74,6 @@ void do_gettimeofday(struct timeval *tv)
tv->tv_sec = sec;
tv->tv_usec = usec;
}
-
EXPORT_SYMBOL(do_gettimeofday);
int do_settimeofday(struct timespec *tv)
@@ -103,7 +106,6 @@ int do_settimeofday(struct timespec *tv)
return 0;
}
-
EXPORT_SYMBOL(do_settimeofday);
/* last time the RTC clock got updated */
@@ -135,7 +137,7 @@ void handle_timer_tick(struct pt_regs *regs)
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_set_time(xtime.tv_sec) == 0)
+ if (rtc_sh_set_time(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
/* do it again in 60s */
@@ -143,8 +145,33 @@ void handle_timer_tick(struct pt_regs *regs)
}
}
+#ifdef CONFIG_PM
+int timer_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+ sys_timer->ops->stop();
+
+ return 0;
+}
+
+int timer_resume(struct sys_device *dev)
+{
+ struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+ sys_timer->ops->start();
+
+ return 0;
+}
+#else
+#define timer_suspend NULL
+#define timer_resume NULL
+#endif
+
static struct sysdev_class timer_sysclass = {
set_kset_name("timer"),
+ .suspend = timer_suspend,
+ .resume = timer_resume,
};
static int __init timer_init_sysfs(void)
@@ -156,7 +183,6 @@ static int __init timer_init_sysfs(void)
sys_timer->dev.cls = &timer_sysclass;
return sysdev_register(&sys_timer->dev);
}
-
device_initcall(timer_init_sysfs);
void (*board_time_init)(void);
@@ -168,15 +194,9 @@ void __init time_init(void)
clk_init();
- if (rtc_get_time) {
- rtc_get_time(&xtime);
- } else {
- xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0);
- xtime.tv_nsec = 0;
- }
-
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
+ rtc_sh_get_time(&xtime);
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
/*
* Find the timer to use as the system timer, it will be
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index d4212add53b..205816fcf0d 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -132,17 +132,17 @@ static unsigned long tmu_timer_get_frequency(void)
ctrl_outl(0xffffffff, TMU0_TCOR);
ctrl_outl(0xffffffff, TMU0_TCNT);
- rtc_get_time(&ts2);
+ rtc_sh_get_time(&ts2);
do {
- rtc_get_time(&ts1);
+ rtc_sh_get_time(&ts1);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
/* actually start the timer */
ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
do {
- rtc_get_time(&ts2);
+ rtc_sh_get_time(&ts2);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
@@ -188,6 +188,18 @@ static struct clk tmu0_clk = {
.ops = &tmu_clk_ops,
};
+static int tmu_timer_start(void)
+{
+ ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+ return 0;
+}
+
+static int tmu_timer_stop(void)
+{
+ ctrl_outb(0, TMU_TSTR);
+ return 0;
+}
+
static int tmu_timer_init(void)
{
unsigned long interval;
@@ -197,7 +209,7 @@ static int tmu_timer_init(void)
tmu0_clk.parent = clk_get("module_clk");
/* Start TMU0 */
- ctrl_outb(0, TMU_TSTR);
+ tmu_timer_stop();
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
#endif
@@ -211,13 +223,15 @@ static int tmu_timer_init(void)
ctrl_outl(interval, TMU0_TCOR);
ctrl_outl(interval, TMU0_TCNT);
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+ tmu_timer_start();
return 0;
}
struct sys_timer_ops tmu_timer_ops = {
.init = tmu_timer_init,
+ .start = tmu_timer_start,
+ .stop = tmu_timer_stop,
.get_frequency = tmu_timer_get_frequency,
.get_offset = tmu_timer_get_offset,
};
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index d9db1180f77..c2c597e0948 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -36,40 +36,15 @@
#ifdef CONFIG_SH_KGDB
#include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs) \
-{ \
- if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
- { \
- (*kgdb_debug_hook)(regs); \
- } \
+#define CHK_REMOTE_DEBUG(regs) \
+{ \
+ if (kgdb_debug_hook && !user_mode(regs))\
+ (*kgdb_debug_hook)(regs); \
}
#else
#define CHK_REMOTE_DEBUG(regs)
#endif
-#define DO_ERROR(trapnr, signr, str, name, tsk) \
-asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
- unsigned long r6, unsigned long r7, \
- struct pt_regs regs) \
-{ \
- unsigned long error_code; \
- \
- /* Check if it's a DSP instruction */ \
- if (is_dsp_inst(&regs)) { \
- /* Enable DSP mode, and restart instruction. */ \
- regs.sr |= SR_DSP; \
- return; \
- } \
- \
- asm volatile("stc r2_bank, %0": "=r" (error_code)); \
- local_irq_enable(); \
- tsk->thread.error_code = error_code; \
- tsk->thread.trap_no = trapnr; \
- CHK_REMOTE_DEBUG(&regs); \
- force_sig(signr, tsk); \
- die_if_no_fixup(str,&regs,error_code); \
-}
-
#ifdef CONFIG_CPU_SH2
#define TRAP_RESERVED_INST 4
#define TRAP_ILLEGAL_SLOT_INST 6
@@ -86,7 +61,7 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)
-spinlock_t die_lock;
+DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * regs, long err)
{
@@ -575,8 +550,117 @@ int is_dsp_inst(struct pt_regs *regs)
#define is_dsp_inst(regs) (0)
#endif /* CONFIG_SH_DSP */
-DO_ERROR(TRAP_RESERVED_INST, SIGILL, "reserved instruction", reserved_inst, current)
-DO_ERROR(TRAP_ILLEGAL_SLOT_INST, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
+extern int do_fpu_inst(unsigned short, struct pt_regs*);
+
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ unsigned long error_code;
+ struct task_struct *tsk = current;
+
+#ifdef CONFIG_SH_FPU_EMU
+ unsigned short inst;
+ int err;
+
+ get_user(inst, (unsigned short*)regs.pc);
+
+ err = do_fpu_inst(inst, &regs);
+ if (!err) {
+ regs.pc += 2;
+ return;
+ }
+ /* not a FPU inst. */
+#endif
+
+#ifdef CONFIG_SH_DSP
+ /* Check if it's a DSP instruction */
+ if (is_dsp_inst(&regs)) {
+ /* Enable DSP mode, and restart instruction. */
+ regs.sr |= SR_DSP;
+ return;
+ }
+#endif
+
+ asm volatile("stc r2_bank, %0": "=r" (error_code));
+ local_irq_enable();
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = TRAP_RESERVED_INST;
+ CHK_REMOTE_DEBUG(&regs);
+ force_sig(SIGILL, tsk);
+ die_if_no_fixup("reserved instruction", &regs, error_code);
+}
+
+#ifdef CONFIG_SH_FPU_EMU
+static int emulate_branch(unsigned short inst, struct pt_regs* regs)
+{
+ /*
+ * bfs: 8fxx: PC+=d*2+4;
+ * bts: 8dxx: PC+=d*2+4;
+ * bra: axxx: PC+=D*2+4;
+ * bsr: bxxx: PC+=D*2+4 after PR=PC+4;
+ * braf:0x23: PC+=Rn*2+4;
+ * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4;
+ * jmp: 4x2b: PC=Rn;
+ * jsr: 4x0b: PC=Rn after PR=PC+4;
+ * rts: 000b: PC=PR;
+ */
+ if ((inst & 0xfd00) == 0x8d00) {
+ regs->pc += SH_PC_8BIT_OFFSET(inst);
+ return 0;
+ }
+
+ if ((inst & 0xe000) == 0xa000) {
+ regs->pc += SH_PC_12BIT_OFFSET(inst);
+ return 0;
+ }
+
+ if ((inst & 0xf0df) == 0x0003) {
+ regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4;
+ return 0;
+ }
+
+ if ((inst & 0xf0df) == 0x400b) {
+ regs->pc = regs->regs[(inst & 0x0f00) >> 8];
+ return 0;
+ }
+
+ if ((inst & 0xffff) == 0x000b) {
+ regs->pc = regs->pr;
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ unsigned long error_code;
+ struct task_struct *tsk = current;
+#ifdef CONFIG_SH_FPU_EMU
+ unsigned short inst;
+
+ get_user(inst, (unsigned short *)regs.pc + 1);
+ if (!do_fpu_inst(inst, &regs)) {
+ get_user(inst, (unsigned short *)regs.pc);
+ if (!emulate_branch(inst, &regs))
+ return;
+ /* fault in branch.*/
+ }
+ /* not a FPU inst. */
+#endif
+
+ asm volatile("stc r2_bank, %0": "=r" (error_code));
+ local_irq_enable();
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = TRAP_RESERVED_INST;
+ CHK_REMOTE_DEBUG(&regs);
+ force_sig(SIGILL, tsk);
+ die_if_no_fixup("illegal slot instruction", &regs, error_code);
+}
asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
@@ -634,14 +718,16 @@ void __init trap_init(void)
exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
= (void *)do_illegal_slot_inst;
-#ifdef CONFIG_CPU_SH4
- if (!(cpu_data->flags & CPU_HAS_FPU)) {
- /* For SH-4 lacking an FPU, treat floating point instructions
- as reserved. */
- /* entry 64 corresponds to EXPEVT=0x800 */
- exception_handling_table[64] = (void *)do_reserved_inst;
- exception_handling_table[65] = (void *)do_illegal_slot_inst;
- }
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
+ defined(CONFIG_SH_FPU_EMU)
+ /*
+ * For SH-4 lacking an FPU, treat floating point instructions as
+ * reserved. They'll be handled in the math-emu case, or faulted on
+ * otherwise.
+ */
+ /* entry 64 corresponds to EXPEVT=0x800 */
+ exception_handling_table[64] = (void *)do_reserved_inst;
+ exception_handling_table[65] = (void *)do_illegal_slot_inst;
#endif
/* Setup VBR for boot cpu */
@@ -655,20 +741,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
unsigned long module_end = VMALLOC_END;
int i = 1;
- if (tsk && !sp) {
+ if (!tsk)
+ tsk = current;
+ if (tsk == current)
+ sp = (unsigned long *)current_stack_pointer;
+ else
sp = (unsigned long *)tsk->thread.sp;
- }
-
- if (!sp) {
- __asm__ __volatile__ (
- "mov r15, %0\n\t"
- "stc r7_bank, %1\n\t"
- : "=r" (module_start),
- "=r" (module_end)
- );
-
- sp = (unsigned long *)module_start;
- }
stack = sp;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 95fdd9135fc..5eb93091818 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -2,6 +2,7 @@
* ld script to make SuperH Linux kernel
* Written by Niibe Yutaka
*/
+#include <asm/thread_info.h>
#include <asm-generic/vmlinux.lds.h>
#ifdef CONFIG_CPU_LITTLE_ENDIAN
@@ -13,7 +14,7 @@ OUTPUT_ARCH(sh)
ENTRY(_start)
SECTIONS
{
- . = 0x80000000 + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+ . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
_text = .; /* Text and read-only data */
text = .; /* Text and read-only data */
.empty_zero_page : {
@@ -40,16 +41,16 @@ SECTIONS
*(.data)
/* Align the initial ramdisk image (INITRD) on page boundaries. */
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__rd_start = .;
*(.initrd)
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__rd_end = .;
CONSTRUCTORS
}
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.data.page_aligned : { *(.data.idt) }
. = ALIGN(32);
@@ -60,12 +61,10 @@ SECTIONS
_edata = .; /* End of data section */
- . = ALIGN(8192); /* init_task */
+ . = ALIGN(THREAD_SIZE); /* init_task */
.data.init_task : { *(.data.init_task) }
- /* stack */
- .stack : { stack = .; _stack = .; }
- . = ALIGN(4096); /* Init code and data */
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .;
_sinittext = .;
.init.text : { *(.init.text) }
@@ -96,7 +95,7 @@ SECTIONS
__machvec_start = .;
.init.machvec : { *(.init.machvec) }
__machvec_end = .;
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__init_end = .;
. = ALIGN(4);
diff --git a/arch/sh/kernel/vsyscall/Makefile b/arch/sh/kernel/vsyscall/Makefile
new file mode 100644
index 00000000000..4bbce1cfa35
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/Makefile
@@ -0,0 +1,36 @@
+obj-y += vsyscall.o vsyscall-syscall.o
+
+$(obj)/vsyscall-syscall.o: \
+ $(foreach F,trapa,$(obj)/vsyscall-$F.so)
+
+# Teach kbuild about targets
+targets += $(foreach F,trapa,vsyscall-$F.o vsyscall-$F.so)
+targets += vsyscall-note.o vsyscall.lds
+
+# The DSO images are built using a special linker script
+quiet_cmd_syscall = SYSCALL $@
+ cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
+ -Wl,-T,$(filter-out FORCE,$^) -o $@
+
+export CPPFLAGS_vsyscall.lds += -P -C -Ush
+
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+SYSCFLAGS_vsyscall-trapa.so = $(vsyscall-flags)
+
+$(obj)/vsyscall-trapa.so: \
+$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+ $(call if_changed,syscall)
+
+# We also create a special relocatable object that should mirror the symbol
+# table and layout of the linked DSO. With ld -R we can then refer to
+# these symbols in the kernel code rather than hand-coded addresses.
+extra-y += vsyscall-syms.o
+$(obj)/built-in.o: $(obj)/vsyscall-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
+
+SYSCFLAGS_vsyscall-syms.o = -r
+$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
+ $(obj)/vsyscall-trapa.o $(obj)/vsyscall-note.o FORCE
+ $(call if_changed,syscall)
diff --git a/arch/sh/kernel/vsyscall/vsyscall-note.S b/arch/sh/kernel/vsyscall/vsyscall-note.S
new file mode 100644
index 00000000000..d4b5be4f3d5
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall-note.S
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \
+ .section name, flags; \
+ .balign 4; \
+ .long 1f - 0f; /* name length */ \
+ .long 3f - 2f; /* data length */ \
+ .long type; /* note type */ \
+0: .asciz vendor; /* vendor name */ \
+1: .balign 4; \
+2:
+
+#define ASM_ELF_NOTE_END \
+3: .balign 4; /* pad out section */ \
+ .previous
+
+ ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+ .long LINUX_VERSION_CODE
+ ASM_ELF_NOTE_END
diff --git a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
new file mode 100644
index 00000000000..555a64f124c
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
@@ -0,0 +1,39 @@
+#include <asm/unistd.h>
+
+ .text
+ .balign 32
+ .globl __kernel_sigreturn
+ .type __kernel_sigreturn,@function
+__kernel_sigreturn:
+.LSTART_sigreturn:
+ mov.w 1f, r3
+ trapa #0x10
+ or r0, r0
+ or r0, r0
+ or r0, r0
+ or r0, r0
+ or r0, r0
+
+1: .short __NR_sigreturn
+.LEND_sigreturn:
+ .size __kernel_sigreturn,.-.LSTART_sigreturn
+
+ .balign 32
+ .globl __kernel_rt_sigreturn
+ .type __kernel_rt_sigreturn,@function
+__kernel_rt_sigreturn:
+.LSTART_rt_sigreturn:
+ mov.w 1f, r3
+ trapa #0x10
+ or r0, r0
+ or r0, r0
+ or r0, r0
+ or r0, r0
+ or r0, r0
+
+1: .short __NR_rt_sigreturn
+.LEND_rt_sigreturn:
+ .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+
+ .section .eh_frame,"a",@progbits
+ .previous
diff --git a/arch/sh/kernel/vsyscall/vsyscall-syscall.S b/arch/sh/kernel/vsyscall/vsyscall-syscall.S
new file mode 100644
index 00000000000..c2ac7f0282b
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall-syscall.S
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+ .globl vsyscall_trapa_start, vsyscall_trapa_end
+vsyscall_trapa_start:
+ .incbin "arch/sh/kernel/vsyscall/vsyscall-trapa.so"
+vsyscall_trapa_end:
+
+__FINIT
diff --git a/arch/sh/kernel/vsyscall/vsyscall-trapa.S b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
new file mode 100644
index 00000000000..3b6eb34c43f
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
@@ -0,0 +1,42 @@
+ .text
+ .globl __kernel_vsyscall
+ .type __kernel_vsyscall,@function
+__kernel_vsyscall:
+.LSTART_vsyscall:
+ /* XXX: We'll have to do something here once we opt to use the vDSO
+ * page for something other than the signal trampoline.. as well as
+ * fill out .eh_frame -- PFM. */
+.LEND_vsyscall:
+ .size __kernel_vsyscall,.-.LSTART_vsyscall
+ .previous
+
+ .section .eh_frame,"a",@progbits
+.LCIE:
+ .ualong .LCIE_end - .LCIE_start
+.LCIE_start:
+ .ualong 0 /* CIE ID */
+ .byte 0x1 /* Version number */
+ .string "zRS" /* NUL-terminated augmentation string */
+ .uleb128 0x1 /* Code alignment factor */
+ .sleb128 -4 /* Data alignment factor */
+ .byte 0x11 /* Return address register column */
+ /* Augmentation length and data (none) */
+ .byte 0xc /* DW_CFA_def_cfa */
+ .uleb128 0xf /* r15 */
+ .uleb128 0x0 /* offset 0 */
+
+ .align 2
+.LCIE_end:
+
+ .ualong .LFDE_end-.LFDE_start /* Length FDE */
+.LFDE_start:
+ .ualong .LCIE /* CIE pointer */
+ .ualong .LSTART_vsyscall-. /* start address */
+ .ualong .LEND_vsyscall-.LSTART_vsyscall
+ .uleb128 0
+ .align 2
+.LFDE_end:
+ .previous
+
+/* Get the common code for the sigreturn entry points */
+#include "vsyscall-sigreturn.S"
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
new file mode 100644
index 00000000000..075d6cc1a2d
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -0,0 +1,150 @@
+/*
+ * arch/sh/kernel/vsyscall.c
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * vDSO randomization
+ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/elf.h>
+
+/*
+ * Should the kernel map a VDSO page into processes and pass its
+ * address down to glibc upon exec()?
+ */
+unsigned int __read_mostly vdso_enabled = 1;
+EXPORT_SYMBOL_GPL(vdso_enabled);
+
+static int __init vdso_setup(char *s)
+{
+ vdso_enabled = simple_strtoul(s, NULL, 0);
+ return 1;
+}
+__setup("vdso=", vdso_setup);
+
+/*
+ * These symbols are defined by vsyscall.o to mark the bounds
+ * of the ELF DSO images included therein.
+ */
+extern const char vsyscall_trapa_start, vsyscall_trapa_end;
+static void *syscall_page;
+
+int __init vsyscall_init(void)
+{
+ syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+
+ /*
+ * XXX: Map this page to a fixmap entry if we get around
+ * to adding the page to ELF core dumps
+ */
+
+ memcpy(syscall_page,
+ &vsyscall_trapa_start,
+ &vsyscall_trapa_end - &vsyscall_trapa_start);
+
+ return 0;
+}
+
+static struct page *syscall_vma_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ unsigned long offset = address - vma->vm_start;
+ struct page *page;
+
+ if (address < vma->vm_start || address > vma->vm_end)
+ return NOPAGE_SIGBUS;
+
+ page = virt_to_page(syscall_page + offset);
+
+ get_page(page);
+
+ return page;
+}
+
+/* Prevent VMA merging */
+static void syscall_vma_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct syscall_vm_ops = {
+ .nopage = syscall_vma_nopage,
+ .close = syscall_vma_close,
+};
+
+/* Setup a VMA at program startup for the vsyscall page */
+int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int executable_stack)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ unsigned long addr;
+ int ret;
+
+ down_write(&mm->mmap_sem);
+ addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+ if (IS_ERR_VALUE(addr)) {
+ ret = addr;
+ goto up_fail;
+ }
+
+ vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+ if (!vma) {
+ ret = -ENOMEM;
+ goto up_fail;
+ }
+
+ vma->vm_start = addr;
+ vma->vm_end = addr + PAGE_SIZE;
+ /* MAYWRITE to allow gdb to COW and set breakpoints */
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+ vma->vm_flags |= mm->def_flags;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+ vma->vm_ops = &syscall_vm_ops;
+ vma->vm_mm = mm;
+
+ ret = insert_vm_struct(mm, vma);
+ if (unlikely(ret)) {
+ kmem_cache_free(vm_area_cachep, vma);
+ goto up_fail;
+ }
+
+ current->mm->context.vdso = (void *)addr;
+
+ mm->total_vm++;
+up_fail:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+ return "[vdso]";
+
+ return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *task)
+{
+ return NULL;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long address)
+{
+ return 0;
+}
+
+int in_gate_area_no_task(unsigned long address)
+{
+ return 0;
+}
diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S
new file mode 100644
index 00000000000..b13c3d439fe
--- /dev/null
+++ b/arch/sh/kernel/vsyscall/vsyscall.lds.S
@@ -0,0 +1,74 @@
+/*
+ * Linker script for vsyscall DSO. The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page). This script controls its layout.
+ */
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
+#else
+OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
+#endif
+OUTPUT_ARCH(sh)
+
+/* The ELF entry point can be used to set the AT_SYSINFO value. */
+ENTRY(__kernel_vsyscall);
+
+SECTIONS
+{
+ . = SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ /* This linker script is used both with -r and with -shared.
+ For the layouts to match, we need to skip more than enough
+ space for the dynamic symbol table et al. If this amount
+ is insufficient, ld -shared will barf. Just increase it here. */
+ . = 0x400;
+
+ .text : { *(.text) } :text =0x90909090
+ .note : { *(.note.*) } :text :note
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .useless : {
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ } :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_2.6 {
+ global:
+ __kernel_vsyscall;
+ __kernel_sigreturn;
+ __kernel_rt_sigreturn;
+
+ local: *;
+ };
+}
diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S
index 7c50dfe68c0..cbdd0d40e54 100644
--- a/arch/sh/lib/checksum.S
+++ b/arch/sh/lib/checksum.S
@@ -202,8 +202,9 @@ ENTRY(csum_partial_copy_generic)
cmp/pz r6 ! Jump if we had at least two bytes.
bt/s 1f
clrt
+ add #2,r6 ! r6 was < 2. Deal with it.
bra 4f
- add #2,r6 ! r6 was < 2. Deal with it.
+ mov r6,r2
3: ! Handle different src and dest alignments.
! This is not common, so simple byte by byte copy will do.
diff --git a/arch/sh/lib/memcpy-sh4.S b/arch/sh/lib/memcpy-sh4.S
index db6b736537a..560bc17eebd 100644
--- a/arch/sh/lib/memcpy-sh4.S
+++ b/arch/sh/lib/memcpy-sh4.S
@@ -727,8 +727,8 @@ ENTRY(memcpy)
mov.l @(0x04,r5), r11 ! 18 LS (latency=2)
xtrct r9, r8 ! 48 EX
- mov.w @(0x02,r5), r12 ! 18 LS (latency=2)
- xtrct r10, r9 ! 48 EX
+ mov.l @(0x00,r5), r12 ! 18 LS (latency=2)
+ xtrct r10, r9 ! 48 EX
movca.l r0,@r1 ! 40 LS (latency=3-7)
add #-0x1c, r1 ! 50 EX
diff --git a/arch/sh/lib/memset.S b/arch/sh/lib/memset.S
index 95670090680..af91fe2b72a 100644
--- a/arch/sh/lib/memset.S
+++ b/arch/sh/lib/memset.S
@@ -29,6 +29,7 @@ ENTRY(memset)
bf/s 1b
mov.b r5,@-r4
2: ! make VVVV
+ extu.b r5,r5
swap.b r5,r0 ! V0
or r0,r5 ! VV
swap.w r5,r0 ! VV00
diff --git a/arch/sh/math-emu/Makefile b/arch/sh/math-emu/Makefile
new file mode 100644
index 00000000000..638b342c781
--- /dev/null
+++ b/arch/sh/math-emu/Makefile
@@ -0,0 +1 @@
+obj-y := math.o
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
new file mode 100644
index 00000000000..26b6046814f
--- /dev/null
+++ b/arch/sh/math-emu/math.c
@@ -0,0 +1,624 @@
+/*
+ * arch/sh/math-emu/math.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII <takasi-y@ops.dti.ne.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#include "sfp-util.h"
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+#include <math-emu/double.h>
+
+#define FPUL (fregs->fpul)
+#define FPSCR (fregs->fpscr)
+#define FPSCR_RM (FPSCR&3)
+#define FPSCR_DN ((FPSCR>>18)&1)
+#define FPSCR_PR ((FPSCR>>19)&1)
+#define FPSCR_SZ ((FPSCR>>20)&1)
+#define FPSCR_FR ((FPSCR>>21)&1)
+#define FPSCR_MASK 0x003fffffUL
+
+#define BANK(n) (n^(FPSCR_FR?16:0))
+#define FR ((unsigned long*)(fregs->fp_regs))
+#define FR0 (FR[BANK(0)])
+#define FRn (FR[BANK(n)])
+#define FRm (FR[BANK(m)])
+#define DR ((unsigned long long*)(fregs->fp_regs))
+#define DRn (DR[BANK(n)/2])
+#define DRm (DR[BANK(m)/2])
+
+#define XREG(n) (n^16)
+#define XFn (FR[BANK(XREG(n))])
+#define XFm (FR[BANK(XREG(m))])
+#define XDn (DR[BANK(XREG(n))/2])
+#define XDm (DR[BANK(XREG(m))/2])
+
+#define R0 (regs->regs[0])
+#define Rn (regs->regs[n])
+#define Rm (regs->regs[m])
+
+#define WRITE(d,a) ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
+#define READ(d,a) ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
+
+#define PACK_S(r,f) FP_PACK_SP(&r,f)
+#define UNPACK_S(f,r) FP_UNPACK_SP(f,&r)
+#define PACK_D(r,f) \
+ {u32 t[2]; FP_PACK_DP(t,f); ((u32*)&r)[0]=t[1]; ((u32*)&r)[1]=t[0];}
+#define UNPACK_D(f,r) \
+ {u32 t[2]; t[0]=((u32*)&r)[1]; t[1]=((u32*)&r)[0]; FP_UNPACK_DP(f,t);}
+
+// 2 args instructions.
+#define BOTH_PRmn(op,x) \
+ FP_DECL_EX; if(FPSCR_PR) op(D,x,DRm,DRn); else op(S,x,FRm,FRn);
+
+#define CMP_X(SZ,R,M,N) do{ \
+ FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+ UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+ FP_CMP_##SZ(R, Fn, Fm, 2); }while(0)
+#define EQ_X(SZ,R,M,N) do{ \
+ FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+ UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+ FP_CMP_EQ_##SZ(R, Fn, Fm); }while(0)
+#define CMP(OP) ({ int r; BOTH_PRmn(OP##_X,r); r; })
+
+static int
+fcmp_gt(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ if (CMP(CMP) > 0)
+ regs->sr |= 1;
+ else
+ regs->sr &= ~1;
+
+ return 0;
+}
+
+static int
+fcmp_eq(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ if (CMP(CMP /*EQ*/) == 0)
+ regs->sr |= 1;
+ else
+ regs->sr &= ~1;
+ return 0;
+}
+
+#define ARITH_X(SZ,OP,M,N) do{ \
+ FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); FP_DECL_##SZ(Fr); \
+ UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+ FP_##OP##_##SZ(Fr, Fn, Fm); \
+ PACK_##SZ(N, Fr); }while(0)
+
+static int
+fadd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ BOTH_PRmn(ARITH_X, ADD);
+ return 0;
+}
+
+static int
+fsub(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ BOTH_PRmn(ARITH_X, SUB);
+ return 0;
+}
+
+static int
+fmul(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ BOTH_PRmn(ARITH_X, MUL);
+ return 0;
+}
+
+static int
+fdiv(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ BOTH_PRmn(ARITH_X, DIV);
+ return 0;
+}
+
+static int
+fmac(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ FP_DECL_EX;
+ FP_DECL_S(Fr);
+ FP_DECL_S(Ft);
+ FP_DECL_S(F0);
+ FP_DECL_S(Fm);
+ FP_DECL_S(Fn);
+ UNPACK_S(F0, FR0);
+ UNPACK_S(Fm, FRm);
+ UNPACK_S(Fn, FRn);
+ FP_MUL_S(Ft, Fm, F0);
+ FP_ADD_S(Fr, Fn, Ft);
+ PACK_S(FRn, Fr);
+ return 0;
+}
+
+// to process fmov's extention (odd n for DR access XD).
+#define FMOV_EXT(x) if(x&1) x+=16-1
+
+static int
+fmov_idx_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(n);
+ READ(FRn, Rm + R0 + 4);
+ n++;
+ READ(FRn, Rm + R0);
+ } else {
+ READ(FRn, Rm + R0);
+ }
+
+ return 0;
+}
+
+static int
+fmov_mem_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(n);
+ READ(FRn, Rm + 4);
+ n++;
+ READ(FRn, Rm);
+ } else {
+ READ(FRn, Rm);
+ }
+
+ return 0;
+}
+
+static int
+fmov_inc_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(n);
+ READ(FRn, Rm + 4);
+ n++;
+ READ(FRn, Rm);
+ Rm += 8;
+ } else {
+ READ(FRn, Rm);
+ Rm += 4;
+ }
+
+ return 0;
+}
+
+static int
+fmov_reg_idx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(m);
+ WRITE(FRm, Rn + R0 + 4);
+ m++;
+ WRITE(FRm, Rn + R0);
+ } else {
+ WRITE(FRm, Rn + R0);
+ }
+
+ return 0;
+}
+
+static int
+fmov_reg_mem(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(m);
+ WRITE(FRm, Rn + 4);
+ m++;
+ WRITE(FRm, Rn);
+ } else {
+ WRITE(FRm, Rn);
+ }
+
+ return 0;
+}
+
+static int
+fmov_reg_dec(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(m);
+ Rn -= 8;
+ WRITE(FRm, Rn + 4);
+ m++;
+ WRITE(FRm, Rn);
+ } else {
+ Rn -= 4;
+ WRITE(FRm, Rn);
+ }
+
+ return 0;
+}
+
+static int
+fmov_reg_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+ int n)
+{
+ if (FPSCR_SZ) {
+ FMOV_EXT(m);
+ FMOV_EXT(n);
+ DRn = DRm;
+ } else {
+ FRn = FRm;
+ }
+
+ return 0;
+}
+
+static int
+fnop_mn(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+ return -EINVAL;
+}
+
+// 1 arg instructions.
+#define NOTYETn(i) static int i(struct sh_fpu_soft_struct *fregs, int n) \
+ { printk( #i " not yet done.\n"); return 0; }
+
+NOTYETn(ftrv)
+NOTYETn(fsqrt)
+NOTYETn(fipr)
+NOTYETn(fsca)
+NOTYETn(fsrra)
+
+#define EMU_FLOAT_X(SZ,N) do { \
+ FP_DECL_##SZ(Fn); \
+ FP_FROM_INT_##SZ(Fn, FPUL, 32, int); \
+ PACK_##SZ(N, Fn); }while(0)
+static int ffloat(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FP_DECL_EX;
+
+ if (FPSCR_PR)
+ EMU_FLOAT_X(D, DRn);
+ else
+ EMU_FLOAT_X(S, FRn);
+
+ return 0;
+}
+
+#define EMU_FTRC_X(SZ,N) do { \
+ FP_DECL_##SZ(Fn); \
+ UNPACK_##SZ(Fn, N); \
+ FP_TO_INT_##SZ(FPUL, Fn, 32, 1); }while(0)
+static int ftrc(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FP_DECL_EX;
+
+ if (FPSCR_PR)
+ EMU_FTRC_X(D, DRn);
+ else
+ EMU_FTRC_X(S, FRn);
+
+ return 0;
+}
+
+static int fcnvsd(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FP_DECL_EX;
+ FP_DECL_S(Fn);
+ FP_DECL_D(Fr);
+ UNPACK_S(Fn, FPUL);
+ FP_CONV(D, S, 2, 1, Fr, Fn);
+ PACK_D(DRn, Fr);
+ return 0;
+}
+
+static int fcnvds(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FP_DECL_EX;
+ FP_DECL_D(Fn);
+ FP_DECL_S(Fr);
+ UNPACK_D(Fn, DRn);
+ FP_CONV(S, D, 1, 2, Fr, Fn);
+ PACK_S(FPUL, Fr);
+ return 0;
+}
+
+static int fxchg(struct sh_fpu_soft_struct *fregs, int flag)
+{
+ FPSCR ^= flag;
+ return 0;
+}
+
+static int fsts(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FRn = FPUL;
+ return 0;
+}
+
+static int flds(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FPUL = FRn;
+ return 0;
+}
+
+static int fneg(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FRn ^= (1 << (_FP_W_TYPE_SIZE - 1));
+ return 0;
+}
+
+static int fabs(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FRn &= ~(1 << (_FP_W_TYPE_SIZE - 1));
+ return 0;
+}
+
+static int fld0(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FRn = 0;
+ return 0;
+}
+
+static int fld1(struct sh_fpu_soft_struct *fregs, int n)
+{
+ FRn = (_FP_EXPBIAS_S << (_FP_FRACBITS_S - 1));
+ return 0;
+}
+
+static int fnop_n(struct sh_fpu_soft_struct *fregs, int n)
+{
+ return -EINVAL;
+}
+
+/// Instruction decoders.
+
+static int id_fxfd(struct sh_fpu_soft_struct *, int);
+static int id_fnxd(struct sh_fpu_soft_struct *, struct pt_regs *, int, int);
+
+static int (*fnxd[])(struct sh_fpu_soft_struct *, int) = {
+ fsts, flds, ffloat, ftrc, fneg, fabs, fsqrt, fsrra,
+ fld0, fld1, fcnvsd, fcnvds, fnop_n, fnop_n, fipr, id_fxfd
+};
+
+static int (*fnmx[])(struct sh_fpu_soft_struct *, struct pt_regs *, int, int) = {
+ fadd, fsub, fmul, fdiv, fcmp_eq, fcmp_gt, fmov_idx_reg, fmov_reg_idx,
+ fmov_mem_reg, fmov_inc_reg, fmov_reg_mem, fmov_reg_dec,
+ fmov_reg_reg, id_fnxd, fmac, fnop_mn};
+
+static int id_fxfd(struct sh_fpu_soft_struct *fregs, int x)
+{
+ const int flag[] = { FPSCR_SZ, FPSCR_PR, FPSCR_FR, 0 };
+ switch (x & 3) {
+ case 3:
+ fxchg(fregs, flag[x >> 2]);
+ break;
+ case 1:
+ ftrv(fregs, x - 1);
+ break;
+ default:
+ fsca(fregs, x);
+ }
+ return 0;
+}
+
+static int
+id_fnxd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int x, int n)
+{
+ return (fnxd[x])(fregs, n);
+}
+
+static int
+id_fnmx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+ int n = (code >> 8) & 0xf, m = (code >> 4) & 0xf, x = code & 0xf;
+ return (fnmx[x])(fregs, regs, m, n);
+}
+
+static int
+id_sys(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+ int n = ((code >> 8) & 0xf);
+ unsigned long *reg = (code & 0x0010) ? &FPUL : &FPSCR;
+
+ switch (code & 0xf0ff) {
+ case 0x005a:
+ case 0x006a:
+ Rn = *reg;
+ break;
+ case 0x405a:
+ case 0x406a:
+ *reg = Rn;
+ break;
+ case 0x4052:
+ case 0x4062:
+ Rn -= 4;
+ WRITE(*reg, Rn);
+ break;
+ case 0x4056:
+ case 0x4066:
+ READ(*reg, Rn);
+ Rn += 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_regs *regs)
+{
+ if ((code & 0xf000) == 0xf000)
+ return id_fnmx(fregs, regs, code);
+ else
+ return id_sys(fregs, regs, code);
+}
+
+/**
+ * denormal_to_double - Given denormalized float number,
+ * store double float
+ *
+ * @fpu: Pointer to sh_fpu_hard structure
+ * @n: Index to FP register
+ */
+static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n)
+{
+ unsigned long du, dl;
+ unsigned long x = fpu->fpul;
+ int exp = 1023 - 126;
+
+ if (x != 0 && (x & 0x7f800000) == 0) {
+ du = (x & 0x80000000);
+ while ((x & 0x00800000) == 0) {
+ x <<= 1;
+ exp--;
+ }
+ x &= 0x007fffff;
+ du |= (exp << 20) | (x >> 3);
+ dl = x << 29;
+
+ fpu->fp_regs[n] = du;
+ fpu->fp_regs[n+1] = dl;
+ }
+}
+
+/**
+ * ieee_fpe_handler - Handle denormalized number exception
+ *
+ * @regs: Pointer to register structure
+ *
+ * Returns 1 when it's handled (should not cause exception).
+ */
+static int ieee_fpe_handler(struct pt_regs *regs)
+{
+ unsigned short insn = *(unsigned short *)regs->pc;
+ unsigned short finsn;
+ unsigned long nextpc;
+ int nib[4] = {
+ (insn >> 12) & 0xf,
+ (insn >> 8) & 0xf,
+ (insn >> 4) & 0xf,
+ insn & 0xf};
+
+ if (nib[0] == 0xb ||
+ (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+ regs->pr = regs->pc + 4;
+
+ if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+ nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ else
+ nextpc = regs->pc + 4;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4;
+ else
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x4 && nib[3] == 0xb &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+ nextpc = regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+ nextpc = regs->pc + 4 + regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (insn == 0x000b) { /* rts */
+ nextpc = regs->pr;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else {
+ nextpc = regs->pc + 2;
+ finsn = insn;
+ }
+
+ if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+ struct task_struct *tsk = current;
+
+ if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+ /* FPU error */
+ denormal_to_double (&tsk->thread.fpu.hard,
+ (finsn >> 8) & 0xf);
+ tsk->thread.fpu.hard.fpscr &=
+ ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+ set_tsk_thread_flag(tsk, TIF_USEDFPU);
+ } else {
+ tsk->thread.trap_no = 11;
+ tsk->thread.error_code = 0;
+ force_sig(SIGFPE, tsk);
+ }
+
+ regs->pc = nextpc;
+ return 1;
+ }
+
+ return 0;
+}
+
+asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ struct task_struct *tsk = current;
+
+ if (ieee_fpe_handler (&regs))
+ return;
+
+ regs.pc += 2;
+ tsk->thread.trap_no = 11;
+ tsk->thread.error_code = 0;
+ force_sig(SIGFPE, tsk);
+}
+
+/**
+ * fpu_init - Initialize FPU registers
+ * @fpu: Pointer to software emulated FPU registers.
+ */
+static void fpu_init(struct sh_fpu_soft_struct *fpu)
+{
+ int i;
+
+ fpu->fpscr = FPSCR_INIT;
+ fpu->fpul = 0;
+
+ for (i = 0; i < 16; i++) {
+ fpu->fp_regs[i] = 0;
+ fpu->xfp_regs[i]= 0;
+ }
+}
+
+/**
+ * do_fpu_inst - Handle reserved instructions for FPU emulation
+ * @inst: instruction code.
+ * @regs: registers on stack.
+ */
+int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
+{
+ struct task_struct *tsk = current;
+ struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft);
+
+ if (!test_tsk_thread_flag(tsk, TIF_USEDFPU)) {
+ /* initialize once. */
+ fpu_init(fpu);
+ set_tsk_thread_flag(tsk, TIF_USEDFPU);
+ }
+
+ return fpu_emulate(inst, fpu, regs);
+}
diff --git a/arch/sh/math-emu/sfp-util.h b/arch/sh/math-emu/sfp-util.h
new file mode 100644
index 00000000000..8ae1bd310ad
--- /dev/null
+++ b/arch/sh/math-emu/sfp-util.h
@@ -0,0 +1,72 @@
+/*
+ * These are copied from glibc/stdlib/longlong.h
+ */
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \
+ : "=r" ((u32)(w1)), "=r" ((u32)(w0)) \
+ : "r" ((u32)(u)), "r" ((u32)(v)) \
+ : "macl", "mach")
+
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0; \
+ UWtype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+#define abort() return 0
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index fb586b1cf8b..9dd606464d2 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -20,7 +20,10 @@ config CPU_SH4
config CPU_SH4A
bool
select CPU_SH4
- select CPU_HAS_INTC2_IRQ
+
+config CPU_SH4AL_DSP
+ bool
+ select CPU_SH4A
config CPU_SUBTYPE_ST40
bool
@@ -48,6 +51,12 @@ config CPU_SUBTYPE_SH7705
select CPU_SH3
select CPU_HAS_PINT_IRQ
+config CPU_SUBTYPE_SH7706
+ bool "Support SH7706 processor"
+ select CPU_SH3
+ help
+ Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU.
+
config CPU_SUBTYPE_SH7707
bool "Support SH7707 processor"
select CPU_SH3
@@ -69,6 +78,12 @@ config CPU_SUBTYPE_SH7709
help
Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
+config CPU_SUBTYPE_SH7710
+ bool "Support SH7710 processor"
+ select CPU_SH3
+ help
+ Select SH7710 if you have a SH3-DSP SH7710 CPU.
+
comment "SH-4 Processor Support"
config CPU_SUBTYPE_SH7750
@@ -133,10 +148,6 @@ config CPU_SUBTYPE_ST40GX1
comment "SH-4A Processor Support"
-config CPU_SUBTYPE_SH73180
- bool "Support SH73180 processor"
- select CPU_SH4A
-
config CPU_SUBTYPE_SH7770
bool "Support SH7770 processor"
select CPU_SH4A
@@ -144,6 +155,17 @@ config CPU_SUBTYPE_SH7770
config CPU_SUBTYPE_SH7780
bool "Support SH7780 processor"
select CPU_SH4A
+ select CPU_HAS_INTC2_IRQ
+
+comment "SH4AL-DSP Processor Support"
+
+config CPU_SUBTYPE_SH73180
+ bool "Support SH73180 processor"
+ select CPU_SH4AL_DSP
+
+config CPU_SUBTYPE_SH7343
+ bool "Support SH7343 processor"
+ select CPU_SH4AL_DSP
endmenu
@@ -161,15 +183,59 @@ config MMU
turning this off will boot the kernel on these machines with the
MMU implicitly switched off.
+config PAGE_OFFSET
+ hex
+ default "0x80000000" if MMU
+ default "0x00000000"
+
+config MEMORY_START
+ hex "Physical memory start address"
+ default "0x08000000"
+ ---help---
+ Computers built with Hitachi SuperH processors always
+ map the ROM starting at address zero. But the processor
+ does not specify the range that RAM takes.
+
+ The physical memory (RAM) start address will be automatically
+ set to 08000000. Other platforms, such as the Solution Engine
+ boards typically map RAM at 0C000000.
+
+ Tweak this only when porting to a new machine which does not
+ already have a defconfig. Changing it from the known correct
+ value on any of the known systems will only lead to disaster.
+
+config MEMORY_SIZE
+ hex "Physical memory size"
+ default "0x00400000"
+ help
+ This sets the default memory size assumed by your SH kernel. It can
+ be overridden as normal by the 'mem=' argument on the kernel command
+ line. If unsure, consult your board specifications or just leave it
+ as 0x00400000 which was the default value before this became
+ configurable.
+
config 32BIT
bool "Support 32-bit physical addressing through PMB"
- depends on CPU_SH4A
+ depends on CPU_SH4A && MMU
default y
help
If you say Y here, physical addressing will be extended to
32-bits through the SH-4A PMB. If this is not set, legacy
29-bit physical addressing will be used.
+config VSYSCALL
+ bool "Support vsyscall page"
+ depends on MMU
+ default y
+ help
+ This will enable support for the kernel mapping a vDSO page
+ in process space, and subsequently handing down the entry point
+ to the libc through the ELF auxiliary vector.
+
+ From the kernel side this is used for the signal trampoline.
+ For systems with an MMU that can afford to give up a page,
+ (the default value) say Y.
+
choice
prompt "HugeTLB page size"
depends on HUGETLB_PAGE && CPU_SH4 && MMU
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 9489a142464..3ffd7f68c0a 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -6,20 +6,26 @@ obj-y := init.o extable.o consistent.o
obj-$(CONFIG_CPU_SH2) += cache-sh2.o
obj-$(CONFIG_CPU_SH3) += cache-sh3.o
-obj-$(CONFIG_CPU_SH4) += cache-sh4.o pg-sh4.o
+obj-$(CONFIG_CPU_SH4) += cache-sh4.o
obj-$(CONFIG_DMA_PAGE_OPS) += pg-dma.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o
+mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \
+ ioremap.o
obj-y += $(mmu-y)
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_CPU_SH4) += cache-debugfs.o
+endif
+
ifdef CONFIG_MMU
-obj-$(CONFIG_CPU_SH3) += tlb-sh3.o
-obj-$(CONFIG_CPU_SH4) += tlb-sh4.o ioremap.o
+obj-$(CONFIG_CPU_SH3) += tlb-sh3.o
+obj-$(CONFIG_CPU_SH4) += tlb-sh4.o pg-sh4.o
obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
endif
-obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
+obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
+obj-$(CONFIG_32BIT) += pmb.o
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
new file mode 100644
index 00000000000..a22d914e4d1
--- /dev/null
+++ b/arch/sh/mm/cache-debugfs.c
@@ -0,0 +1,147 @@
+/*
+ * debugfs ops for the L1 cache
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+enum cache_type {
+ CACHE_TYPE_ICACHE,
+ CACHE_TYPE_DCACHE,
+ CACHE_TYPE_UNIFIED,
+};
+
+static int cache_seq_show(struct seq_file *file, void *iter)
+{
+ unsigned int cache_type = (unsigned int)file->private;
+ struct cache_info *cache;
+ unsigned int waysize, way, cache_size;
+ unsigned long ccr, base;
+ static unsigned long addrstart = 0;
+
+ /*
+ * Go uncached immediately so we don't skew the results any
+ * more than we already are..
+ */
+ jump_to_P2();
+
+ ccr = ctrl_inl(CCR);
+ if ((ccr & CCR_CACHE_ENABLE) == 0) {
+ back_to_P1();
+
+ seq_printf(file, "disabled\n");
+ return 0;
+ }
+
+ if (cache_type == CACHE_TYPE_DCACHE) {
+ base = CACHE_OC_ADDRESS_ARRAY;
+ cache = &cpu_data->dcache;
+ } else {
+ base = CACHE_IC_ADDRESS_ARRAY;
+ cache = &cpu_data->icache;
+ }
+
+ /*
+ * Due to the amount of data written out (depending on the cache size),
+ * we may be iterated over multiple times. In this case, keep track of
+ * the entry position in addrstart, and rewind it when we've hit the
+ * end of the cache.
+ *
+ * Likewise, the same code is used for multiple caches, so care must
+ * be taken for bouncing addrstart back and forth so the appropriate
+ * cache is hit.
+ */
+ cache_size = cache->ways * cache->sets * cache->linesz;
+ if (((addrstart & 0xff000000) != base) ||
+ (addrstart & 0x00ffffff) > cache_size)
+ addrstart = base;
+
+ waysize = cache->sets;
+
+ /*
+ * If the OC is already in RAM mode, we only have
+ * half of the entries to consider..
+ */
+ if ((ccr & CCR_CACHE_ORA) && cache_type == CACHE_TYPE_DCACHE)
+ waysize >>= 1;
+
+ waysize <<= cache->entry_shift;
+
+ for (way = 0; way < cache->ways; way++) {
+ unsigned long addr;
+ unsigned int line;
+
+ seq_printf(file, "-----------------------------------------\n");
+ seq_printf(file, "Way %d\n", way);
+ seq_printf(file, "-----------------------------------------\n");
+
+ for (addr = addrstart, line = 0;
+ addr < addrstart + waysize;
+ addr += cache->linesz, line++) {
+ unsigned long data = ctrl_inl(addr);
+
+ /* Check the V bit, ignore invalid cachelines */
+ if ((data & 1) == 0)
+ continue;
+
+ /* U: Dirty, cache tag is 10 bits up */
+ seq_printf(file, "%3d: %c 0x%lx\n",
+ line, data & 2 ? 'U' : ' ',
+ data & 0x1ffffc00);
+ }
+
+ addrstart += cache->way_incr;
+ }
+
+ back_to_P1();
+
+ return 0;
+}
+
+static int cache_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cache_seq_show, inode->u.generic_ip);
+}
+
+static struct file_operations cache_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = cache_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init cache_debugfs_init(void)
+{
+ struct dentry *dcache_dentry, *icache_dentry;
+
+ dcache_dentry = debugfs_create_file("dcache", S_IRUSR, NULL,
+ (unsigned int *)CACHE_TYPE_DCACHE,
+ &cache_debugfs_fops);
+ if (IS_ERR(dcache_dentry))
+ return PTR_ERR(dcache_dentry);
+
+ icache_dentry = debugfs_create_file("icache", S_IRUSR, NULL,
+ (unsigned int *)CACHE_TYPE_ICACHE,
+ &cache_debugfs_fops);
+ if (IS_ERR(icache_dentry)) {
+ debugfs_remove(dcache_dentry);
+ return PTR_ERR(icache_dentry);
+ }
+
+ return 0;
+}
+module_init(cache_debugfs_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 524cea5b47f..e48cc22724d 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -2,49 +2,120 @@
* arch/sh/mm/cache-sh4.c
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2001 - 2006 Paul Mundt
* Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-
#include <linux/init.h>
-#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/threads.h>
#include <asm/addrspace.h>
-#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/cache.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
-extern void __flush_cache_4096_all(unsigned long start);
-static void __flush_cache_4096_all_ex(unsigned long start);
-extern void __flush_dcache_all(void);
-static void __flush_dcache_all_ex(void);
+/*
+ * The maximum number of pages we support up to when doing ranged dcache
+ * flushing. Anything exceeding this will simply flush the dcache in its
+ * entirety.
+ */
+#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
+
+static void __flush_dcache_segment_1way(unsigned long start,
+ unsigned long extent);
+static void __flush_dcache_segment_2way(unsigned long start,
+ unsigned long extent);
+static void __flush_dcache_segment_4way(unsigned long start,
+ unsigned long extent);
+
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+ unsigned long exec_offset);
+
+/*
+ * This is initialised here to ensure that it is not placed in the BSS. If
+ * that were to happen, note that cache_init gets called before the BSS is
+ * cleared, so this would get nulled out which would be hopeless.
+ */
+static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
+ (void (*)(unsigned long, unsigned long))0xdeadbeef;
+
+static void compute_alias(struct cache_info *c)
+{
+ c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
+ c->n_aliases = (c->alias_mask >> PAGE_SHIFT) + 1;
+}
+
+static void __init emit_cache_params(void)
+{
+ printk("PVR=%08x CVR=%08x PRR=%08x\n",
+ ctrl_inl(CCN_PVR),
+ ctrl_inl(CCN_CVR),
+ ctrl_inl(CCN_PRR));
+ printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+ cpu_data->icache.ways,
+ cpu_data->icache.sets,
+ cpu_data->icache.way_incr);
+ printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+ cpu_data->icache.entry_mask,
+ cpu_data->icache.alias_mask,
+ cpu_data->icache.n_aliases);
+ printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+ cpu_data->dcache.ways,
+ cpu_data->dcache.sets,
+ cpu_data->dcache.way_incr);
+ printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+ cpu_data->dcache.entry_mask,
+ cpu_data->dcache.alias_mask,
+ cpu_data->dcache.n_aliases);
+
+ if (!__flush_dcache_segment_fn)
+ panic("unknown number of cache ways\n");
+}
/*
* SH-4 has virtually indexed and physically tagged cache.
*/
-struct semaphore p3map_sem[4];
+/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
+#define MAX_P3_SEMAPHORES 16
+
+struct semaphore p3map_sem[MAX_P3_SEMAPHORES];
void __init p3_cache_init(void)
{
- if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
+ int i;
+
+ compute_alias(&cpu_data->icache);
+ compute_alias(&cpu_data->dcache);
+
+ switch (cpu_data->dcache.ways) {
+ case 1:
+ __flush_dcache_segment_fn = __flush_dcache_segment_1way;
+ break;
+ case 2:
+ __flush_dcache_segment_fn = __flush_dcache_segment_2way;
+ break;
+ case 4:
+ __flush_dcache_segment_fn = __flush_dcache_segment_4way;
+ break;
+ default:
+ __flush_dcache_segment_fn = NULL;
+ break;
+ }
+
+ emit_cache_params();
+
+ if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE))
panic("%s failed.", __FUNCTION__);
- sema_init (&p3map_sem[0], 1);
- sema_init (&p3map_sem[1], 1);
- sema_init (&p3map_sem[2], 1);
- sema_init (&p3map_sem[3], 1);
+ for (i = 0; i < cpu_data->dcache.n_aliases; i++)
+ sema_init(&p3map_sem[i], 1);
}
/*
@@ -89,7 +160,6 @@ void __flush_purge_region(void *start, int size)
}
}
-
/*
* No write back please
*/
@@ -108,40 +178,6 @@ void __flush_invalidate_region(void *start, int size)
}
}
-static void __flush_dcache_all_ex(void)
-{
- unsigned long addr, end_addr, entry_offset;
-
- end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways;
- entry_offset = 1 << cpu_data->dcache.entry_shift;
- for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) {
- ctrl_outl(0, addr);
- }
-}
-
-static void __flush_cache_4096_all_ex(unsigned long start)
-{
- unsigned long addr, entry_offset;
- int i;
-
- entry_offset = 1 << cpu_data->dcache.entry_shift;
- for (i = 0; i < cpu_data->dcache.ways; i++, start += cpu_data->dcache.way_incr) {
- for (addr = CACHE_OC_ADDRESS_ARRAY + start;
- addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start;
- addr += entry_offset) {
- ctrl_outl(0, addr);
- }
- }
-}
-
-void flush_cache_4096_all(unsigned long start)
-{
- if (cpu_data->dcache.ways == 1)
- __flush_cache_4096_all(start);
- else
- __flush_cache_4096_all_ex(start);
-}
-
/*
* Write back the range of D-cache, and purge the I-cache.
*
@@ -153,14 +189,14 @@ void flush_icache_range(unsigned long start, unsigned long end)
}
/*
- * Write back the D-cache and purge the I-cache for signal trampoline.
+ * Write back the D-cache and purge the I-cache for signal trampoline.
* .. which happens to be the same behavior as flush_icache_range().
* So, we simply flush out a line.
*/
void flush_cache_sigtramp(unsigned long addr)
{
unsigned long v, index;
- unsigned long flags;
+ unsigned long flags;
int i;
v = addr & ~(L1_CACHE_BYTES-1);
@@ -172,30 +208,33 @@ void flush_cache_sigtramp(unsigned long addr)
local_irq_save(flags);
jump_to_P2();
- for(i = 0; i < cpu_data->icache.ways; i++, index += cpu_data->icache.way_incr)
+
+ for (i = 0; i < cpu_data->icache.ways;
+ i++, index += cpu_data->icache.way_incr)
ctrl_outl(0, index); /* Clear out Valid-bit */
+
back_to_P1();
+ wmb();
local_irq_restore(flags);
}
static inline void flush_cache_4096(unsigned long start,
unsigned long phys)
{
- unsigned long flags;
- extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
+ unsigned long flags, exec_offset = 0;
/*
- * SH7751, SH7751R, and ST40 have no restriction to handle cache.
- * (While SH7750 must do that at P2 area.)
+ * All types of SH-4 require PC to be in P2 to operate on the I-cache.
+ * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
*/
- if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG)
- || start < CACHE_OC_ADDRESS_ARRAY) {
- local_irq_save(flags);
- __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0x20000000);
- local_irq_restore(flags);
- } else {
- __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0);
- }
+ if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
+ (start < CACHE_OC_ADDRESS_ARRAY))
+ exec_offset = 0x20000000;
+
+ local_irq_save(flags);
+ __flush_cache_4096(start | SH_CACHE_ASSOC,
+ P1SEGADDR(phys), exec_offset);
+ local_irq_restore(flags);
}
/*
@@ -206,15 +245,19 @@ void flush_dcache_page(struct page *page)
{
if (test_bit(PG_mapped, &page->flags)) {
unsigned long phys = PHYSADDR(page_address(page));
+ unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
+ int i, n;
/* Loop all the D-cache */
- flush_cache_4096(CACHE_OC_ADDRESS_ARRAY, phys);
- flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
- flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
- flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+ n = cpu_data->dcache.n_aliases;
+ for (i = 0; i < n; i++, addr += PAGE_SIZE)
+ flush_cache_4096(addr, phys);
}
+
+ wmb();
}
+/* TODO: Selective icache invalidation through IC address array.. */
static inline void flush_icache_all(void)
{
unsigned long flags, ccr;
@@ -227,34 +270,142 @@ static inline void flush_icache_all(void)
ccr |= CCR_CACHE_ICI;
ctrl_outl(ccr, CCR);
+ /*
+ * back_to_P1() will take care of the barrier for us, don't add
+ * another one!
+ */
+
back_to_P1();
local_irq_restore(flags);
}
+void flush_dcache_all(void)
+{
+ (*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size);
+ wmb();
+}
+
void flush_cache_all(void)
{
- if (cpu_data->dcache.ways == 1)
- __flush_dcache_all();
- else
- __flush_dcache_all_ex();
+ flush_dcache_all();
flush_icache_all();
}
+static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ unsigned long d = 0, p = start & PAGE_MASK;
+ unsigned long alias_mask = cpu_data->dcache.alias_mask;
+ unsigned long n_aliases = cpu_data->dcache.n_aliases;
+ unsigned long select_bit;
+ unsigned long all_aliases_mask;
+ unsigned long addr_offset;
+ pgd_t *dir;
+ pmd_t *pmd;
+ pud_t *pud;
+ pte_t *pte;
+ int i;
+
+ dir = pgd_offset(mm, p);
+ pud = pud_offset(dir, p);
+ pmd = pmd_offset(pud, p);
+ end = PAGE_ALIGN(end);
+
+ all_aliases_mask = (1 << n_aliases) - 1;
+
+ do {
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
+ p &= PMD_MASK;
+ p += PMD_SIZE;
+ pmd++;
+
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, p);
+
+ do {
+ unsigned long phys;
+ pte_t entry = *pte;
+
+ if (!(pte_val(entry) & _PAGE_PRESENT)) {
+ pte++;
+ p += PAGE_SIZE;
+ continue;
+ }
+
+ phys = pte_val(entry) & PTE_PHYS_MASK;
+
+ if ((p ^ phys) & alias_mask) {
+ d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
+ d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
+
+ if (d == all_aliases_mask)
+ goto loop_exit;
+ }
+
+ pte++;
+ p += PAGE_SIZE;
+ } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
+ pmd++;
+ } while (p < end);
+
+loop_exit:
+ addr_offset = 0;
+ select_bit = 1;
+
+ for (i = 0; i < n_aliases; i++) {
+ if (d & select_bit) {
+ (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
+ wmb();
+ }
+
+ select_bit <<= 1;
+ addr_offset += PAGE_SIZE;
+ }
+}
+
+/*
+ * Note : (RPC) since the caches are physically tagged, the only point
+ * of flush_cache_mm for SH-4 is to get rid of aliases from the
+ * D-cache. The assumption elsewhere, e.g. flush_cache_range, is that
+ * lines can stay resident so long as the virtual address they were
+ * accessed with (hence cache set) is in accord with the physical
+ * address (i.e. tag). It's no different here. So I reckon we don't
+ * need to flush the I-cache, since aliases don't matter for that. We
+ * should try that.
+ *
+ * Caller takes mm->mmap_sem.
+ */
void flush_cache_mm(struct mm_struct *mm)
{
- /* Is there any good way? */
- /* XXX: possibly call flush_cache_range for each vm area */
- /*
- * FIXME: Really, the optimal solution here would be able to flush out
- * individual lines created by the specified context, but this isn't
- * feasible for a number of architectures (such as MIPS, and some
- * SPARC) .. is this possible for SuperH?
- *
- * In the meantime, we'll just flush all of the caches.. this
- * seems to be the simplest way to avoid at least a few wasted
- * cache flushes. -Lethal
+ /*
+ * If cache is only 4k-per-way, there are never any 'aliases'. Since
+ * the cache is physically tagged, the data can just be left in there.
*/
- flush_cache_all();
+ if (cpu_data->dcache.n_aliases == 0)
+ return;
+
+ /*
+ * Don't bother groveling around the dcache for the VMA ranges
+ * if there are too many PTEs to make it worthwhile.
+ */
+ if (mm->nr_ptes >= MAX_DCACHE_PAGES)
+ flush_dcache_all();
+ else {
+ struct vm_area_struct *vma;
+
+ /*
+ * In this case there are reasonably sized ranges to flush,
+ * iterate through the VMA list and take care of any aliases.
+ */
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
+ __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
+ }
+
+ /* Only touch the icache if one of the VMAs has VM_EXEC set. */
+ if (mm->exec_vm)
+ flush_icache_all();
}
/*
@@ -263,27 +414,40 @@ void flush_cache_mm(struct mm_struct *mm)
* ADDR: Virtual Address (U0 address)
* PFN: Physical page number
*/
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+ unsigned long pfn)
{
unsigned long phys = pfn << PAGE_SHIFT;
+ unsigned int alias_mask;
+
+ alias_mask = cpu_data->dcache.alias_mask;
/* We only need to flush D-cache when we have alias */
- if ((address^phys) & CACHE_ALIAS) {
+ if ((address^phys) & alias_mask) {
/* Loop 4K of the D-cache */
flush_cache_4096(
- CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+ CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
phys);
/* Loop another 4K of the D-cache */
flush_cache_4096(
- CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+ CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
phys);
}
- if (vma->vm_flags & VM_EXEC)
- /* Loop 4K (half) of the I-cache */
+ alias_mask = cpu_data->icache.alias_mask;
+ if (vma->vm_flags & VM_EXEC) {
+ /*
+ * Evict entries from the portion of the cache from which code
+ * may have been executed at this address (virtual). There's
+ * no need to evict from the portion corresponding to the
+ * physical address as for the D-cache, because we know the
+ * kernel has never executed the code through its identity
+ * translation.
+ */
flush_cache_4096(
- CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+ CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
phys);
+ }
}
/*
@@ -298,52 +462,31 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigne
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- unsigned long p = start & PAGE_MASK;
- pgd_t *dir;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
- unsigned long phys;
- unsigned long d = 0;
-
- dir = pgd_offset(vma->vm_mm, p);
- pmd = pmd_offset(dir, p);
+ /*
+ * If cache is only 4k-per-way, there are never any 'aliases'. Since
+ * the cache is physically tagged, the data can just be left in there.
+ */
+ if (cpu_data->dcache.n_aliases == 0)
+ return;
- do {
- if (pmd_none(*pmd) || pmd_bad(*pmd)) {
- p &= ~((1 << PMD_SHIFT) -1);
- p += (1 << PMD_SHIFT);
- pmd++;
- continue;
- }
- pte = pte_offset_kernel(pmd, p);
- do {
- entry = *pte;
- if ((pte_val(entry) & _PAGE_PRESENT)) {
- phys = pte_val(entry)&PTE_PHYS_MASK;
- if ((p^phys) & CACHE_ALIAS) {
- d |= 1 << ((p & CACHE_ALIAS)>>12);
- d |= 1 << ((phys & CACHE_ALIAS)>>12);
- if (d == 0x0f)
- goto loop_exit;
- }
- }
- pte++;
- p += PAGE_SIZE;
- } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
- pmd++;
- } while (p < end);
- loop_exit:
- if (d & 1)
- flush_cache_4096_all(0);
- if (d & 2)
- flush_cache_4096_all(0x1000);
- if (d & 4)
- flush_cache_4096_all(0x2000);
- if (d & 8)
- flush_cache_4096_all(0x3000);
- if (vma->vm_flags & VM_EXEC)
+ /*
+ * Don't bother with the lookup and alias check if we have a
+ * wide range to cover, just blow away the dcache in its
+ * entirety instead. -- PFM.
+ */
+ if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
+ flush_dcache_all();
+ else
+ __flush_cache_mm(vma->vm_mm, start, end);
+
+ if (vma->vm_flags & VM_EXEC) {
+ /*
+ * TODO: Is this required??? Need to look at how I-cache
+ * coherency is assured when new programs are loaded to see if
+ * this matters.
+ */
flush_icache_all();
+ }
}
/*
@@ -357,5 +500,273 @@ void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr, int len)
{
flush_cache_page(vma, addr, page_to_pfn(page));
+ mb();
+}
+
+/**
+ * __flush_cache_4096
+ *
+ * @addr: address in memory mapped cache array
+ * @phys: P1 address to flush (has to match tags if addr has 'A' bit
+ * set i.e. associative write)
+ * @exec_offset: set to 0x20000000 if flush has to be executed from P2
+ * region else 0x0
+ *
+ * The offset into the cache array implied by 'addr' selects the
+ * 'colour' of the virtual address range that will be flushed. The
+ * operation (purge/write-back) is selected by the lower 2 bits of
+ * 'phys'.
+ */
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+ unsigned long exec_offset)
+{
+ int way_count;
+ unsigned long base_addr = addr;
+ struct cache_info *dcache;
+ unsigned long way_incr;
+ unsigned long a, ea, p;
+ unsigned long temp_pc;
+
+ dcache = &cpu_data->dcache;
+ /* Write this way for better assembly. */
+ way_count = dcache->ways;
+ way_incr = dcache->way_incr;
+
+ /*
+ * Apply exec_offset (i.e. branch to P2 if required.).
+ *
+ * FIXME:
+ *
+ * If I write "=r" for the (temp_pc), it puts this in r6 hence
+ * trashing exec_offset before it's been added on - why? Hence
+ * "=&r" as a 'workaround'
+ */
+ asm volatile("mov.l 1f, %0\n\t"
+ "add %1, %0\n\t"
+ "jmp @%0\n\t"
+ "nop\n\t"
+ ".balign 4\n\t"
+ "1: .long 2f\n\t"
+ "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
+
+ /*
+ * We know there will be >=1 iteration, so write as do-while to avoid
+ * pointless nead-of-loop check for 0 iterations.
+ */
+ do {
+ ea = base_addr + PAGE_SIZE;
+ a = base_addr;
+ p = phys;
+
+ do {
+ *(volatile unsigned long *)a = p;
+ /*
+ * Next line: intentionally not p+32, saves an add, p
+ * will do since only the cache tag bits need to
+ * match.
+ */
+ *(volatile unsigned long *)(a+32) = p;
+ a += 64;
+ p += 64;
+ } while (a < ea);
+
+ base_addr += way_incr;
+ } while (--way_count != 0);
}
+/*
+ * Break the 1, 2 and 4 way variants of this out into separate functions to
+ * avoid nearly all the overhead of having the conditional stuff in the function
+ * bodies (+ the 1 and 2 way cases avoid saving any registers too).
+ */
+static void __flush_dcache_segment_1way(unsigned long start,
+ unsigned long extent_per_way)
+{
+ unsigned long orig_sr, sr_with_bl;
+ unsigned long base_addr;
+ unsigned long way_incr, linesz, way_size;
+ struct cache_info *dcache;
+ register unsigned long a0, a0e;
+
+ asm volatile("stc sr, %0" : "=r" (orig_sr));
+ sr_with_bl = orig_sr | (1<<28);
+ base_addr = ((unsigned long)&empty_zero_page[0]);
+
+ /*
+ * The previous code aligned base_addr to 16k, i.e. the way_size of all
+ * existing SH-4 D-caches. Whilst I don't see a need to have this
+ * aligned to any better than the cache line size (which it will be
+ * anyway by construction), let's align it to at least the way_size of
+ * any existing or conceivable SH-4 D-cache. -- RPC
+ */
+ base_addr = ((base_addr >> 16) << 16);
+ base_addr |= start;
+
+ dcache = &cpu_data->dcache;
+ linesz = dcache->linesz;
+ way_incr = dcache->way_incr;
+ way_size = dcache->way_size;
+
+ a0 = base_addr;
+ a0e = base_addr + extent_per_way;
+ do {
+ asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+ asm volatile("movca.l r0, @%0\n\t"
+ "ocbi @%0" : : "r" (a0));
+ a0 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "ocbi @%0" : : "r" (a0));
+ a0 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "ocbi @%0" : : "r" (a0));
+ a0 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "ocbi @%0" : : "r" (a0));
+ asm volatile("ldc %0, sr" : : "r" (orig_sr));
+ a0 += linesz;
+ } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_2way(unsigned long start,
+ unsigned long extent_per_way)
+{
+ unsigned long orig_sr, sr_with_bl;
+ unsigned long base_addr;
+ unsigned long way_incr, linesz, way_size;
+ struct cache_info *dcache;
+ register unsigned long a0, a1, a0e;
+
+ asm volatile("stc sr, %0" : "=r" (orig_sr));
+ sr_with_bl = orig_sr | (1<<28);
+ base_addr = ((unsigned long)&empty_zero_page[0]);
+
+ /* See comment under 1-way above */
+ base_addr = ((base_addr >> 16) << 16);
+ base_addr |= start;
+
+ dcache = &cpu_data->dcache;
+ linesz = dcache->linesz;
+ way_incr = dcache->way_incr;
+ way_size = dcache->way_size;
+
+ a0 = base_addr;
+ a1 = a0 + way_incr;
+ a0e = base_addr + extent_per_way;
+ do {
+ asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1" : :
+ "r" (a0), "r" (a1));
+ a0 += linesz;
+ a1 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1" : :
+ "r" (a0), "r" (a1));
+ a0 += linesz;
+ a1 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1" : :
+ "r" (a0), "r" (a1));
+ a0 += linesz;
+ a1 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1" : :
+ "r" (a0), "r" (a1));
+ asm volatile("ldc %0, sr" : : "r" (orig_sr));
+ a0 += linesz;
+ a1 += linesz;
+ } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_4way(unsigned long start,
+ unsigned long extent_per_way)
+{
+ unsigned long orig_sr, sr_with_bl;
+ unsigned long base_addr;
+ unsigned long way_incr, linesz, way_size;
+ struct cache_info *dcache;
+ register unsigned long a0, a1, a2, a3, a0e;
+
+ asm volatile("stc sr, %0" : "=r" (orig_sr));
+ sr_with_bl = orig_sr | (1<<28);
+ base_addr = ((unsigned long)&empty_zero_page[0]);
+
+ /* See comment under 1-way above */
+ base_addr = ((base_addr >> 16) << 16);
+ base_addr |= start;
+
+ dcache = &cpu_data->dcache;
+ linesz = dcache->linesz;
+ way_incr = dcache->way_incr;
+ way_size = dcache->way_size;
+
+ a0 = base_addr;
+ a1 = a0 + way_incr;
+ a2 = a1 + way_incr;
+ a3 = a2 + way_incr;
+ a0e = base_addr + extent_per_way;
+ do {
+ asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "movca.l r0, @%2\n\t"
+ "movca.l r0, @%3\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1\n\t"
+ "ocbi @%2\n\t"
+ "ocbi @%3\n\t" : :
+ "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+ a0 += linesz;
+ a1 += linesz;
+ a2 += linesz;
+ a3 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "movca.l r0, @%2\n\t"
+ "movca.l r0, @%3\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1\n\t"
+ "ocbi @%2\n\t"
+ "ocbi @%3\n\t" : :
+ "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+ a0 += linesz;
+ a1 += linesz;
+ a2 += linesz;
+ a3 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "movca.l r0, @%2\n\t"
+ "movca.l r0, @%3\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1\n\t"
+ "ocbi @%2\n\t"
+ "ocbi @%3\n\t" : :
+ "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+ a0 += linesz;
+ a1 += linesz;
+ a2 += linesz;
+ a3 += linesz;
+ asm volatile("movca.l r0, @%0\n\t"
+ "movca.l r0, @%1\n\t"
+ "movca.l r0, @%2\n\t"
+ "movca.l r0, @%3\n\t"
+ "ocbi @%0\n\t"
+ "ocbi @%1\n\t"
+ "ocbi @%2\n\t"
+ "ocbi @%3\n\t" : :
+ "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+ asm volatile("ldc %0, sr" : : "r" (orig_sr));
+ a0 += linesz;
+ a1 += linesz;
+ a2 += linesz;
+ a3 += linesz;
+ } while (a0 < a0e);
+}
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index ad8ed7d41e1..045abdf078f 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -9,7 +9,6 @@
* for more details.
*
*/
-
#include <linux/init.h>
#include <linux/mman.h>
#include <linux/mm.h>
@@ -25,14 +24,10 @@
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
-/* The 32KB cache on the SH7705 suffers from the same synonym problem
- * as SH4 CPUs */
-
-#define __pte_offset(address) \
- ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
- __pte_offset(address))
-
+/*
+ * The 32KB cache on the SH7705 suffers from the same synonym problem
+ * as SH4 CPUs
+ */
static inline void cache_wback_all(void)
{
unsigned long ways, waysize, addrstart;
@@ -73,7 +68,6 @@ void flush_icache_range(unsigned long start, unsigned long end)
__flush_wback_region((void *)start, end - start);
}
-
/*
* Writeback&Invalidate the D-cache of the page
*/
@@ -128,7 +122,6 @@ static void __flush_dcache_page(unsigned long phys)
local_irq_restore(flags);
}
-
/*
* Write back & invalidate the D-cache of the page.
* (To avoid "alias" issues)
@@ -186,7 +179,8 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
*
* ADDRESS: Virtual Address (U0 address)
*/
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+ unsigned long pfn)
{
__flush_dcache_page(pfn << PAGE_SHIFT);
}
@@ -203,4 +197,3 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
__flush_purge_region(page_address(page), PAGE_SIZE);
}
-
diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S
index 08acead7b2a..7b96425ae27 100644
--- a/arch/sh/mm/clear_page.S
+++ b/arch/sh/mm/clear_page.S
@@ -193,102 +193,5 @@ ENTRY(__clear_user_page)
nop
.L4096: .word 4096
-ENTRY(__flush_cache_4096)
- mov.l 1f,r3
- add r6,r3
- mov r4,r0
- mov #64,r2
- shll r2
- mov #64,r6
- jmp @r3
- mov #96,r7
- .align 2
-1: .long 2f
-2:
- .rept 32
- mov.l r5,@r0
- mov.l r5,@(32,r0)
- mov.l r5,@(r0,r6)
- mov.l r5,@(r0,r7)
- add r2,r5
- add r2,r0
- .endr
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- rts
- nop
-
-ENTRY(__flush_dcache_all)
- mov.l 2f,r0
- mov.l 3f,r4
- and r0,r4 ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
- stc sr,r1 ! save SR
- mov.l 4f,r2
- or r1,r2
- mov #32,r3
- shll2 r3
-1:
- ldc r2,sr ! set BL bit
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- ldc r1,sr ! restore SR
- dt r3
- bf/s 1b
- add #32,r4
-
- rts
- nop
- .align 2
-2: .long 0xffffc000
-3: .long empty_zero_page
-4: .long 0x10000000 ! BL bit
-
-/* __flush_cache_4096_all(unsigned long addr) */
-ENTRY(__flush_cache_4096_all)
- mov.l 2f,r0
- mov.l 3f,r2
- and r0,r2
- or r2,r4 ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
- stc sr,r1 ! save SR
- mov.l 4f,r2
- or r1,r2
- mov #32,r3
-1:
- ldc r2,sr ! set BL bit
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- add #32,r4
- movca.l r0,@r4
- ocbi @r4
- ldc r1,sr ! restore SR
- dt r3
- bf/s 1b
- add #32,r4
-
- rts
- nop
- .align 2
-2: .long 0xffffc000
-3: .long empty_zero_page
-4: .long 0x10000000 ! BL bit
#endif
+
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index ee73e30263a..c81e6b67ad3 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -9,6 +9,8 @@
*/
#include <linux/mm.h>
#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/addrspace.h>
#include <asm/io.h>
void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 775f86cd3fe..c69fd603226 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -1,33 +1,22 @@
-/* $Id: fault.c,v 1.14 2004/01/13 05:52:11 kkojima Exp $
+/*
+ * Page fault handler for SH with an MMU.
*
- * linux/arch/sh/mm/fault.c
* Copyright (C) 1999 Niibe Yutaka
* Copyright (C) 2003 Paul Mundt
*
* Based on linux/arch/i386/mm/fault.c:
* Copyright (C) 1995 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
#include <asm/kgdb.h>
extern void die(const char *,struct pt_regs *,long);
@@ -187,18 +176,30 @@ do_sigbus:
goto no_context;
}
+#ifdef CONFIG_SH_STORE_QUEUES
/*
- * Called with interrupt disabled.
+ * This is a special case for the SH-4 store queues, as pages for this
+ * space still need to be faulted in before it's possible to flush the
+ * store queue cache for writeout to the remapped region.
*/
-asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
- unsigned long address)
+#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000)
+#else
+#define P3_ADDR_MAX P4SEG
+#endif
+
+/*
+ * Called with interrupts disabled.
+ */
+asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
+ unsigned long writeaccess,
+ unsigned long address)
{
- unsigned long addrmax = P4SEG;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t entry;
- struct mm_struct *mm;
+ struct mm_struct *mm = current->mm;
spinlock_t *ptl;
int ret = 1;
@@ -207,31 +208,37 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
kgdb_bus_err_hook();
#endif
-#ifdef CONFIG_SH_STORE_QUEUES
- addrmax = P4SEG_STORE_QUE + 0x04000000;
-#endif
-
- if (address >= P3SEG && address < addrmax) {
+ /*
+ * We don't take page faults for P1, P2, and parts of P4, these
+ * are always mapped, whether it be due to legacy behaviour in
+ * 29-bit mode, or due to PMB configuration in 32-bit mode.
+ */
+ if (address >= P3SEG && address < P3_ADDR_MAX) {
pgd = pgd_offset_k(address);
mm = NULL;
- } else if (address >= TASK_SIZE)
- return 1;
- else if (!(mm = current->mm))
- return 1;
- else
+ } else {
+ if (unlikely(address >= TASK_SIZE || !mm))
+ return 1;
+
pgd = pgd_offset(mm, address);
+ }
- pmd = pmd_offset(pgd, address);
+ pud = pud_offset(pgd, address);
+ if (pud_none_or_clear_bad(pud))
+ return 1;
+ pmd = pmd_offset(pud, address);
if (pmd_none_or_clear_bad(pmd))
return 1;
+
if (mm)
pte = pte_offset_map_lock(mm, pmd, address, &ptl);
else
pte = pte_offset_kernel(pmd, address);
entry = *pte;
- if (pte_none(entry) || pte_not_present(entry)
- || (writeaccess && !pte_write(entry)))
+ if (unlikely(pte_none(entry) || pte_not_present(entry)))
+ goto unlock;
+ if (unlikely(writeaccess && !pte_write(entry)))
goto unlock;
if (writeaccess)
@@ -243,13 +250,7 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
* ITLB is not affected by "ldtlb" instruction.
* So, we need to flush the entry by ourselves.
*/
-
- {
- unsigned long flags;
- local_irq_save(flags);
- __flush_tlb_page(get_asid(), address&PAGE_MASK);
- local_irq_restore(flags);
- }
+ __flush_tlb_page(get_asid(), address & PAGE_MASK);
#endif
set_pte(pte, entry);
@@ -260,121 +261,3 @@ unlock:
pte_unmap_unlock(pte, ptl);
return ret;
}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
- unsigned long flags;
- unsigned long asid;
- unsigned long saved_asid = MMU_NO_ASID;
-
- asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
- page &= PAGE_MASK;
-
- local_irq_save(flags);
- if (vma->vm_mm != current->mm) {
- saved_asid = get_asid();
- set_asid(asid);
- }
- __flush_tlb_page(asid, page);
- if (saved_asid != MMU_NO_ASID)
- set_asid(saved_asid);
- local_irq_restore(flags);
- }
-}
-
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if (mm->context != NO_CONTEXT) {
- unsigned long flags;
- int size;
-
- local_irq_save(flags);
- size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
- if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
- mm->context = NO_CONTEXT;
- if (mm == current->mm)
- activate_context(mm);
- } else {
- unsigned long asid = mm->context&MMU_CONTEXT_ASID_MASK;
- unsigned long saved_asid = MMU_NO_ASID;
-
- start &= PAGE_MASK;
- end += (PAGE_SIZE - 1);
- end &= PAGE_MASK;
- if (mm != current->mm) {
- saved_asid = get_asid();
- set_asid(asid);
- }
- while (start < end) {
- __flush_tlb_page(asid, start);
- start += PAGE_SIZE;
- }
- if (saved_asid != MMU_NO_ASID)
- set_asid(saved_asid);
- }
- local_irq_restore(flags);
- }
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
- unsigned long flags;
- int size;
-
- local_irq_save(flags);
- size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
- if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
- flush_tlb_all();
- } else {
- unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
- unsigned long saved_asid = get_asid();
-
- start &= PAGE_MASK;
- end += (PAGE_SIZE - 1);
- end &= PAGE_MASK;
- set_asid(asid);
- while (start < end) {
- __flush_tlb_page(asid, start);
- start += PAGE_SIZE;
- }
- set_asid(saved_asid);
- }
- local_irq_restore(flags);
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
- /* Invalidate all TLB of this process. */
- /* Instead of invalidating each TLB, we get new MMU context. */
- if (mm->context != NO_CONTEXT) {
- unsigned long flags;
-
- local_irq_save(flags);
- mm->context = NO_CONTEXT;
- if (mm == current->mm)
- activate_context(mm);
- local_irq_restore(flags);
- }
-}
-
-void flush_tlb_all(void)
-{
- unsigned long flags, status;
-
- /*
- * Flush all the TLB.
- *
- * Write to the MMU control register's bit:
- * TF-bit for SH-3, TI-bit for SH-4.
- * It's same position, bit #2.
- */
- local_irq_save(flags);
- status = ctrl_inl(MMUCR);
- status |= 0x04;
- ctrl_outl(status, MMUCR);
- local_irq_restore(flags);
-}
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 2a85bc15a41..329059d6b54 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -26,61 +26,41 @@
pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte = NULL;
pgd = pgd_offset(mm, addr);
if (pgd) {
- pmd = pmd_alloc(mm, pgd, addr);
- if (pmd)
- pte = pte_alloc_map(mm, pmd, addr);
+ pud = pud_alloc(mm, pgd, addr);
+ if (pud) {
+ pmd = pmd_alloc(mm, pud, addr);
+ if (pmd)
+ pte = pte_alloc_map(mm, pmd, addr);
+ }
}
+
return pte;
}
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte = NULL;
pgd = pgd_offset(mm, addr);
if (pgd) {
- pmd = pmd_offset(pgd, addr);
- if (pmd)
- pte = pte_offset_map(pmd, addr);
- }
- return pte;
-}
-
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t entry)
-{
- int i;
-
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte_at(mm, addr, ptep, entry);
- ptep++;
- addr += PAGE_SIZE;
- pte_val(entry) += PAGE_SIZE;
+ pud = pud_offset(pgd, addr);
+ if (pud) {
+ pmd = pmd_offset(pud, addr);
+ if (pmd)
+ pte = pte_offset_map(pmd, addr);
+ }
}
-}
-
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
- pte_t entry;
- int i;
-
- entry = *ptep;
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(mm, addr, ptep);
- addr += PAGE_SIZE;
- ptep++;
- }
-
- return entry;
+ return pte;
}
struct page *follow_huge_addr(struct mm_struct *mm,
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 8ea27ca4b70..7154d1ce978 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -24,7 +24,7 @@
#include <linux/highmem.h>
#include <linux/bootmem.h>
#include <linux/pagemap.h>
-
+#include <linux/proc_fs.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -80,6 +80,7 @@ void show_mem(void)
static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
@@ -89,7 +90,17 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
return;
}
- pmd = pmd_offset(pgd, addr);
+ pud = pud_offset(pgd, addr);
+ if (pud_none(*pud)) {
+ pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+ if (pmd != pmd_offset(pud, 0)) {
+ pud_ERROR(*pud);
+ return;
+ }
+ }
+
+ pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
@@ -212,6 +223,8 @@ void __init paging_init(void)
free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
}
+static struct kcore_list kcore_mem, kcore_vmalloc;
+
void __init mem_init(void)
{
extern unsigned long empty_zero_page[1024];
@@ -237,8 +250,13 @@ void __init mem_init(void)
* Setup wrappers for copy/clear_page(), these will get overridden
* later in the boot process if a better method is available.
*/
+#ifdef CONFIG_MMU
copy_page = copy_page_slow;
clear_page = clear_page_slow;
+#else
+ copy_page = copy_page_nommu;
+ clear_page = clear_page_nommu;
+#endif
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem_node(NODE_DATA(0));
@@ -254,7 +272,12 @@ void __init mem_init(void)
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+ kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+ kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+ VMALLOC_END - VMALLOC_START);
+
+ printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+ "%dk reserved, %dk data, %dk init)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codesize >> 10,
@@ -263,6 +286,9 @@ void __init mem_init(void)
initsize >> 10);
p3_cache_init();
+
+ /* Initialize the vDSO */
+ vsyscall_init();
}
void free_initmem(void)
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index 96fa4a999e2..a9fe80cfc23 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/pci.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -135,6 +136,20 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return (void __iomem *)phys_to_virt(phys_addr);
/*
+ * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
+ * mapped at the end of the address space (typically 0xfd000000)
+ * in a non-translatable area, so mapping through page tables for
+ * this area is not only pointless, but also fundamentally
+ * broken. Just return the physical address instead.
+ *
+ * For boards that map a small PCI memory aperture somewhere in
+ * P1/P2 space, ioremap() will already do the right thing,
+ * and we'll never get this far.
+ */
+ if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
+ return (void __iomem *)phys_addr;
+
+ /*
* Don't allow anybody to remap normal RAM that we're using..
*/
if (phys_addr < virt_to_phys(high_memory))
@@ -192,7 +207,7 @@ void __iounmap(void __iomem *addr)
unsigned long vaddr = (unsigned long __force)addr;
struct vm_struct *p;
- if (PXSEG(vaddr) < P3SEG)
+ if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr))
return;
#ifdef CONFIG_32BIT
diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c
index 8f9165a4e33..d15221beaa1 100644
--- a/arch/sh/mm/pg-nommu.c
+++ b/arch/sh/mm/pg-nommu.c
@@ -14,23 +14,24 @@
#include <linux/string.h>
#include <asm/page.h>
-static void copy_page_nommu(void *to, void *from)
+void copy_page_nommu(void *to, void *from)
{
memcpy(to, from, PAGE_SIZE);
}
-static void clear_page_nommu(void *to)
+void clear_page_nommu(void *to)
{
memset(to, 0, PAGE_SIZE);
}
-static int __init pg_nommu_init(void)
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
{
- copy_page = copy_page_nommu;
- clear_page = clear_page_nommu;
-
+ memcpy(to, from, n);
return 0;
}
-subsys_initcall(pg_nommu_init);
-
+__kernel_size_t __clear_user(void *to, __kernel_size_t n)
+{
+ memset(to, 0, n);
+ return 0;
+}
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index c776b60fc25..07371ed7a31 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -2,7 +2,7 @@
* arch/sh/mm/pg-sh4.c
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2002 Paul Mundt
+ * Copyright (C) 2002 - 2005 Paul Mundt
*
* Released under the terms of the GNU GPL v2.0.
*/
@@ -23,6 +23,8 @@
extern struct semaphore p3map_sem[];
+#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
+
/*
* clear_user_page
* @to: P1 address
@@ -35,14 +37,15 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
clear_page(to);
else {
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
_PAGE_RW | _PAGE_CACHABLE |
- _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
unsigned long phys_addr = PHYSADDR(to);
unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
- pgd_t *dir = pgd_offset_k(p3_addr);
- pmd_t *pmd = pmd_offset(dir, p3_addr);
+ pgd_t *pgd = pgd_offset_k(p3_addr);
+ pud_t *pud = pud_offset(pgd, p3_addr);
+ pmd_t *pmd = pmd_offset(pud, p3_addr);
pte_t *pte = pte_offset_kernel(pmd, p3_addr);
pte_t entry;
unsigned long flags;
@@ -67,21 +70,22 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
* @address: U0 address to be mapped
* @page: page (virt_to_page(to))
*/
-void copy_user_page(void *to, void *from, unsigned long address,
+void copy_user_page(void *to, void *from, unsigned long address,
struct page *page)
{
__set_bit(PG_mapped, &page->flags);
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
copy_page(to, from);
else {
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
_PAGE_RW | _PAGE_CACHABLE |
- _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
unsigned long phys_addr = PHYSADDR(to);
unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
- pgd_t *dir = pgd_offset_k(p3_addr);
- pmd_t *pmd = pmd_offset(dir, p3_addr);
+ pgd_t *pgd = pgd_offset_k(p3_addr);
+ pud_t *pud = pud_offset(pgd, p3_addr);
+ pmd_t *pmd = pmd_offset(pud, p3_addr);
pte_t *pte = pte_offset_kernel(pmd, p3_addr);
pte_t entry;
unsigned long flags;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
new file mode 100644
index 00000000000..92e745341e4
--- /dev/null
+++ b/arch/sh/mm/pmb.c
@@ -0,0 +1,400 @@
+/*
+ * arch/sh/mm/pmb.c
+ *
+ * Privileged Space Mapping Buffer (PMB) Support.
+ *
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * P1/P2 Section mapping definitions from map32.h, which was:
+ *
+ * Copyright 2003 (c) Lineo Solutions,Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+
+#define NR_PMB_ENTRIES 16
+
+static kmem_cache_t *pmb_cache;
+static unsigned long pmb_map;
+
+static struct pmb_entry pmb_init_map[] = {
+ /* vpn ppn flags (ub/sz/c/wt) */
+
+ /* P1 Section Mappings */
+ { 0x80000000, 0x00000000, PMB_SZ_64M | PMB_C, },
+ { 0x84000000, 0x04000000, PMB_SZ_64M | PMB_C, },
+ { 0x88000000, 0x08000000, PMB_SZ_128M | PMB_C, },
+ { 0x90000000, 0x10000000, PMB_SZ_64M | PMB_C, },
+ { 0x94000000, 0x14000000, PMB_SZ_64M | PMB_C, },
+ { 0x98000000, 0x18000000, PMB_SZ_64M | PMB_C, },
+
+ /* P2 Section Mappings */
+ { 0xa0000000, 0x00000000, PMB_UB | PMB_SZ_64M | PMB_WT, },
+ { 0xa4000000, 0x04000000, PMB_UB | PMB_SZ_64M | PMB_WT, },
+ { 0xa8000000, 0x08000000, PMB_UB | PMB_SZ_128M | PMB_WT, },
+ { 0xb0000000, 0x10000000, PMB_UB | PMB_SZ_64M | PMB_WT, },
+ { 0xb4000000, 0x14000000, PMB_UB | PMB_SZ_64M | PMB_WT, },
+ { 0xb8000000, 0x18000000, PMB_UB | PMB_SZ_64M | PMB_WT, },
+};
+
+static inline unsigned long mk_pmb_entry(unsigned int entry)
+{
+ return (entry & PMB_E_MASK) << PMB_E_SHIFT;
+}
+
+static inline unsigned long mk_pmb_addr(unsigned int entry)
+{
+ return mk_pmb_entry(entry) | PMB_ADDR;
+}
+
+static inline unsigned long mk_pmb_data(unsigned int entry)
+{
+ return mk_pmb_entry(entry) | PMB_DATA;
+}
+
+struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
+ unsigned long flags)
+{
+ struct pmb_entry *pmbe;
+
+ pmbe = kmem_cache_alloc(pmb_cache, GFP_KERNEL);
+ if (!pmbe)
+ return ERR_PTR(-ENOMEM);
+
+ pmbe->vpn = vpn;
+ pmbe->ppn = ppn;
+ pmbe->flags = flags;
+
+ return pmbe;
+}
+
+void pmb_free(struct pmb_entry *pmbe)
+{
+ kmem_cache_free(pmb_cache, pmbe);
+}
+
+/*
+ * Must be in P2 for __set_pmb_entry()
+ */
+int __set_pmb_entry(unsigned long vpn, unsigned long ppn,
+ unsigned long flags, int *entry)
+{
+ unsigned int pos = *entry;
+
+ if (unlikely(pos == PMB_NO_ENTRY))
+ pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+
+repeat:
+ if (unlikely(pos > NR_PMB_ENTRIES))
+ return -ENOSPC;
+
+ if (test_and_set_bit(pos, &pmb_map)) {
+ pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+ goto repeat;
+ }
+
+ ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
+
+#ifdef CONFIG_SH_WRITETHROUGH
+ /*
+ * When we are in 32-bit address extended mode, CCR.CB becomes
+ * invalid, so care must be taken to manually adjust cacheable
+ * translations.
+ */
+ if (likely(flags & PMB_C))
+ flags |= PMB_WT;
+#endif
+
+ ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos));
+
+ *entry = pos;
+
+ return 0;
+}
+
+int set_pmb_entry(struct pmb_entry *pmbe)
+{
+ int ret;
+
+ jump_to_P2();
+ ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry);
+ back_to_P1();
+
+ return ret;
+}
+
+void clear_pmb_entry(struct pmb_entry *pmbe)
+{
+ unsigned int entry = pmbe->entry;
+ unsigned long addr;
+
+ /*
+ * Don't allow clearing of wired init entries, P1 or P2 access
+ * without a corresponding mapping in the PMB will lead to reset
+ * by the TLB.
+ */
+ if (unlikely(entry < ARRAY_SIZE(pmb_init_map) ||
+ entry >= NR_PMB_ENTRIES))
+ return;
+
+ jump_to_P2();
+
+ /* Clear V-bit */
+ addr = mk_pmb_addr(entry);
+ ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+ addr = mk_pmb_data(entry);
+ ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+ back_to_P1();
+
+ clear_bit(entry, &pmb_map);
+}
+
+static DEFINE_SPINLOCK(pmb_list_lock);
+static struct pmb_entry *pmb_list;
+
+static inline void pmb_list_add(struct pmb_entry *pmbe)
+{
+ struct pmb_entry **p, *tmp;
+
+ p = &pmb_list;
+ while ((tmp = *p) != NULL)
+ p = &tmp->next;
+
+ pmbe->next = tmp;
+ *p = pmbe;
+}
+
+static inline void pmb_list_del(struct pmb_entry *pmbe)
+{
+ struct pmb_entry **p, *tmp;
+
+ for (p = &pmb_list; (tmp = *p); p = &tmp->next)
+ if (tmp == pmbe) {
+ *p = tmp->next;
+ return;
+ }
+}
+
+static struct {
+ unsigned long size;
+ int flag;
+} pmb_sizes[] = {
+ { .size = 0x20000000, .flag = PMB_SZ_512M, },
+ { .size = 0x08000000, .flag = PMB_SZ_128M, },
+ { .size = 0x04000000, .flag = PMB_SZ_64M, },
+ { .size = 0x01000000, .flag = PMB_SZ_16M, },
+};
+
+long pmb_remap(unsigned long vaddr, unsigned long phys,
+ unsigned long size, unsigned long flags)
+{
+ struct pmb_entry *pmbp;
+ unsigned long wanted;
+ int pmb_flags, i;
+
+ /* Convert typical pgprot value to the PMB equivalent */
+ if (flags & _PAGE_CACHABLE) {
+ if (flags & _PAGE_WT)
+ pmb_flags = PMB_WT;
+ else
+ pmb_flags = PMB_C;
+ } else
+ pmb_flags = PMB_WT | PMB_UB;
+
+ pmbp = NULL;
+ wanted = size;
+
+again:
+ for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+ struct pmb_entry *pmbe;
+ int ret;
+
+ if (size < pmb_sizes[i].size)
+ continue;
+
+ pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag);
+ if (IS_ERR(pmbe))
+ return PTR_ERR(pmbe);
+
+ ret = set_pmb_entry(pmbe);
+ if (ret != 0) {
+ pmb_free(pmbe);
+ return -EBUSY;
+ }
+
+ phys += pmb_sizes[i].size;
+ vaddr += pmb_sizes[i].size;
+ size -= pmb_sizes[i].size;
+
+ /*
+ * Link adjacent entries that span multiple PMB entries
+ * for easier tear-down.
+ */
+ if (likely(pmbp))
+ pmbp->link = pmbe;
+
+ pmbp = pmbe;
+ }
+
+ if (size >= 0x1000000)
+ goto again;
+
+ return wanted - size;
+}
+
+void pmb_unmap(unsigned long addr)
+{
+ struct pmb_entry **p, *pmbe;
+
+ for (p = &pmb_list; (pmbe = *p); p = &pmbe->next)
+ if (pmbe->vpn == addr)
+ break;
+
+ if (unlikely(!pmbe))
+ return;
+
+ WARN_ON(!test_bit(pmbe->entry, &pmb_map));
+
+ do {
+ struct pmb_entry *pmblink = pmbe;
+
+ clear_pmb_entry(pmbe);
+ pmbe = pmblink->link;
+
+ pmb_free(pmblink);
+ } while (pmbe);
+}
+
+static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+ struct pmb_entry *pmbe = pmb;
+
+ memset(pmb, 0, sizeof(struct pmb_entry));
+
+ spin_lock_irq(&pmb_list_lock);
+
+ pmbe->entry = PMB_NO_ENTRY;
+ pmb_list_add(pmbe);
+
+ spin_unlock_irq(&pmb_list_lock);
+}
+
+static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+ spin_lock_irq(&pmb_list_lock);
+ pmb_list_del(pmb);
+ spin_unlock_irq(&pmb_list_lock);
+}
+
+static int __init pmb_init(void)
+{
+ unsigned int nr_entries = ARRAY_SIZE(pmb_init_map);
+ unsigned int entry;
+
+ BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES));
+
+ pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry),
+ 0, 0, pmb_cache_ctor, pmb_cache_dtor);
+ BUG_ON(!pmb_cache);
+
+ jump_to_P2();
+
+ /*
+ * Ordering is important, P2 must be mapped in the PMB before we
+ * can set PMB.SE, and P1 must be mapped before we jump back to
+ * P1 space.
+ */
+ for (entry = 0; entry < nr_entries; entry++) {
+ struct pmb_entry *pmbe = pmb_init_map + entry;
+
+ __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &entry);
+ }
+
+ ctrl_outl(0, PMB_IRMCR);
+
+ /* PMB.SE and UB[7] */
+ ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR);
+
+ back_to_P1();
+
+ return 0;
+}
+arch_initcall(pmb_init);
+
+static int pmb_seq_show(struct seq_file *file, void *iter)
+{
+ int i;
+
+ seq_printf(file, "V: Valid, C: Cacheable, WT: Write-Through\n"
+ "CB: Copy-Back, B: Buffered, UB: Unbuffered\n");
+ seq_printf(file, "ety vpn ppn size flags\n");
+
+ for (i = 0; i < NR_PMB_ENTRIES; i++) {
+ unsigned long addr, data;
+ unsigned int size;
+ char *sz_str = NULL;
+
+ addr = ctrl_inl(mk_pmb_addr(i));
+ data = ctrl_inl(mk_pmb_data(i));
+
+ size = data & PMB_SZ_MASK;
+ sz_str = (size == PMB_SZ_16M) ? " 16MB":
+ (size == PMB_SZ_64M) ? " 64MB":
+ (size == PMB_SZ_128M) ? "128MB":
+ "512MB";
+
+ /* 02: V 0x88 0x08 128MB C CB B */
+ seq_printf(file, "%02d: %c 0x%02lx 0x%02lx %s %c %s %s\n",
+ i, ((addr & PMB_V) && (data & PMB_V)) ? 'V' : ' ',
+ (addr >> 24) & 0xff, (data >> 24) & 0xff,
+ sz_str, (data & PMB_C) ? 'C' : ' ',
+ (data & PMB_WT) ? "WT" : "CB",
+ (data & PMB_UB) ? "UB" : " B");
+ }
+
+ return 0;
+}
+
+static int pmb_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pmb_seq_show, NULL);
+}
+
+static struct file_operations pmb_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = pmb_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init pmb_debugfs_init(void)
+{
+ struct dentry *dentry;
+
+ dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
+ NULL, NULL, &pmb_debugfs_fops);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ return 0;
+}
+postcore_initcall(pmb_debugfs_init);
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c
new file mode 100644
index 00000000000..73ec7f6084f
--- /dev/null
+++ b/arch/sh/mm/tlb-flush.c
@@ -0,0 +1,134 @@
+/*
+ * TLB flushing operations for SH with an MMU.
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if (vma->vm_mm && vma->vm_mm->context.id != NO_CONTEXT) {
+ unsigned long flags;
+ unsigned long asid;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ asid = vma->vm_mm->context.id & MMU_CONTEXT_ASID_MASK;
+ page &= PAGE_MASK;
+
+ local_irq_save(flags);
+ if (vma->vm_mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+ __flush_tlb_page(asid, page);
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (mm->context.id != NO_CONTEXT) {
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+ mm->context.id = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ } else {
+ unsigned long asid;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ asid = mm->context.id & MMU_CONTEXT_ASID_MASK;
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ if (mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+ flush_tlb_all();
+ } else {
+ unsigned long asid;
+ unsigned long saved_asid = get_asid();
+
+ asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ set_asid(asid);
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ /* Invalidate all TLB of this process. */
+ /* Instead of invalidating each TLB, we get new MMU context. */
+ if (mm->context.id != NO_CONTEXT) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mm->context.id = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_all(void)
+{
+ unsigned long flags, status;
+
+ /*
+ * Flush all the TLB.
+ *
+ * Write to the MMU control register's bit:
+ * TF-bit for SH-3, TI-bit for SH-4.
+ * It's same position, bit #2.
+ */
+ local_irq_save(flags);
+ status = ctrl_inl(MMUCR);
+ status |= 0x04;
+ ctrl_outl(status, MMUCR);
+ ctrl_barrier();
+ local_irq_restore(flags);
+}
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index 115b1b6be40..812b2d567de 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -36,7 +36,6 @@ void update_mmu_cache(struct vm_area_struct * vma,
unsigned long vpn;
struct page *page;
unsigned long pfn;
- unsigned long ptea;
/* Ptrace may call this routine. */
if (vma && current->active_mm != vma->vm_mm)
@@ -59,10 +58,11 @@ void update_mmu_cache(struct vm_area_struct * vma,
ctrl_outl(vpn, MMU_PTEH);
pteval = pte_val(pte);
+
/* Set PTEA register */
- /* TODO: make this look less hacky */
- ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
- ctrl_outl(ptea, MMU_PTEA);
+ if (cpu_data->flags & CPU_HAS_PTEA)
+ /* TODO: make this look less hacky */
+ ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
/* Set PTEL register */
pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile
index 686738d4aa3..1f25d9bb753 100644
--- a/arch/sh/oprofile/Makefile
+++ b/arch/sh/oprofile/Makefile
@@ -7,7 +7,11 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
timer_int.o )
profdrvr-y := op_model_null.o
+
+# SH7750-style performance counters exist across 7750/7750S and 7091.
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750S) := op_model_sh7750.o
profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750) := op_model_sh7750.o
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7091) := op_model_sh7750.o
oprofile-y := $(DRIVER_OBJS) $(profdrvr-y)
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 182fe909257..ac57638977e 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -8,16 +8,15 @@
SE SH_SOLUTION_ENGINE
7751SE SH_7751_SOLUTION_ENGINE
7300SE SH_7300_SOLUTION_ENGINE
+7343SE SH_7343_SOLUTION_ENGINE
73180SE SH_73180_SOLUTION_ENGINE
7751SYSTEMH SH_7751_SYSTEMH
HP6XX SH_HP6XX
HD64461 HD64461
HD64465 HD64465
-SH2000 SH_SH2000
SATURN SH_SATURN
DREAMCAST SH_DREAMCAST
BIGSUR SH_BIGSUR
-ADX SH_ADX
MPC1211 SH_MPC1211
SNAPGEAR SH_SECUREEDGE5410
HS7751RVOIP SH_HS7751RVOIP
@@ -25,4 +24,9 @@ RTS7751R2D SH_RTS7751R2D
EDOSK7705 SH_EDOSK7705
SH4202_MICRODEV SH_SH4202_MICRODEV
SH03 SH_SH03
-
+LANDISK SH_LANDISK
+R7780RP SH_R7780RP
+R7780MP SH_R7780MP
+TITAN SH_TITAN
+SHMIN SH_SHMIN
+7710VOIPGW SH_7710VOIPGW
diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
index 1169757fb38..83295bd21aa 100644
--- a/arch/sh64/mm/init.c
+++ b/arch/sh64/mm/init.c
@@ -110,7 +110,7 @@ void show_mem(void)
*/
void __init paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
pgd_init((unsigned long)swapper_pg_dir);
pgd_init((unsigned long)swapper_pg_dir +
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 16e13f663ab..b27a506309e 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -2175,7 +2175,7 @@ void __init ld_mmu_srmmu(void)
BTFIXUPSET_CALL(pte_pfn, srmmu_pte_pfn, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(pgd_page_vaddr, srmmu_pgd_page, BTFIXUPCALL_NORM);
BTFIXUPSET_SETHI(none_mask, 0xF0000000);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 7fdddf3c7e1..436021ceb2e 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -2280,5 +2280,5 @@ void __init ld_mmu_sun4c(void)
/* These should _never_ get called with two level tables. */
BTFIXUPSET_CALL(pgd_set, sun4c_pgd_set, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(pgd_page, sun4c_pgd_page, BTFIXUPCALL_RETO0);
+ BTFIXUPSET_CALL(pgd_page_vaddr, sun4c_pgd_page, BTFIXUPCALL_RETO0);
}
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 51cf6027b70..0fbdaa5daa8 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.18
-# Sat Sep 23 18:32:19 2006
+# Tue Sep 26 23:09:35 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -141,6 +141,7 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC32_COMPAT=y
@@ -194,21 +195,9 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
-CONFIG_TCP_CONG_ADVANCED=y
-
-#
-# TCP congestion control
-#
-CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_CUBIC=m
-CONFIG_TCP_CONG_WESTWOOD=m
-CONFIG_TCP_CONG_HTCP=m
-CONFIG_TCP_CONG_HSTCP=m
-CONFIG_TCP_CONG_HYBLA=m
-CONFIG_TCP_CONG_VEGAS=m
-CONFIG_TCP_CONG_SCALABLE=m
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_CONG_VENO=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -247,6 +236,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m
# DCCP Kernel Hacking
#
# CONFIG_IP_DCCP_DEBUG is not set
+# CONFIG_NET_DCCPPROBE is not set
#
# SCTP Configuration (EXPERIMENTAL)
@@ -401,6 +391,7 @@ CONFIG_IDEDMA_AUTO=y
#
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
#
@@ -422,12 +413,13 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -440,16 +432,18 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -462,6 +456,11 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_SUNESP is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
@@ -575,6 +574,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
CONFIG_BNX2=m
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -1006,6 +1006,7 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
#
# USB devices
@@ -1353,6 +1354,7 @@ CONFIG_KPROBES=y
# Kernel hacking
#
CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index c88ae23ce81..69444f266e2 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1016,7 +1016,7 @@ struct __sysctl_args32 {
asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
{
-#ifndef CONFIG_SYSCTL
+#ifndef CONFIG_SYSCTL_SYSCALL
return -ENOSYS;
#else
struct __sysctl_args32 tmp;
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index dcba4e6ab57..09cb7fccc03 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -920,8 +920,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
if (sparc_ramdisk_image || sparc_ramdisk_image64) {
unsigned long ramdisk_image = sparc_ramdisk_image ?
sparc_ramdisk_image : sparc_ramdisk_image64;
- if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
- ramdisk_image -= KERNBASE;
+ ramdisk_image -= KERNBASE;
initrd_start = ramdisk_image + phys_base;
initrd_end = initrd_start + sparc_ramdisk_size;
if (initrd_end > end_of_phys_memory) {
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 8135ec322c9..642541769a1 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -736,20 +736,15 @@ struct exec_domain solaris_exec_domain = {
extern int init_socksys(void);
-#ifdef MODULE
-
MODULE_AUTHOR("Jakub Jelinek (jj@ultra.linux.cz), Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)");
MODULE_DESCRIPTION("Solaris binary emulation module");
MODULE_LICENSE("GPL");
-#ifdef __sparc_v9__
extern u32 tl0_solaris[8];
#define update_ttable(x) \
tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
wmb(); \
__asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
-#else
-#endif
extern u32 solaris_sparc_syscall[];
extern u32 solaris_syscall[];
@@ -757,7 +752,7 @@ extern void cleanup_socksys(void);
extern u32 entry64_personality_patch;
-int init_module(void)
+static int __init solaris_init(void)
{
int ret;
@@ -777,19 +772,12 @@ int init_module(void)
return 0;
}
-void cleanup_module(void)
+static void __exit solaris_exit(void)
{
update_ttable(solaris_syscall);
cleanup_socksys();
unregister_exec_domain(&solaris_exec_domain);
}
-#else
-int init_solaris_emul(void)
-{
- register_exec_domain(&solaris_exec_domain);
- init_socksys();
- return 0;
-}
-#endif
-
+module_init(solaris_init);
+module_exit(solaris_exit);
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index bc3df95bc05..7c90e41fd3b 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -168,8 +168,7 @@ static struct file_operations socksys_fops = {
.release = socksys_release,
};
-int __init
-init_socksys(void)
+int __init init_socksys(void)
{
int ret;
struct file * file;
@@ -199,8 +198,7 @@ init_socksys(void)
return 0;
}
-void
-cleanup_socksys(void)
+void __exit cleanup_socksys(void)
{
if (unregister_chrdev(30, "socksys"))
printk ("Couldn't unregister socksys character device\n");
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 9558a7cf34d..11154b6773e 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -4,10 +4,13 @@
core-y += arch/um/sys-x86_64/
START := 0x60000000
+_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
+
#We #undef __x86_64__ for kernelspace, not for userspace where
#it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64
-USER_CFLAGS += -fno-builtin -m64
+CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
+USER_CFLAGS += $(_extra_flags_)
+
CHECKFLAGS += -m64
AFLAGS += -m64
LDFLAGS += -m elf_x86_64
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7218c754505..3576b3cc505 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -110,7 +110,7 @@ static void not_configged_free(void *data)
"UML\n");
}
-static struct chan_ops not_configged_ops = {
+static const struct chan_ops not_configged_ops = {
.init = not_configged_init,
.open = not_configged_open,
.close = not_configged_close,
@@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
}
int console_open_chan(struct line *line, struct console *co,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
int err;
@@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size,
struct chan_type {
char *key;
- struct chan_ops *ops;
+ const struct chan_ops *ops;
};
-static struct chan_type chan_table[] = {
+static const struct chan_type chan_table[] = {
{ "fd", &fd_ops },
#ifdef CONFIG_NULL_CHAN
@@ -534,17 +534,17 @@ static struct chan_type chan_table[] = {
};
static struct chan *parse_chan(struct line *line, char *str, int device,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
- struct chan_type *entry;
- struct chan_ops *ops;
+ const struct chan_type *entry;
+ const struct chan_ops *ops;
struct chan *chan;
void *data;
int i;
ops = NULL;
data = NULL;
- for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(chan_table); i++){
entry = &chan_table[i];
if(!strncmp(str, entry->key, strlen(entry->key))){
ops = entry->ops;
@@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
}
int parse_chan_pair(char *str, struct line *line, int device,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
struct list_head *chans = &line->chan_list;
struct chan *new, *chan;
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h
index 7326c42f7ef..3bc3cf6b94a 100644
--- a/arch/um/drivers/daemon.h
+++ b/arch/um/drivers/daemon.h
@@ -18,7 +18,7 @@ struct daemon_data {
void *dev;
};
-extern struct net_user_info daemon_user_info;
+extern const struct net_user_info daemon_user_info;
extern int daemon_user_write(int fd, void *buf, int len,
struct daemon_data *pri);
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 53d09ed78b4..824386974f8 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -57,7 +57,7 @@ static int daemon_write(int fd, struct sk_buff **skb,
(struct daemon_data *) &lp->user));
}
-static struct net_kern_info daemon_kern_info = {
+static const struct net_kern_info daemon_kern_info = {
.init = daemon_init,
.protocol = eth_protocol,
.read = daemon_read,
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index c944265955e..77954ea7704 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -182,7 +182,7 @@ static int daemon_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info daemon_user_info = {
+const struct net_user_info daemon_user_info = {
.init = daemon_user_init,
.open = daemon_open,
.close = NULL,
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index c41f75e4acb..108b7dafbd0 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -20,7 +20,7 @@ struct fd_chan {
char str[sizeof("1234567890\0")];
};
-static void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, const struct chan_opts *opts)
{
struct fd_chan *data;
char *end;
@@ -77,7 +77,7 @@ static void fd_close(int fd, void *d)
}
}
-struct chan_ops fd_ops = {
+const struct chan_ops fd_ops = {
.type = "fd",
.init = fd_init,
.open = fd_open,
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 37232f908cd..d247ef45c37 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -280,7 +280,7 @@ static int hostmixer_release(struct inode *inode, struct file *file)
/* kernel module operations */
-static struct file_operations hostaudio_fops = {
+static const struct file_operations hostaudio_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hostaudio_read,
@@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = {
.release = hostaudio_release,
};
-static struct file_operations hostmixer_fops = {
+static const struct file_operations hostmixer_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = hostmixer_ioctl_mixdev,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ebebaabb78a..563ce7690a1 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -251,7 +251,7 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
/* nothing */
}
-static struct {
+static const struct {
int cmd;
char *level;
char *name;
@@ -405,7 +405,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
{
- struct line_driver *driver = line->driver;
+ const struct line_driver *driver = line->driver;
int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
if (input)
@@ -558,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
}
int line_config(struct line *lines, unsigned int num, char *str,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
struct line *line;
char *new;
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h
index a2c6db24345..bc56af9d3e5 100644
--- a/arch/um/drivers/mcast.h
+++ b/arch/um/drivers/mcast.h
@@ -13,7 +13,7 @@ struct mcast_data {
void *dev;
};
-extern struct net_user_info mcast_user_info;
+extern const struct net_user_info mcast_user_info;
extern int mcast_user_write(int fd, void *buf, int len,
struct mcast_data *pri);
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index 3a7af18cf94..c090fbd464e 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -61,7 +61,7 @@ static int mcast_write(int fd, struct sk_buff **skb,
(struct mcast_data *) &lp->user);
}
-static struct net_kern_info mcast_kern_info = {
+static const struct net_kern_info mcast_kern_info = {
.init = mcast_init,
.protocol = eth_protocol,
.read = mcast_read,
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index afe85bfa66e..4d2bd39a85b 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -152,7 +152,7 @@ static int mcast_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info mcast_user_info = {
+const struct net_user_info mcast_user_info = {
.init = mcast_user_init,
.open = mcast_open,
.close = mcast_close,
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index b414522f768..79610b5ce67 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -497,7 +497,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
}
error = NULL;
- size = sizeof(default_buf)/sizeof(default_buf[0]);
+ size = ARRAY_SIZE(default_buf);
buf = default_buf;
while(1){
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 9bfd405c3bd..5b2f5fe9e42 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -16,6 +16,7 @@
#include "user.h"
#include "mconsole.h"
#include "umid.h"
+#include "user_util.h"
static struct mconsole_command commands[] = {
/* With uts namespaces, uts information becomes process-specific, so
@@ -65,14 +66,14 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
struct mconsole_command *cmd;
int i;
- for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){
+ for(i = 0; i < ARRAY_SIZE(commands); i++){
cmd = &commands[i];
if(!strncmp(req->request.data, cmd->command,
strlen(cmd->command))){
- return(cmd);
+ return cmd;
}
}
- return(NULL);
+ return NULL;
}
#define MIN(a,b) ((a)<(b) ? (a):(b))
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 022f67bb687..9a3b5daf625 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -85,7 +85,7 @@ mmapper_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations mmapper_fops = {
+static const struct file_operations mmapper_fops = {
.owner = THIS_MODULE,
.read = mmapper_read,
.write = mmapper_write,
@@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = {
.release = mmapper_release,
};
-static struct miscdevice mmapper_dev = {
+static const struct miscdevice mmapper_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mmapper",
.fops = &mmapper_fops
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 501f95675d8..664c2e2fb82 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -31,6 +31,11 @@
#include "irq_user.h"
#include "irq_kern.h"
+static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
+{
+ memcpy(dev->dev_addr, addr, ETH_ALEN);
+}
+
#define DRIVER_NAME "uml-netdev"
static DEFINE_SPINLOCK(opened_lock);
@@ -109,8 +114,6 @@ static int uml_net_open(struct net_device *dev)
struct uml_net_private *lp = dev->priv;
int err;
- spin_lock(&lp->lock);
-
if(lp->fd >= 0){
err = -ENXIO;
goto out;
@@ -144,8 +147,6 @@ static int uml_net_open(struct net_device *dev)
*/
while((err = uml_net_rx(dev)) > 0) ;
- spin_unlock(&lp->lock);
-
spin_lock(&opened_lock);
list_add(&lp->list, &opened);
spin_unlock(&opened_lock);
@@ -155,7 +156,6 @@ out_close:
if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
out:
- spin_unlock(&lp->lock);
return err;
}
@@ -164,15 +164,12 @@ static int uml_net_close(struct net_device *dev)
struct uml_net_private *lp = dev->priv;
netif_stop_queue(dev);
- spin_lock(&lp->lock);
free_irq(dev->irq, dev);
if(lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
- spin_unlock(&lp->lock);
-
spin_lock(&opened_lock);
list_del(&lp->list);
spin_unlock(&opened_lock);
@@ -241,9 +238,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
struct uml_net_private *lp = dev->priv;
struct sockaddr *hwaddr = addr;
- spin_lock(&lp->lock);
- memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
- spin_unlock(&lp->lock);
+ spin_lock_irq(&lp->lock);
+ set_ether_mac(dev, hwaddr->sa_data);
+ spin_unlock_irq(&lp->lock);
return(0);
}
@@ -253,7 +250,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
struct uml_net_private *lp = dev->priv;
int err = 0;
- spin_lock(&lp->lock);
+ spin_lock_irq(&lp->lock);
new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
if(new_mtu < 0){
@@ -264,7 +261,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
dev->mtu = new_mtu;
out:
- spin_unlock(&lp->lock);
+ spin_unlock_irq(&lp->lock);
return err;
}
@@ -564,12 +561,13 @@ static int eth_setup(char *str)
int n, err;
err = eth_parse(str, &n, &str);
- if(err) return(1);
+ if(err)
+ return 1;
- new = alloc_bootmem(sizeof(new));
+ new = alloc_bootmem(sizeof(*new));
if (new == NULL){
printk("eth_init : alloc_bootmem failed\n");
- return(1);
+ return 1;
}
INIT_LIST_HEAD(&new->list);
@@ -577,7 +575,7 @@ static int eth_setup(char *str)
new->init = str;
list_add_tail(&new->list, &eth_cmd_line);
- return(1);
+ return 1;
}
__setup("eth", eth_setup);
@@ -790,13 +788,6 @@ void dev_ip_addr(void *d, unsigned char *bin_buf)
memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
}
-void set_ether_mac(void *d, unsigned char *addr)
-{
- struct net_device *dev = d;
-
- memcpy(dev->dev_addr, addr, ETH_ALEN);
-}
-
struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
{
if((skb != NULL) && (skb_tailroom(skb) < extra)){
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 14cc5f78398..3683ed44315 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -10,7 +10,7 @@
static int null_chan;
-static void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, const struct chan_opts *opts)
{
return(&null_chan);
}
@@ -31,7 +31,7 @@ static void null_free(void *data)
{
}
-struct chan_ops null_ops = {
+const struct chan_ops null_ops = {
.type = "null",
.init = null_init,
.open = null_open,
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 466ff2c2f91..6e1ef855828 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -46,7 +46,7 @@ static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
return(-EPERM);
}
-static struct net_kern_info pcap_kern_info = {
+static const struct net_kern_info pcap_kern_info = {
.init = pcap_init,
.protocol = eth_protocol,
.read = pcap_read,
@@ -76,7 +76,7 @@ int pcap_setup(char *str, char **mac_out, void *data)
if(host_if != NULL)
init->host_if = host_if;
- for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(options); i++){
if(options[i] == NULL)
continue;
if(!strcmp(options[i], "promisc"))
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index edfcb29273e..2ef641ded96 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -120,7 +120,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
return(hdata.len);
}
-struct net_user_info pcap_user_info = {
+const struct net_user_info pcap_user_info = {
.init = pcap_user_init,
.open = pcap_open,
.close = NULL,
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index c43e8bb3250..f2e8fc42ecc 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -27,7 +27,7 @@ struct port_chan {
char dev[sizeof("32768\0")];
};
-static void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, const struct chan_opts *opts)
{
struct port_chan *data;
void *kern_data;
@@ -100,7 +100,7 @@ static void port_close(int fd, void *d)
os_close_file(fd);
}
-struct chan_ops port_ops = {
+const struct chan_ops port_ops = {
.type = "port",
.init = port_init,
.open = port_open,
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1c555c38de4..abec620e838 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -22,7 +22,7 @@ struct pty_chan {
char dev_name[sizeof("/dev/pts/0123456\0")];
};
-static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct pty_chan *data;
@@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d,
return(fd);
}
-struct chan_ops pty_ops = {
+const struct chan_ops pty_ops = {
.type = "pty",
.init = pty_chan_init,
.open = pty_open,
@@ -131,7 +131,7 @@ struct chan_ops pty_ops = {
.winch = 0,
};
-struct chan_ops pts_ops = {
+const struct chan_ops pts_ops = {
.type = "pts",
.init = pty_chan_init,
.open = pts_open,
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index ba471f5864a..ae9909415b9 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -68,7 +68,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
return ret;
}
-static struct file_operations rng_chrdev_ops = {
+static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index bb0dab41c2e..c64f8c61d27 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -12,7 +12,7 @@ struct slip_data {
struct slip_proto slip;
};
-extern struct net_user_info slip_user_info;
+extern const struct net_user_info slip_user_info;
extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 163ee0d5f75..ccea2d7885e 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -61,7 +61,7 @@ static int slip_write(int fd, struct sk_buff **skb,
(struct slip_data *) &lp->user));
}
-struct net_kern_info slip_kern_info = {
+const struct net_kern_info slip_kern_info = {
.init = slip_init,
.protocol = slip_protocol,
.read = slip_read,
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 89fbec185cc..8460285c69a 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -241,7 +241,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
close_addr(addr, netmask, pri->name);
}
-struct net_user_info slip_user_info = {
+const struct net_user_info slip_user_info = {
.init = slip_user_init,
.open = slip_open,
.close = slip_close,
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
index 6cf88ab580c..89ccf83b757 100644
--- a/arch/um/drivers/slirp.h
+++ b/arch/um/drivers/slirp.h
@@ -24,7 +24,7 @@ struct slirp_data {
struct slip_proto slip;
};
-extern struct net_user_info slirp_user_info;
+extern const struct net_user_info slirp_user_info;
extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
extern int slirp_user_write(int fd, void *buf, int len,
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 95e50c943e1..ae322e1c8a8 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -64,7 +64,7 @@ static int slirp_write(int fd, struct sk_buff **skb,
(struct slirp_data *) &lp->user));
}
-struct net_kern_info slirp_kern_info = {
+const struct net_kern_info slirp_kern_info = {
.init = slirp_init,
.protocol = slirp_protocol,
.read = slirp_read,
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 33c5f6e625e..ce5e85d1de3 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -126,7 +126,7 @@ static int slirp_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info slirp_user_info = {
+const struct net_user_info slirp_user_info = {
.init = slirp_user_init,
.open = slirp_open,
.close = slirp_close,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 6dafd6fbfda..6f13e7c71a8 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -23,7 +23,7 @@
#include "irq_user.h"
#include "mconsole_kern.h"
-static int ssl_version = 1;
+static const int ssl_version = 1;
/* Referenced only by tty_driver below - presumably it's locked correctly
* by the tty driver.
@@ -123,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty)
}
#endif
-static struct tty_operations ssl_ops = {
+static const struct tty_operations ssl_ops = {
.open = ssl_open,
.close = line_close,
.write = line_write,
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 856f568c268..5e44adb0705 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -110,7 +110,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
static int con_init_done = 0;
-static struct tty_operations console_ops = {
+static const struct tty_operations console_ops = {
.open = con_open,
.close = line_close,
.write = line_write,
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 9f70edf5d8e..11de3ac1eb5 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -18,7 +18,7 @@ struct tty_chan {
struct termios tt;
};
-static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct tty_chan *data;
@@ -62,7 +62,7 @@ static int tty_open(int input, int output, int primary, void *d,
return fd;
}
-struct chan_ops tty_ops = {
+const struct chan_ops tty_ops = {
.type = "tty",
.init = tty_chan_init,
.open = tty_open,
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index aaa63666104..386f8b95298 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -31,7 +31,7 @@ struct xterm_chan {
};
/* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, struct chan_opts *opts)
+void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
@@ -194,7 +194,7 @@ static void xterm_free(void *d)
free(d);
}
-struct chan_ops xterm_ops = {
+const struct chan_ops xterm_ops = {
.type = "xterm",
.init = xterm_init,
.open = xterm_open,
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 1bb5e9d9427..572d286ed2c 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -23,21 +23,21 @@ struct chan {
unsigned int opened:1;
unsigned int enabled:1;
int fd;
- struct chan_ops *ops;
+ const struct chan_ops *ops;
void *data;
};
extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
struct tty_struct *tty, int irq);
extern int parse_chan_pair(char *str, struct line *line, int device,
- struct chan_opts *opts);
+ const struct chan_opts *opts);
extern int open_chan(struct list_head *chans);
extern int write_chan(struct list_head *chans, const char *buf, int len,
int write_irq);
extern int console_write_chan(struct list_head *chans, const char *buf,
int len);
extern int console_open_chan(struct line *line, struct console *co,
- struct chan_opts *opts);
+ const struct chan_opts *opts);
extern void deactivate_chan(struct list_head *chans, int irq);
extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 659bb3cac32..a795547a1db 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -20,7 +20,7 @@ enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
struct chan_ops {
char *type;
- void *(*init)(char *, int, struct chan_opts *);
+ void *(*init)(char *, int, const struct chan_opts *);
int (*open)(int, int, int, void *, char **);
void (*close)(int, void *);
int (*read)(int, char *, void *);
@@ -31,8 +31,8 @@ struct chan_ops {
int winch;
};
-extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
- xterm_ops;
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+ tty_ops, xterm_ops;
extern void generic_close(int fd, void *unused);
extern int generic_read(int fd, char *c_out, void *unused);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index b98bdd8e052..59cfa9e0cad 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -21,13 +21,12 @@ struct kern_handlers {
kern_hndl timer_handler;
};
-extern struct kern_handlers handlinfo_kern;
+extern const struct kern_handlers handlinfo_kern;
extern int ncpus;
extern char *linux_prog;
extern char *gdb_init;
extern int kmalloc_ok;
-extern int timer_irq_inited;
extern int jail;
extern int nsyscalls;
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 27bf2f6fbc0..642c9a0320f 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -52,7 +52,7 @@ struct line {
int sigio;
struct work_struct task;
- struct line_driver *driver;
+ const struct line_driver *driver;
int have_irq;
};
@@ -99,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
extern void close_lines(struct line *lines, int nlines);
extern int line_config(struct line *lines, unsigned int sizeof_lines,
- char *str, struct chan_opts *opts);
+ char *str, const struct chan_opts *opts);
extern int line_id(char **str, int *start_out, int *end_out);
extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
extern int line_get_config(char *dev, struct line *lines,
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 1b5c0131a12..e93c6d3e893 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -1,9 +1,12 @@
#ifndef __UML_LONGJMP_H
#define __UML_LONGJMP_H
-#include <setjmp.h>
+#include "sysdep/archsetjmp.h"
#include "os.h"
+extern int setjmp(jmp_buf);
+extern void longjmp(jmp_buf, int);
+
#define UML_LONGJMP(buf, val) do { \
longjmp(*buf, val); \
} while(0)
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index f7de6df60dd..769fba43ee0 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -54,8 +54,8 @@ struct transport {
struct list_head list;
char *name;
int (*setup)(char *, char **, void *);
- struct net_user_info *user;
- struct net_kern_info *kern;
+ const struct net_user_info *user;
+ const struct net_kern_info *kern;
int private_size;
int setup_size;
};
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 800c403920b..47ef7cb49a8 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -26,7 +26,6 @@ struct net_user_info {
extern void ether_user_init(void *data, void *dev);
extern void dev_ip_addr(void *d, unsigned char *bin_buf);
-extern void set_ether_mac(void *d, unsigned char *addr);
extern void iter_addresses(void *d, void (*cb)(unsigned char *,
unsigned char *, void *),
void *arg);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 5316e8a4a4f..120ca21a513 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -14,6 +14,7 @@
#include "skas/mm_id.h"
#include "irq_user.h"
#include "sysdep/tls.h"
+#include "sysdep/archsetjmp.h"
#define OS_TYPE_FILE 1
#define OS_TYPE_DIR 2
@@ -198,7 +199,9 @@ extern long os_ptrace_ldt(long pid, long addr, long data);
extern int os_getpid(void);
extern int os_getpgrp(void);
+#ifdef UML_CONFIG_MODE_TT
extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+#endif
extern void init_new_thread_signals(void);
extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
@@ -216,7 +219,6 @@ extern void os_flush_stdout(void);
*/
extern void forward_ipi(int fd, int pid);
extern void kill_child_dead(int pid);
-extern void stop(void);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern int protect_memory(unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
@@ -276,9 +278,11 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern void switch_timers(int to_real);
extern void idle_sleep(int secs);
+extern int set_interval(int is_virtual);
+#ifdef CONFIG_MODE_TT
extern void enable_timer(void);
+#endif
extern void disable_timer(void);
-extern void user_time_init(void);
extern void uml_idle_timer(void);
extern unsigned long long os_nsecs(void);
@@ -305,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid);
extern void userspace(union uml_pt_regs *regs);
extern void map_stub_pages(int fd, unsigned long code,
unsigned long data, unsigned long stack);
-extern void new_thread(void *stack, void **switch_buf_ptr,
- void **fork_buf_ptr, void (*handler)(int));
-extern void thread_wait(void *sw, void *fb);
-extern void switch_threads(void *me, void *next);
-extern int start_idle_thread(void *stack, void *switch_buf_ptr,
- void **fork_buf_ptr);
+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);
extern void initial_thread_cb_skas(void (*proc)(void *),
void *arg);
extern void halt_skas(void);
@@ -329,6 +330,7 @@ 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);
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 83b688ca198..f845b3629a6 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -7,6 +7,7 @@
#define __REGISTERS_H
#include "sysdep/ptrace.h"
+#include "sysdep/archsetjmp.h"
extern void init_thread_registers(union uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
@@ -15,6 +16,6 @@ extern void save_registers(int pid, union uml_pt_regs *regs);
extern void restore_registers(int pid, union uml_pt_regs *regs);
extern void init_registers(int pid);
extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs);
-extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer);
+extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
#endif
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 853b26f148c..e88926b1607 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -14,8 +14,7 @@ extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
extern int skas_needs_stub;
extern int user_thread(unsigned long stack, int flags);
-extern void new_thread_proc(void *stack, void (*handler)(int sig));
-extern void new_thread_handler(int sig);
+extern void new_thread_handler(void);
extern void handle_syscall(union uml_pt_regs *regs);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
new file mode 100644
index 00000000000..11bafab669e
--- /dev/null
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -0,0 +1,22 @@
+/*
+ * arch/i386/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned int __ebx;
+ unsigned int __esp;
+ unsigned int __ebp;
+ unsigned int __esi;
+ unsigned int __edi;
+ unsigned int __eip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __eip
+#define JB_SP __esp
+
+#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
deleted file mode 100644
index 07518b16213..00000000000
--- a/arch/um/include/sysdep-i386/signal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Licensed under the GPL
- */
-
-#ifndef __I386_SIGNAL_H_
-#define __I386_SIGNAL_H_
-
-#include <signal.h>
-
-#define ARCH_SIGHDLR_PARAM int sig
-
-#define ARCH_GET_SIGCONTEXT(sc, sig) \
- do sc = (struct sigcontext *) (&sig + 1); while(0)
-
-#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/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
new file mode 100644
index 00000000000..9a5e1a6ec80
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -0,0 +1,24 @@
+/*
+ * arch/x86_64/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned long __rbx;
+ unsigned long __rsp;
+ unsigned long __rbp;
+ unsigned long __r12;
+ unsigned long __r13;
+ unsigned long __r14;
+ unsigned long __r15;
+ unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __rip
+#define JB_SP __rsp
+
+#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 8d353f0feec..617bb9efc93 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -50,6 +50,21 @@
#define HOST_FS 25
#define HOST_GS 26
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers. So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
#define REGS_DS(r) ((r)[HOST_DS])
@@ -89,9 +104,12 @@ union uml_pt_regs {
#endif
#ifdef UML_CONFIG_MODE_SKAS
struct skas_regs {
- /* XXX */
- unsigned long regs[27];
- unsigned long fp[65];
+ /* x86_64 ptrace uses sizeof(user_regs_struct) as its register
+ * file size, while i386 uses FRAME_SIZE. Therefore, we need
+ * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE.
+ */
+ unsigned long regs[UM_FRAME_SIZE];
+ unsigned long fp[HOST_FP_SIZE];
struct faultinfo faultinfo;
long syscall;
int is_user;
@@ -120,11 +138,16 @@ extern int mode_tt;
#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_FS_BASE(r) \
+ __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+#define UPT_GS_BASE(r) \
+ __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
#define UPT_ORIG_RAX(r) \
__CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
@@ -183,6 +206,13 @@ struct syscall_args {
case RBP: val = UPT_RBP(regs); break; \
case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
case CS: val = UPT_CS(regs); break; \
+ case SS: val = UPT_SS(regs); break; \
+ case FS_BASE: val = UPT_FS_BASE(regs); break; \
+ case GS_BASE: val = UPT_GS_BASE(regs); break; \
+ case DS: val = UPT_DS(regs); break; \
+ case ES: val = UPT_ES(regs); break; \
+ case FS : val = UPT_FS (regs); break; \
+ case GS: val = UPT_GS(regs); break; \
case EFLAGS: val = UPT_EFLAGS(regs); break; \
default : \
panic("Bad register in UPT_REG : %d\n", reg); \
@@ -214,6 +244,13 @@ struct syscall_args {
case RBP: UPT_RBP(regs) = __upt_val; break; \
case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
case CS: UPT_CS(regs) = __upt_val; break; \
+ case SS: UPT_SS(regs) = __upt_val; break; \
+ case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
+ case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
+ case DS: UPT_DS(regs) = __upt_val; break; \
+ case ES: UPT_ES(regs) = __upt_val; break; \
+ case FS: UPT_FS(regs) = __upt_val; break; \
+ case GS: UPT_GS(regs) = __upt_val; break; \
case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
default : \
panic("Bad register in UPT_SET : %d\n", reg); \
diff --git a/arch/um/include/sysdep-x86_64/sc.h b/arch/um/include/sysdep-x86_64/sc.h
index a160d9fcc59..8aee45b0743 100644
--- a/arch/um/include/sysdep-x86_64/sc.h
+++ b/arch/um/include/sysdep-x86_64/sc.h
@@ -35,11 +35,11 @@
#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
#if 0
#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
#endif
#endif
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
deleted file mode 100644
index 6142897af3d..00000000000
--- a/arch/um/include/sysdep-x86_64/signal.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Licensed under the GPL
- */
-
-#ifndef __X86_64_SIGNAL_H_
-#define __X86_64_SIGNAL_H_
-
-#define ARCH_SIGHDLR_PARAM int sig
-
-#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
- do { \
- struct ucontext *__uc; \
- asm("movq %%rdx, %0" : "=r" (__uc)); \
- sc = (struct sigcontext *) &__uc->uc_mcontext; \
- } while(0)
-
-#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/kernel/Makefile b/arch/um/kernel/Makefile
index a2d93065b2d..6fa63a2a89e 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
- physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \
+ physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
um_arch.o umid.o
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index fc38a6d5906..0561c43b468 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -41,9 +41,11 @@ static long execve1(char *file, char __user * __user *argv,
long error;
#ifdef CONFIG_TTY_LOG
- task_lock(current);
+ mutex_lock(&tty_mutex);
+ task_lock(current); /* FIXME: is this needed ? */
log_exec(argv, current->signal->tty);
task_unlock(current);
+ mutex_unlock(&tty_mutex);
#endif
error = do_execve(file, argv, env, &current->thread.regs);
if (error == 0){
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 2c86e7fdb01..13aa115cd1b 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -5,7 +5,7 @@
#include "linux/module.h"
-extern void __bb_init_func(void *);
+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
@@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init);
extern void __gcov_merge_add(void *) __attribute__((weak));
EXPORT_SYMBOL(__gcov_merge_add);
-
-/*
- * 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/irq.c b/arch/um/kernel/irq.c
index 589c69a7504..ce7f233fc49 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -142,19 +142,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.events = events,
.current_events = 0 } );
- /* Critical section - locked by a spinlock because this stuff can
- * be changed from interrupt handlers. The stuff above is done
- * outside the lock because it allocates memory.
- */
-
- /* Actually, it only looks like it can be called from interrupt
- * context. The culprit is reactivate_fd, which calls
- * maybe_sigio_broken, which calls write_sigio_workaround,
- * which calls activate_fd. However, write_sigio_workaround should
- * only be called once, at boot time. That would make it clear that
- * this is called only from process context, and can be locked with
- * a semaphore.
- */
spin_lock_irqsave(&irq_lock, flags);
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
@@ -165,7 +152,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
}
}
- /*-------------*/
if (type == IRQ_WRITE)
fd = -1;
@@ -198,7 +184,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
spin_lock_irqsave(&irq_lock, flags);
}
- /*-------------*/
*last_irq_ptr = new_fd;
last_irq_ptr = &new_fd->next;
@@ -210,14 +195,14 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
*/
maybe_sigio_broken(fd, (type == IRQ_READ));
- return(0);
+ return 0;
out_unlock:
spin_unlock_irqrestore(&irq_lock, flags);
out_kfree:
kfree(new_fd);
out:
- return(err);
+ return err;
}
static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
@@ -302,10 +287,7 @@ void reactivate_fd(int fd, int irqnum)
os_set_pollfd(i, irq->fd);
spin_unlock_irqrestore(&irq_lock, flags);
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, (irq->type == IRQ_READ));
+ add_sigio_fd(fd);
}
void deactivate_fd(int fd, int irqnum)
@@ -316,11 +298,15 @@ void deactivate_fd(int fd, int irqnum)
spin_lock_irqsave(&irq_lock, flags);
irq = find_irq_by_fd(fd, irqnum, &i);
- if (irq == NULL)
- goto out;
+ if(irq == NULL){
+ spin_unlock_irqrestore(&irq_lock, flags);
+ return;
+ }
+
os_set_pollfd(i, -1);
- out:
spin_unlock_irqrestore(&irq_lock, flags);
+
+ ignore_sigio_fd(fd);
}
int deactivate_all_fds(void)
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index c97045d6d89..f030e44262b 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -21,7 +21,6 @@
#include "mem_user.h"
#include "os.h"
-EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(strncpy_from_user_tt);
EXPORT_SYMBOL(copy_from_user_tt);
EXPORT_SYMBOL(copy_to_user_tt);
#endif
#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strnlen_user_skas);
EXPORT_SYMBOL(strncpy_from_user_skas);
EXPORT_SYMBOL(copy_to_user_skas);
EXPORT_SYMBOL(copy_from_user_skas);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 61280167c56..c95855ba6ab 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -79,8 +79,10 @@ void mem_init(void)
/* this will put all low memory onto the freelists */
totalram_pages = free_all_bootmem();
+#ifdef CONFIG_HIGHMEM
totalhigh_pages = highmem >> PAGE_SHIFT;
totalram_pages += totalhigh_pages;
+#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
printk(KERN_INFO "Memory: %luk available\n",
@@ -221,10 +223,14 @@ void 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<sizeof(zones_size)/sizeof(zones_size[0]);i++)
+ for(i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
- zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+
+ zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+ (uml_physmem >> PAGE_SHIFT);
+#ifdef CONFIG_HIGHMEM
zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
+#endif
free_area_init(zones_size);
/*
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c
index f6a5a502120..fe6c64abda5 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process.c
@@ -1,10 +1,9 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
-#include "linux/config.h"
#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/interrupt.h"
@@ -23,6 +22,7 @@
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "linux/random.h"
+#include "linux/personality.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
@@ -112,11 +112,11 @@ void set_current(void *t)
void *_switch_to(void *prev, void *next, void *last)
{
- struct task_struct *from = prev;
- struct task_struct *to= next;
+ struct task_struct *from = prev;
+ struct task_struct *to= next;
- to->thread.prev_sched = from;
- set_current(to);
+ to->thread.prev_sched = from;
+ set_current(to);
do {
current->thread.saved_task = NULL ;
@@ -127,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last)
prev= current;
} while(current->thread.saved_task);
- return(current->thread.prev_sched);
+ return(current->thread.prev_sched);
}
@@ -141,19 +141,19 @@ void release_thread(struct task_struct *task)
{
CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
}
-
+
void exit_thread(void)
{
unprotect_stack((unsigned long) current_thread);
}
-
+
void *get_current(void)
{
return(current);
}
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
+ unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
int ret;
@@ -182,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
int save_kmalloc_ok = kmalloc_ok;
kmalloc_ok = 0;
- CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
arg);
kmalloc_ok = save_kmalloc_ok;
}
-
+
unsigned long stack_sp(unsigned long page)
{
return(page + PAGE_SIZE - sizeof(void *));
@@ -210,7 +210,7 @@ void default_idle(void)
*/
if(need_resched())
schedule();
-
+
idle_sleep(10);
}
}
@@ -225,7 +225,7 @@ int page_size(void)
return(PAGE_SIZE);
}
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
pgd_t *pgd;
@@ -234,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte;
pte_t ptent;
- if(task->mm == NULL)
+ if(task->mm == NULL)
return(ERR_PTR(-EINVAL));
pgd = pgd_offset(task->mm, addr);
if(!pgd_present(*pgd))
@@ -245,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
return(ERR_PTR(-EINVAL));
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd))
+ if(!pmd_present(*pmd))
return(ERR_PTR(-EINVAL));
pte = pte_offset_kernel(pmd, addr);
@@ -270,7 +270,7 @@ char *current_cmd(void)
void force_sigbus(void)
{
- printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
current->pid);
lock_kernel();
sigaddset(&current->pending.signal, SIGBUS);
@@ -476,7 +476,7 @@ int singlestepping(void * t)
#ifndef arch_align_stack
unsigned long arch_align_stack(unsigned long sp)
{
- if (randomize_va_space)
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 3ef73bf2e78..f602623644a 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -22,7 +22,7 @@ static void kill_idlers(int me)
struct task_struct *p;
int i;
- for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
p = idle_threads[i];
if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
os_kill_process(p->thread.mode.tt.extern_pid, 0);
@@ -62,14 +62,3 @@ void machine_halt(void)
{
machine_power_off();
}
-
-/*
- * 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/skas/Makefile b/arch/um/kernel/skas/Makefile
index ea3a8e409a6..3e3fa7e7e3c 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,8 +3,7 @@
# Licensed under the GPL
#
-obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
- syscall.o tlb.o uaccess.o
+obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
# clone.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644
index 00000000000..54b79595137
--- /dev/null
+++ b/arch/um/kernel/skas/exec.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/current.h"
+#include "asm/page.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/mmu_context.h"
+#include "tlb.h"
+#include "skas.h"
+#include "um_mmu.h"
+#include "os.h"
+
+void flush_thread_skas(void)
+{
+ force_flush_all();
+ switch_mm_skas(&current->mm->context.skas.id);
+}
+
+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp)
+{
+ set_fs(USER_DS);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
+}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644
index 77ed7bbab21..00000000000
--- a/arch/um/kernel/skas/exec_kern.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
- force_flush_all();
- switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
-}
-
-/*
- * 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/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 624ca238d1f..79c22707a63 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -55,7 +55,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
* destroy_context_skas.
*/
- mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
+ mm->context.skas.last_page_table = pmd_page_vaddr(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644
index 00000000000..ae4fa71d3b8
--- /dev/null
+++ b/arch/um/kernel/skas/process.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "os.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "kern.h"
+#include "mode.h"
+#include "registers.h"
+
+void switch_to_skas(void *prev, void *next)
+{
+ struct task_struct *from, *to;
+
+ from = prev;
+ to = next;
+
+ /* XXX need to check runqueues[cpu].idle */
+ if(current->pid == 0)
+ switch_timers(0);
+
+ switch_threads(&from->thread.mode.skas.switch_buf,
+ &to->thread.mode.skas.switch_buf);
+
+ arch_switch_to_skas(current->thread.prev_sched, current);
+
+ if(current->pid == 0)
+ switch_timers(1);
+}
+
+extern void schedule_tail(struct task_struct *prev);
+
+/* This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
+{
+ int (*fn)(void *), n;
+ void *arg;
+
+ if(current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+
+ /* The return value is 1 if the kernel thread execs a process,
+ * 0 if it just exits
+ */
+ n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+ if(n == 1){
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
+ userspace(&current->thread.regs.regs);
+ }
+ else do_exit(0);
+}
+
+void release_thread_skas(struct task_struct *task)
+{
+}
+
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
+{
+ force_flush_all();
+ if(current->thread.prev_sched == NULL)
+ panic("blech");
+
+ schedule_tail(current->thread.prev_sched);
+
+ /* XXX: if interrupt_end() calls schedule, this call to
+ * arch_switch_to_skas isn't needed. We could want to apply this to
+ * improve performance. -bb */
+ arch_switch_to_skas(current->thread.prev_sched, current);
+
+ current->thread.prev_sched = NULL;
+
+/* Handle any immediate reschedules or signals */
+ interrupt_end();
+
+ userspace(&current->thread.regs.regs);
+}
+
+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct * p,
+ struct pt_regs *regs)
+{
+ void (*handler)(void);
+
+ if(current->thread.forking){
+ memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
+ sizeof(p->thread.regs.regs.skas));
+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
+ if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
+
+ handler = fork_handler;
+
+ arch_copy_thread(&current->thread.arch, &p->thread.arch);
+ }
+ else {
+ init_thread_registers(&p->thread.regs.regs);
+ p->thread.request.u.thread = current->thread.request.u.thread;
+ handler = new_thread_handler;
+ }
+
+ new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
+ handler);
+ return(0);
+}
+
+int new_mm(unsigned long stack)
+{
+ int fd;
+
+ 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, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+
+ return(fd);
+}
+
+void init_idle_skas(void)
+{
+ cpu_tasks[current_thread->cpu].pid = os_getpid();
+ default_idle();
+}
+
+extern void start_kernel(void);
+
+static int start_kernel_proc(void *unused)
+{
+ int pid;
+
+ block_signals();
+ pid = os_getpid();
+
+ cpu_tasks[0].pid = pid;
+ cpu_tasks[0].task = current;
+#ifdef CONFIG_SMP
+ cpu_online_map = cpumask_of_cpu(0);
+#endif
+ start_kernel();
+ return(0);
+}
+
+extern int userspace_pid[];
+
+int start_uml_skas(void)
+{
+ if(proc_mm)
+ userspace_pid[0] = start_userspace(0);
+
+ init_new_thread_signals();
+
+ init_task.thread.request.u.thread.proc = start_kernel_proc;
+ init_task.thread.request.u.thread.arg = NULL;
+ return(start_idle_thread(task_stack_page(&init_task),
+ &init_task.thread.mode.skas.switch_buf));
+}
+
+int external_pid_skas(struct task_struct *task)
+{
+#warning Need to look up userspace_pid by cpu
+ return(userspace_pid[0]);
+}
+
+int thread_pid_skas(struct task_struct *task)
+{
+#warning Need to look up userspace_pid by cpu
+ return(userspace_pid[0]);
+}
+
+void kill_off_processes_skas(void)
+{
+ if(proc_mm)
+#warning need to loop over userspace_pids in kill_off_processes_skas
+ os_kill_ptraced_process(userspace_pid[0], 1);
+ else {
+ struct task_struct *p;
+ int pid, me;
+
+ me = os_getpid();
+ for_each_process(p){
+ if(p->mm == NULL)
+ continue;
+
+ pid = p->mm->context.skas.id.u.pid;
+ os_kill_ptraced_process(pid, 1);
+ }
+ }
+}
+
+unsigned long current_stub_stack(void)
+{
+ if(current->mm == NULL)
+ return(0);
+
+ return(current->mm->context.skas.id.stack);
+}
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 55caeec8b25..0f3d5d084dc 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,227 +1,484 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
+#include "linux/config.h"
+#include "linux/kernel.h"
#include "linux/sched.h"
+#include "linux/interrupt.h"
+#include "linux/string.h"
+#include "linux/mm.h"
#include "linux/slab.h"
-#include "linux/ptrace.h"
-#include "linux/proc_fs.h"
-#include "linux/file.h"
-#include "linux/errno.h"
+#include "linux/utsname.h"
+#include "linux/fs.h"
+#include "linux/utime.h"
+#include "linux/smp_lock.h"
+#include "linux/module.h"
#include "linux/init.h"
+#include "linux/capability.h"
+#include "linux/vmalloc.h"
+#include "linux/spinlock.h"
+#include "linux/proc_fs.h"
+#include "linux/ptrace.h"
+#include "linux/random.h"
+#include "linux/personality.h"
+#include "asm/unistd.h"
+#include "asm/mman.h"
+#include "asm/segment.h"
+#include "asm/stat.h"
+#include "asm/pgtable.h"
+#include "asm/processor.h"
+#include "asm/tlbflush.h"
#include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "kern_util.h"
-#include "skas.h"
-#include "os.h"
+#include "asm/user.h"
#include "user_util.h"
-#include "tlb.h"
+#include "kern_util.h"
#include "kern.h"
+#include "signal_kern.h"
+#include "init.h"
+#include "irq_user.h"
+#include "mem_user.h"
+#include "tlb.h"
+#include "frame_kern.h"
+#include "sigcontext.h"
+#include "os.h"
#include "mode.h"
-#include "registers.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
+
+/* This is a per-cpu array. A processor only modifies its entry and it only
+ * cares about its entry, so it's OK if another processor is modifying its
+ * entry.
+ */
+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
+
+int external_pid(void *t)
+{
+ struct task_struct *task = t ? t : current;
+
+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
+}
+
+int pid_to_processor_id(int pid)
+{
+ int i;
+
+ for(i = 0; i < ncpus; i++){
+ if(cpu_tasks[i].pid == pid) return(i);
+ }
+ return(-1);
+}
+
+void free_stack(unsigned long stack, int order)
+{
+ free_pages(stack, order);
+}
+
+unsigned long alloc_stack(int order, int atomic)
+{
+ unsigned long page;
+ gfp_t flags = GFP_KERNEL;
+
+ if (atomic)
+ flags = GFP_ATOMIC;
+ page = __get_free_pages(flags, order);
+ if(page == 0)
+ return(0);
+ stack_protections(page);
+ return(page);
+}
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ int pid;
+
+ current->thread.request.u.thread.proc = fn;
+ current->thread.request.u.thread.arg = arg;
+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
+ &current->thread.regs, 0, NULL, NULL);
+ if(pid < 0)
+ panic("do_fork failed in kernel_thread, errno = %d", pid);
+ return(pid);
+}
-void switch_to_skas(void *prev, void *next)
+void set_current(void *t)
{
- struct task_struct *from, *to;
+ struct task_struct *task = t;
- from = prev;
- to = next;
+ cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
+ { external_pid(task), task });
+}
- /* XXX need to check runqueues[cpu].idle */
- if(current->pid == 0)
- switch_timers(0);
+void *_switch_to(void *prev, void *next, void *last)
+{
+ struct task_struct *from = prev;
+ struct task_struct *to= next;
- switch_threads(&from->thread.mode.skas.switch_buf,
- to->thread.mode.skas.switch_buf);
+ to->thread.prev_sched = from;
+ set_current(to);
- arch_switch_to_skas(current->thread.prev_sched, current);
+ do {
+ current->thread.saved_task = NULL ;
+ CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+ if(current->thread.saved_task)
+ show_regs(&(current->thread.regs));
+ next= current->thread.saved_task;
+ prev= current;
+ } while(current->thread.saved_task);
+
+ return(current->thread.prev_sched);
- if(current->pid == 0)
- switch_timers(1);
}
-extern void schedule_tail(struct task_struct *prev);
+void interrupt_end(void)
+{
+ if(need_resched()) schedule();
+ if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
+}
-void new_thread_handler(int sig)
+void release_thread(struct task_struct *task)
{
- int (*fn)(void *), n;
- void *arg;
+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
+}
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
- os_usr1_signal(1);
- thread_wait(&current->thread.mode.skas.switch_buf,
- current->thread.mode.skas.fork_buf);
+void exit_thread(void)
+{
+ unprotect_stack((unsigned long) current_thread);
+}
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
+void *get_current(void)
+{
+ return(current);
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct * p,
+ struct pt_regs *regs)
+{
+ int ret;
- /* The return value is 1 if the kernel thread execs a process,
- * 0 if it just exits
+ p->thread = (struct thread_struct) INIT_THREAD;
+ ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+ clone_flags, sp, stack_top, p, regs);
+
+ if (ret || !current->thread.forking)
+ goto out;
+
+ clear_flushed_tls(p);
+
+ /*
+ * Set a new TLS for the child thread?
*/
- n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
- if(n == 1){
- /* Handle any immediate reschedules or signals */
- interrupt_end();
- userspace(&current->thread.regs.regs);
+ if (clone_flags & CLONE_SETTLS)
+ ret = arch_copy_tls(p);
+
+out:
+ return ret;
+}
+
+void initial_thread_cb(void (*proc)(void *), void *arg)
+{
+ int save_kmalloc_ok = kmalloc_ok;
+
+ kmalloc_ok = 0;
+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+ arg);
+ kmalloc_ok = save_kmalloc_ok;
+}
+
+unsigned long stack_sp(unsigned long page)
+{
+ return(page + PAGE_SIZE - sizeof(void *));
+}
+
+int current_pid(void)
+{
+ return(current->pid);
+}
+
+void default_idle(void)
+{
+ CHOOSE_MODE(uml_idle_timer(), (void) 0);
+
+ while(1){
+ /* endless idle loop with no priority at all */
+
+ /*
+ * although we are an idle CPU, we do not want to
+ * get into the scheduler unnecessarily.
+ */
+ if(need_resched())
+ schedule();
+
+ idle_sleep(10);
}
- else do_exit(0);
}
-void new_thread_proc(void *stack, void (*handler)(int sig))
+void cpu_idle(void)
{
- init_new_thread_stack(stack, handler);
- os_usr1_process(os_getpid());
+ CHOOSE_MODE(init_idle_tt(), init_idle_skas());
}
-void release_thread_skas(struct task_struct *task)
+int page_size(void)
{
+ return(PAGE_SIZE);
}
-void fork_handler(int sig)
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+ pte_t *pte_out)
{
- os_usr1_signal(1);
- thread_wait(&current->thread.mode.skas.switch_buf,
- current->thread.mode.skas.fork_buf);
-
- force_flush_all();
- if(current->thread.prev_sched == NULL)
- panic("blech");
+ 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));
+}
- schedule_tail(current->thread.prev_sched);
+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
+}
- /* XXX: if interrupt_end() calls schedule, this call to
- * arch_switch_to_skas isn't needed. We could want to apply this to
- * improve performance. -bb */
- arch_switch_to_skas(current->thread.prev_sched, current);
+void force_sigbus(void)
+{
+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
+ current->pid);
+ lock_kernel();
+ sigaddset(&current->pending.signal, SIGBUS);
+ recalc_sigpending();
+ current->flags |= PF_SIGNALED;
+ do_exit(SIGBUS | 0x80);
+}
- current->thread.prev_sched = NULL;
+void dump_thread(struct pt_regs *regs, struct user *u)
+{
+}
-/* Handle any immediate reschedules or signals */
- interrupt_end();
+void enable_hlt(void)
+{
+ panic("enable_hlt");
+}
+
+EXPORT_SYMBOL(enable_hlt);
- userspace(&current->thread.regs.regs);
+void disable_hlt(void)
+{
+ panic("disable_hlt");
}
-int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
+EXPORT_SYMBOL(disable_hlt);
+
+void *um_kmalloc(int size)
{
- void (*handler)(int);
+ return kmalloc(size, GFP_KERNEL);
+}
- if(current->thread.forking){
- memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
- sizeof(p->thread.regs.regs.skas));
- REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
- if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
+void *um_kmalloc_atomic(int size)
+{
+ return kmalloc(size, GFP_ATOMIC);
+}
- handler = fork_handler;
+void *um_vmalloc(int size)
+{
+ return vmalloc(size);
+}
- arch_copy_thread(&current->thread.arch, &p->thread.arch);
- }
- else {
- init_thread_registers(&p->thread.regs.regs);
- p->thread.request.u.thread = current->thread.request.u.thread;
- handler = new_thread_handler;
- }
+void *um_vmalloc_atomic(int size)
+{
+ return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
+}
- new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
- &p->thread.mode.skas.fork_buf, handler);
- return(0);
+int __cant_sleep(void) {
+ return in_atomic() || irqs_disabled() || in_interrupt();
+ /* Is in_interrupt() really needed? */
+}
+
+unsigned long get_fault_addr(void)
+{
+ return((unsigned long) current->thread.fault_addr);
}
-int new_mm(unsigned long stack)
+EXPORT_SYMBOL(get_fault_addr);
+
+void not_implemented(void)
{
- int fd;
+ printk(KERN_DEBUG "Something isn't implemented in here\n");
+}
- fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
- if(fd < 0)
- return(fd);
+EXPORT_SYMBOL(not_implemented);
- if(skas_needs_stub)
- map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+int user_context(unsigned long sp)
+{
+ unsigned long stack;
- return(fd);
+ stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
+ return(stack != (unsigned long) current_thread);
}
-void init_idle_skas(void)
+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
+
+void do_uml_exitcalls(void)
{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
- default_idle();
+ exitcall_t *call;
+
+ call = &__uml_exitcall_end;
+ while (--call >= &__uml_exitcall_begin)
+ (*call)();
}
-extern void start_kernel(void);
+char *uml_strdup(char *string)
+{
+ return kstrdup(string, GFP_KERNEL);
+}
-static int start_kernel_proc(void *unused)
+int copy_to_user_proc(void __user *to, void *from, int size)
{
- int pid;
+ return(copy_to_user(to, from, size));
+}
+
+int copy_from_user_proc(void *to, void __user *from, int size)
+{
+ return(copy_from_user(to, from, size));
+}
+
+int clear_user_proc(void __user *buf, int size)
+{
+ return(clear_user(buf, size));
+}
- block_signals();
- pid = os_getpid();
+int strlen_user_proc(char __user *str)
+{
+ return(strlen_user(str));
+}
- cpu_tasks[0].pid = pid;
- cpu_tasks[0].task = current;
+int smp_sigio_handler(void)
+{
#ifdef CONFIG_SMP
- cpu_online_map = cpumask_of_cpu(0);
+ int cpu = current_thread->cpu;
+ IPI_handler(cpu);
+ if(cpu != 0)
+ return(1);
#endif
- start_kernel();
return(0);
}
-extern int userspace_pid[];
-
-int start_uml_skas(void)
+int cpu(void)
{
- if(proc_mm)
- userspace_pid[0] = start_userspace(0);
+ return(current_thread->cpu);
+}
+
+static atomic_t using_sysemu = ATOMIC_INIT(0);
+int sysemu_supported;
- init_new_thread_signals();
+void set_using_sysemu(int value)
+{
+ if (value > sysemu_supported)
+ return;
+ atomic_set(&using_sysemu, value);
+}
- init_task.thread.request.u.thread.proc = start_kernel_proc;
- init_task.thread.request.u.thread.arg = NULL;
- return(start_idle_thread(task_stack_page(&init_task),
- &init_task.thread.mode.skas.switch_buf,
- &init_task.thread.mode.skas.fork_buf));
+int get_using_sysemu(void)
+{
+ return atomic_read(&using_sysemu);
}
-int external_pid_skas(struct task_struct *task)
+static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
-#warning Need to look up userspace_pid by cpu
- return(userspace_pid[0]);
+ if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+ *eof = 1;
+
+ return strlen(buf);
}
-int thread_pid_skas(struct task_struct *task)
+static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
{
-#warning Need to look up userspace_pid by cpu
- return(userspace_pid[0]);
+ char tmp[2];
+
+ if (copy_from_user(tmp, buf, 1))
+ return -EFAULT;
+
+ if (tmp[0] >= '0' && tmp[0] <= '2')
+ set_using_sysemu(tmp[0] - '0');
+ return count; /*We use the first char, but pretend to write everything*/
}
-void kill_off_processes_skas(void)
+int __init make_proc_sysemu(void)
{
- if(proc_mm)
-#warning need to loop over userspace_pids in kill_off_processes_skas
- os_kill_ptraced_process(userspace_pid[0], 1);
- else {
- struct task_struct *p;
- int pid, me;
+ struct proc_dir_entry *ent;
+ if (!sysemu_supported)
+ return 0;
- me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
- continue;
+ ent = create_proc_entry("sysemu", 0600, &proc_root);
- pid = p->mm->context.skas.id.u.pid;
- os_kill_ptraced_process(pid, 1);
- }
+ if (ent == NULL)
+ {
+ printk(KERN_WARNING "Failed to register /proc/sysemu\n");
+ return(0);
}
+
+ ent->read_proc = proc_read_sysemu;
+ ent->write_proc = proc_write_sysemu;
+
+ return 0;
}
-unsigned long current_stub_stack(void)
+late_initcall(make_proc_sysemu);
+
+int singlestepping(void * t)
{
- if(current->mm == NULL)
+ struct task_struct *task = t ? t : current;
+
+ if ( ! (task->ptrace & PT_DTRACE) )
return(0);
- return(current->mm->context.skas.id.stack);
+ if (task->thread.singlestep_syscall)
+ return(1);
+
+ return 2;
+}
+
+/*
+ * Only x86 and x86_64 have an arch_align_stack().
+ * All other arches have "#define arch_align_stack(x) (x)"
+ * in their asm/system.h
+ * As this is included in UML from asm-um/system-generic.h,
+ * we can use it to behave as the subarch does.
+ */
+#ifndef arch_align_stack
+unsigned long arch_align_stack(unsigned long sp)
+{
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
}
+#endif
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 552ca1cb984..820affbf3e1 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -35,9 +35,6 @@ unsigned long long sched_clock(void)
return (unsigned long long)jiffies_64 * (1000000000 / HZ);
}
-/* Changed at early boot */
-int timer_irq_inited = 0;
-
static unsigned long long prev_nsecs;
#ifdef CONFIG_UML_REAL_TIME_CLOCK
static long long delta; /* Deviation per interval */
@@ -98,7 +95,7 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
do_timer(regs);
- nsecs = get_time() + local_offset;
+ nsecs = get_time();
xtime.tv_sec = nsecs / NSEC_PER_SEC;
xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
@@ -113,12 +110,13 @@ static void register_timer(void)
err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
if(err != 0)
- printk(KERN_ERR "timer_init : request_irq failed - "
+ printk(KERN_ERR "register_timer : request_irq failed - "
"errno = %d\n", -err);
- timer_irq_inited = 1;
-
- user_time_init();
+ err = set_interval(1);
+ if(err != 0)
+ printk(KERN_ERR "register_timer : set_interval failed - "
+ "errno = %d\n", -err);
}
extern void (*late_time_init)(void);
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f5b0636f9ad..54a5ff25645 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -16,12 +16,12 @@
#include "os.h"
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x, struct host_vm_op *ops, int *index,
+ int r, int w, int x, struct host_vm_op *ops, int *index,
int last_filled, union mm_context *mmu, void **flush,
int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
- __u64 offset;
+ __u64 offset;
struct host_vm_op *last;
int fd, ret = 0;
@@ -89,7 +89,7 @@ static int add_munmap(unsigned long addr, unsigned long len,
static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
int x, struct host_vm_op *ops, int *index,
int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
struct host_vm_op *last;
@@ -124,105 +124,105 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force,
+ unsigned long end_addr, int force,
int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
- pgd_t *npgd;
- pud_t *npud;
- pmd_t *npmd;
- pte_t *npte;
- union mm_context *mmu = &mm->context;
- unsigned long addr, end;
- int r, w, x;
- struct host_vm_op ops[1];
- void *flush = NULL;
- int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1;
- int ret = 0;
-
- if(mm == NULL) return;
-
- ops[0].type = NONE;
- for(addr = start_addr; addr < end_addr && !ret;){
- npgd = pgd_offset(mm, addr);
- if(!pgd_present(*npgd)){
- end = ADD_ROUND(addr, PGDIR_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pgd_newpage(*npgd)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pgd_mkuptodate(*npgd);
- }
- addr = end;
- continue;
- }
-
- npud = pud_offset(npgd, addr);
- if(!pud_present(*npud)){
- end = ADD_ROUND(addr, PUD_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pud_newpage(*npud)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pud_mkuptodate(*npud);
- }
- addr = end;
- continue;
- }
-
- npmd = pmd_offset(npud, addr);
- if(!pmd_present(*npmd)){
- end = ADD_ROUND(addr, PMD_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pmd_newpage(*npmd)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pmd_mkuptodate(*npmd);
- }
- addr = end;
- continue;
- }
-
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
+ pgd_t *npgd;
+ pud_t *npud;
+ pmd_t *npmd;
+ pte_t *npte;
+ union mm_context *mmu = &mm->context;
+ unsigned long addr, end;
+ int r, w, x;
+ struct host_vm_op ops[1];
+ void *flush = NULL;
+ int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
+ int ret = 0;
+
+ if(mm == NULL)
+ return;
+
+ ops[0].type = NONE;
+ for(addr = start_addr; addr < end_addr && !ret;){
+ npgd = pgd_offset(mm, addr);
+ if(!pgd_present(*npgd)){
+ end = ADD_ROUND(addr, PGDIR_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pgd_newpage(*npgd)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pgd_mkuptodate(*npgd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npud = pud_offset(npgd, addr);
+ if(!pud_present(*npud)){
+ end = ADD_ROUND(addr, PUD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pud_newpage(*npud)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pud_mkuptodate(*npud);
+ }
+ addr = end;
+ continue;
+ }
+
+ npmd = pmd_offset(npud, addr);
+ if(!pmd_present(*npmd)){
+ end = ADD_ROUND(addr, PMD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pmd_newpage(*npmd)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pmd_mkuptodate(*npmd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
if (!pte_young(*npte)) {
r = 0;
w = 0;
} else if (!pte_dirty(*npte)) {
w = 0;
}
- if(force || pte_newpage(*npte)){
- if(pte_present(*npte))
- ret = add_mmap(addr,
- pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
+ if(force || pte_newpage(*npte)){
+ if(pte_present(*npte))
+ ret = add_mmap(addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
else ret = add_munmap(addr, PAGE_SIZE, ops,
&op_index, last_op, mmu,
&flush, do_ops);
- }
- else if(pte_newprot(*npte))
+ }
+ else if(pte_newprot(*npte))
ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
&op_index, last_op, mmu,
&flush, do_ops);
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
- }
-
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
+ }
if(!ret)
ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
- /* This is not an else because ret is modified above */
+/* This is not an else because ret is modified above */
if(ret) {
printk("fix_range_common: failed, killing current process\n");
force_sig(SIGKILL, current);
@@ -231,160 +231,160 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
{
- struct mm_struct *mm;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, last;
- int updated = 0, err;
-
- mm = &init_mm;
- for(addr = start; addr < end;){
- pgd = pgd_offset(mm, addr);
- if(!pgd_present(*pgd)){
- last = ADD_ROUND(addr, PGDIR_SIZE);
- if(last > end)
- last = end;
- if(pgd_newpage(*pgd)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
- last = ADD_ROUND(addr, PUD_SIZE);
- if(last > end)
- last = end;
- if(pud_newpage(*pud)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
- last = ADD_ROUND(addr, PMD_SIZE);
- if(last > end)
- last = end;
- if(pmd_newpage(*pmd)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- if(pte_present(*pte))
- map_memory(addr,
- pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
- }
- else if(pte_newprot(*pte)){
- updated = 1;
- os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
- }
- addr += PAGE_SIZE;
- }
- return(updated);
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr, last;
+ int updated = 0, err;
+
+ mm = &init_mm;
+ for(addr = start; addr < end;){
+ pgd = pgd_offset(mm, addr);
+ if(!pgd_present(*pgd)){
+ last = ADD_ROUND(addr, PGDIR_SIZE);
+ if(last > end)
+ last = end;
+ if(pgd_newpage(*pgd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud)){
+ last = ADD_ROUND(addr, PUD_SIZE);
+ if(last > end)
+ last = end;
+ if(pud_newpage(*pud)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, addr);
+ if(!pmd_present(*pmd)){
+ last = ADD_ROUND(addr, PMD_SIZE);
+ if(last > end)
+ last = end;
+ if(pmd_newpage(*pmd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
+ }
+ return(updated);
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
{
- return(pgd_offset(mm, address));
+ return(pgd_offset(mm, address));
}
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pud_offset(pgd, address));
+ return(pud_offset(pgd, address));
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
- return(pmd_offset(pud, address));
+ return(pmd_offset(pud, address));
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
{
- return(pte_offset_kernel(pmd, address));
+ return(pte_offset_kernel(pmd, address));
}
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
{
- pgd_t *pgd = pgd_offset(task->mm, addr);
- pud_t *pud = pud_offset(pgd, addr);
- pmd_t *pmd = pmd_offset(pud, addr);
+ pgd_t *pgd = pgd_offset(task->mm, addr);
+ pud_t *pud = pud_offset(pgd, addr);
+ pmd_t *pmd = pmd_offset(pud, addr);
- return(pte_offset_map(pmd, addr));
+ return(pte_offset_map(pmd, addr));
}
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
{
- address &= PAGE_MASK;
- flush_tlb_range(vma, address, address + PAGE_SIZE);
+ address &= PAGE_MASK;
+ flush_tlb_range(vma, address, address + PAGE_SIZE);
}
void flush_tlb_all(void)
{
- flush_tlb_mm(current->mm);
+ flush_tlb_mm(current->mm);
}
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
- flush_tlb_kernel_range_common, start, end);
+ CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
+ flush_tlb_kernel_range_common, start, end);
}
void flush_tlb_kernel_vm(void)
{
- CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
- flush_tlb_kernel_range_common(start_vm, end_vm));
+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
+ flush_tlb_kernel_range_common(start_vm, end_vm));
}
void __flush_tlb_one(unsigned long addr)
{
- CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
}
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
- end);
+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+ end);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
}
void force_flush_all(void)
{
- CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index ac70fa5a2e2..61a23fff439 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs)
segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
}
-struct kern_handlers handlinfo_kern = {
- .relay_signal = relay_signal,
- .winch = winch,
- .bus_handler = relay_signal,
- .page_fault = segv_handler,
- .sigio_handler = sigio_handler,
- .timer_handler = timer_handler
-};
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -227,9 +219,16 @@ void bad_segv(struct faultinfo fi, unsigned long ip)
void relay_signal(int sig, union uml_pt_regs *regs)
{
- if(arch_handle_signal(sig, regs)) return;
- if(!UPT_IS_USER(regs))
+ if(arch_handle_signal(sig, regs))
+ return;
+
+ if(!UPT_IS_USER(regs)){
+ if(sig == SIGBUS)
+ printk("Bus error - the /dev/shm or /tmp mount likely "
+ "just ran out of space\n");
panic("Kernel mode signal %d", sig);
+ }
+
current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
@@ -246,6 +245,15 @@ void winch(int sig, union 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/um_arch.c b/arch/um/kernel/um_arch.c
index 7896cf98232..55005710dcb 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index f4bfc4c7cca..b4183929b32 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,15 +4,19 @@
#
obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
- signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+ signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
+
+obj-$(CONFIG_MODE_TT) += tt.o
+user-objs-$(CONFIG_MODE_TT) += tt.o
+
obj-$(CONFIG_TTY_LOG) += tty_log.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
- process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+ process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
index b84f6c4740f..57ecdaf2f67 100644
--- a/arch/um/os-Linux/drivers/etap.h
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -13,7 +13,7 @@ struct ethertap_data {
void *dev;
};
-extern struct net_user_info ethertap_user_info;
+extern const struct net_user_info ethertap_user_info;
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 768606bec23..16385e2ada8 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
return(net_send(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info ethertap_kern_info = {
+const struct net_kern_info ethertap_kern_info = {
.init = etap_init,
.protocol = eth_protocol,
.read = etap_read,
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 8f49507e64e..f559bdf746e 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
etap_close_addr(addr, netmask, &pri->control_fd);
}
-struct net_user_info ethertap_user_info = {
+const struct net_user_info ethertap_user_info = {
.init = etap_user_init,
.open = etap_open,
.close = etap_close,
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
index 25d4a286881..d3e8d3af624 100644
--- a/arch/um/os-Linux/drivers/tuntap.h
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -16,7 +16,7 @@ struct tuntap_data {
void *dev;
};
-extern struct net_user_info tuntap_user_info;
+extern const struct net_user_info tuntap_user_info;
#endif
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 190009a6f89..0edbac63c52 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
return(net_write(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info tuntap_kern_info = {
+const struct net_kern_info tuntap_kern_info = {
.init = tuntap_init,
.protocol = eth_protocol,
.read = tuntap_read,
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 87c3aa0252d..e846b23f755 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info tuntap_user_info = {
+const struct net_user_info tuntap_user_info = {
.init = tuntap_user_init,
.open = tuntap_open,
.close = tuntap_close,
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6987d1d247a..cd15b9df5b5 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -42,7 +42,7 @@ static int helper_child(void *arg)
if(data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
- errval = errno;
+ errval = -errno;
printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
@@ -62,7 +62,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
stack = *stack_out;
else stack = alloc_stack(0, __cant_sleep());
if(stack == 0)
- return(-ENOMEM);
+ return -ENOMEM;
ret = os_pipe(fds, 1, 0);
if(ret < 0){
@@ -95,16 +95,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
/* Read the errno value from the child, if the exec failed, or get 0 if
* the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if (n < 0) {
- printk("run_helper : read on pipe failed, ret = %d\n", -n);
- ret = n;
- kill(pid, SIGKILL);
- CATCH_EINTR(waitpid(pid, NULL, 0));
- } else if(n != 0){
- CATCH_EINTR(n = waitpid(pid, NULL, 0));
- ret = -errno;
- } else {
+ if(n == 0)
ret = pid;
+ else {
+ if(n < 0){
+ printk("run_helper : read on pipe failed, ret = %d\n",
+ -n);
+ ret = n;
+ kill(pid, SIGKILL);
+ }
+ CATCH_EINTR(waitpid(pid, NULL, 0));
}
out_close:
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 7555bf9c33d..a97206df5b5 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -132,7 +132,7 @@ void os_set_pollfd(int i, int fd)
void os_set_ioignore(void)
{
- set_handler(SIGIO, SIG_IGN, 0, -1);
+ signal(SIGIO, SIG_IGN);
}
void init_irq_signals(int on_sigstack)
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 90912aaca7a..d1c5670787d 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -67,13 +67,32 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
uml_cleanup();
exit(1);
}
+static void install_fatal_handler(int sig)
+{
+ struct sigaction action;
+
+ /* All signals are enabled in this handler ... */
+ sigemptyset(&action.sa_mask);
+
+ /* ... including the signal being handled, plus we want the
+ * handler reset to the default behavior, so that if an exit
+ * handler is hanging for some reason, the UML will just die
+ * after this signal is sent a second time.
+ */
+ action.sa_flags = SA_RESETHAND | SA_NODEFER;
+ action.sa_restorer = NULL;
+ action.sa_handler = last_ditch_exit;
+ if(sigaction(sig, &action, NULL) < 0){
+ printf("failed to install handler for signal %d - errno = %d\n",
+ errno);
+ exit(1);
+ }
+}
+
#define UML_LIB_PATH ":/usr/lib/uml"
static void setup_env_path(void)
@@ -158,9 +177,12 @@ int main(int argc, char **argv, char **envp)
}
new_argv[argc] = NULL;
- set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ /* Allow these signals to bring down a UML if all other
+ * methods of control fail.
+ */
+ install_fatal_handler(SIGINT);
+ install_fatal_handler(SIGTERM);
+ install_fatal_handler(SIGHUP);
scan_elf_aux( envp);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 560c8063c77..b170b4704dc 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -114,14 +114,14 @@ static void which_tmpdir(void)
}
while(1){
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
break;
if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
goto found;
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ found = next(fd, buf, ARRAY_SIZE(buf), '\n');
if(found != 1)
break;
}
@@ -135,7 +135,7 @@ err:
return;
found:
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
goto err;
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index b98d3ca2cd1..ff203625a4b 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,7 +7,6 @@
#include <stdio.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
@@ -247,7 +246,17 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
set_sigstack(sig_stack, pages * page_size());
flags = SA_ONSTACK;
}
- if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
+ if(usr1_handler){
+ struct sigaction sa;
+
+ sa.sa_handler = usr1_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = flags;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGUSR1, &sa, NULL) < 0)
+ panic("init_new_thread_stack - sigaction failed - "
+ "errno = %d\n", errno);
+ }
}
void init_new_thread_signals(void)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 0ecac563c7b..f6457765b17 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -43,17 +43,9 @@ struct pollfds {
/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
-static struct pollfds current_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
-
-static struct pollfds next_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
+static struct pollfds current_poll;
+static struct pollfds next_poll;
+static struct pollfds all_sigio_fds;
static int write_sigio_thread(void *unused)
{
@@ -78,7 +70,8 @@ static int write_sigio_thread(void *unused)
n = os_read_file(sigio_private[1], &c, sizeof(c));
if(n != sizeof(c))
printk("write_sigio_thread : "
- "read failed, err = %d\n", -n);
+ "read on socket failed, "
+ "err = %d\n", -n);
tmp = current_poll;
current_poll = next_poll;
next_poll = tmp;
@@ -93,35 +86,36 @@ static int write_sigio_thread(void *unused)
n = os_write_file(respond_fd, &c, sizeof(c));
if(n != sizeof(c))
- printk("write_sigio_thread : write failed, "
- "err = %d\n", -n);
+ printk("write_sigio_thread : write on socket "
+ "failed, err = %d\n", -n);
}
}
return 0;
}
-static int need_poll(int n)
+static int need_poll(struct pollfds *polls, int n)
{
- if(n <= next_poll.size){
- next_poll.used = n;
- return(0);
+ if(n <= polls->size){
+ polls->used = n;
+ return 0;
}
- kfree(next_poll.poll);
- next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
- if(next_poll.poll == NULL){
+ kfree(polls->poll);
+ polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
+ if(polls->poll == NULL){
printk("need_poll : failed to allocate new pollfds\n");
- next_poll.size = 0;
- next_poll.used = 0;
- return(-1);
+ polls->size = 0;
+ polls->used = 0;
+ return -ENOMEM;
}
- next_poll.size = n;
- next_poll.used = n;
- return(0);
+ polls->size = n;
+ polls->used = n;
+ return 0;
}
/* Must be called with sigio_lock held, because it's needed by the marked
- * critical section. */
+ * critical section.
+ */
static void update_thread(void)
{
unsigned long flags;
@@ -156,34 +150,39 @@ static void update_thread(void)
set_signals(flags);
}
-static int add_sigio_fd(int fd, int read)
+int add_sigio_fd(int fd)
{
- int err = 0, i, n, events;
+ struct pollfd *p;
+ int err = 0, i, n;
sigio_lock();
+ for(i = 0; i < all_sigio_fds.used; i++){
+ if(all_sigio_fds.poll[i].fd == fd)
+ break;
+ }
+ 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)
goto out;
}
n = current_poll.used + 1;
- err = need_poll(n);
+ err = need_poll(&next_poll, n);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++)
next_poll.poll[i] = current_poll.poll[i];
- if(read) events = POLLIN;
- else events = POLLOUT;
-
- next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
+ next_poll.poll[n - 1] = *p;
update_thread();
out:
sigio_unlock();
- return(err);
+ return err;
}
int ignore_sigio_fd(int fd)
@@ -205,18 +204,14 @@ int ignore_sigio_fd(int fd)
if(i == current_poll.used)
goto out;
- err = need_poll(current_poll.used - 1);
+ err = need_poll(&next_poll, current_poll.used - 1);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++){
p = &current_poll.poll[i];
- if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i];
- }
- if(n == i){
- printk("ignore_sigio_fd : fd %d not found\n", fd);
- err = -1;
- goto out;
+ if(p->fd != fd)
+ next_poll.poll[n++] = *p;
}
update_thread();
@@ -234,7 +229,7 @@ static struct pollfd *setup_initial_poll(int fd)
printk("setup_initial_poll : failed to allocate poll\n");
return NULL;
}
- *p = ((struct pollfd) { .fd = fd,
+ *p = ((struct pollfd) { .fd = fd,
.events = POLLIN,
.revents = 0 });
return p;
@@ -323,6 +318,8 @@ out_close1:
void maybe_sigio_broken(int fd, int read)
{
+ int err;
+
if(!isatty(fd))
return;
@@ -330,7 +327,19 @@ void maybe_sigio_broken(int fd, int read)
return;
write_sigio_workaround();
- add_sigio_fd(fd, read);
+
+ sigio_lock();
+ err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
+ if(err){
+ printk("maybe_sigio_broken - failed to add pollfd\n");
+ goto out;
+ }
+ all_sigio_fds.poll[all_sigio_fds.used++] =
+ ((struct pollfd) { .fd = fd,
+ .events = read ? POLLIN : POLLOUT,
+ .revents = 0 });
+out:
+ sigio_unlock();
}
static void sigio_cleanup(void)
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 60e4faedf25..6b81739279d 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,7 +15,6 @@
#include "user.h"
#include "signal_kern.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/signal.h"
#include "sigcontext.h"
#include "mode.h"
#include "os.h"
@@ -38,18 +37,10 @@
static int signals_enabled = 1;
static int pending = 0;
-void sig_handler(ARCH_SIGHDLR_PARAM)
+void sig_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- /* Must be the first thing that this handler does - x86_64 stores
- * the sigcontext in %rdx, and we need to save it before it has a
- * chance to get trashed.
- */
-
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!enabled && (sig == SIGIO)){
pending |= SIGIO_MASK;
@@ -64,15 +55,8 @@ void sig_handler(ARCH_SIGHDLR_PARAM)
set_signals(enabled);
}
-extern int timer_irq_inited;
-
static void real_alarm_handler(int sig, struct sigcontext *sc)
{
- if(!timer_irq_inited){
- signals_enabled = 1;
- return;
- }
-
if(sig == SIGALRM)
switch_timers(0);
@@ -84,13 +68,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc)
}
-void alarm_handler(ARCH_SIGHDLR_PARAM)
+void alarm_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!signals_enabled){
if(sig == SIGVTALRM)
@@ -126,6 +107,10 @@ void remove_sigstack(void)
panic("disabling signal stack failed, errno = %d\n", errno);
}
+void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+
+extern void hard_handler(int sig);
+
void set_handler(int sig, void (*handler)(int), int flags, ...)
{
struct sigaction action;
@@ -133,13 +118,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigset_t sig_mask;
int mask;
- va_start(ap, flags);
- action.sa_handler = handler;
+ handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
+ action.sa_handler = hard_handler;
+
sigemptyset(&action.sa_mask);
- while((mask = va_arg(ap, int)) != -1){
+
+ va_start(ap, flags);
+ while((mask = va_arg(ap, int)) != -1)
sigaddset(&action.sa_mask, mask);
- }
va_end(ap);
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if(sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 7baf90fda58..cb9ab54146c 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <sched.h>
#include "ptrace_user.h"
#include <sys/wait.h>
@@ -156,11 +155,15 @@ extern int __syscall_stub_start;
static int userspace_tramp(void *stack)
{
void *addr;
+ int err;
ptrace(PTRACE_TRACEME, 0, 0, 0);
init_new_thread_signals();
- enable_timer();
+ err = set_interval(1);
+ if(err)
+ panic("userspace_tramp - setting timer failed, errno = %d\n",
+ err);
if(!proc_mm){
/* This has a pte, but it can't be mapped in with the usual
@@ -190,14 +193,25 @@ static int userspace_tramp(void *stack)
}
}
if(!ptrace_faultinfo && (stack != NULL)){
+ struct sigaction sa;
+
unsigned long v = UML_CONFIG_STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
- set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
- SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
- SIGUSR1, -1);
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGIO);
+ sigaddset(&sa.sa_mask, SIGWINCH);
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sigaddset(&sa.sa_mask, SIGVTALRM);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sa.sa_flags = SA_ONSTACK;
+ 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);
}
os_stop_process(os_getpid());
@@ -430,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
}
}
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
- void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
{
- unsigned long flags;
- jmp_buf switch_buf, fork_buf;
-
- *switch_buf_ptr = &switch_buf;
- *fork_buf_ptr = &fork_buf;
-
- /* Somewhat subtle - siglongjmp restores the signal mask before doing
- * the longjmp. This means that when jumping from one stack to another
- * when the target stack has interrupts enabled, an interrupt may occur
- * on the source stack. This is bad when starting up a process because
- * it's not supposed to get timer ticks until it has been scheduled.
- * So, we disable interrupts around the sigsetjmp to ensure that
- * they can't happen until we get back here where they are safe.
- */
- flags = get_signals();
- block_signals();
- if(UML_SETJMP(&fork_buf) == 0)
- new_thread_proc(stack, handler);
-
- remove_sigstack();
-
- set_signals(flags);
+ (*buf)[0].JB_IP = (unsigned long) handler;
+ (*buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
}
#define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
-void thread_wait(void *sw, void *fb)
+void switch_threads(jmp_buf *me, jmp_buf *you)
{
- jmp_buf buf, **switch_buf = sw, *fork_buf;
-
- *switch_buf = &buf;
- fork_buf = fb;
- if(UML_SETJMP(&buf) == 0)
- siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
-
-void switch_threads(void *me, void *next)
-{
- jmp_buf my_buf, **me_ptr = me, *next_buf = next;
-
- *me_ptr = &my_buf;
- if(UML_SETJMP(&my_buf) == 0)
- UML_LONGJMP(next_buf, 1);
+ if(UML_SETJMP(me) == 0)
+ UML_LONGJMP(you, 1);
}
static jmp_buf initial_jmpbuf;
@@ -489,23 +469,21 @@ static void (*cb_proc)(void *arg);
static void *cb_arg;
static jmp_buf *cb_back;
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
{
- jmp_buf **switch_buf = switch_buf_ptr;
int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
SIGVTALRM, -1);
- *fork_buf_ptr = &initial_jmpbuf;
n = UML_SETJMP(&initial_jmpbuf);
switch(n){
case INIT_JMP_NEW_THREAD:
- new_thread_proc((void *) stack, new_thread_handler);
- break;
- case INIT_JMP_REMOVE_SIGSTACK:
- remove_sigstack();
+ (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+ (*switch_buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+ sizeof(void *);
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
@@ -520,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_LONGJMP(*switch_buf, 1);
+ UML_LONGJMP(switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 50314850400..7fe92680c7d 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -14,7 +14,6 @@
#include <sched.h>
#include <fcntl.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/mman.h>
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index b3213613c41..37806621b25 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 516f66dd87e..7cd0369e02b 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,12 +5,12 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "sysdep/ptrace_user.h"
#include "sysdep/ptrace.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -130,11 +130,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]);
- UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]);
+ switch(reg){
+ case EIP: return buf[0]->__eip;
+ case UESP: return buf[0]->__esp;
+ case EBP: return buf[0]->__ebp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
new file mode 100644
index 00000000000..0d3eae51835
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
+
+ (*handlers[sig])(sig, sc);
+}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index 340ef26f594..f67842a7735 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index becd898d939..cb8e8a26328 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -5,11 +5,11 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "ptrace_user.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -78,11 +78,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]);
- UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]);
+ switch(reg){
+ case RIP: return buf[0]->__rip;
+ case RSP: return buf[0]->__rsp;
+ case RBP: return buf[0]->__rbp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
new file mode 100644
index 00000000000..3f369e5f976
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct ucontext *uc;
+ asm("movq %%rdx, %0" : "=r" (uc));
+
+ (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
+}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 4ae73c0e548..38be096e750 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -17,20 +17,25 @@
#include "kern_constants.h"
#include "os.h"
-static void set_interval(int timer_type)
+int set_interval(int is_virtual)
{
int usec = 1000000/hz();
+ int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
struct itimerval interval = ((struct itimerval) { { 0, usec },
{ 0, usec } });
if(setitimer(timer_type, &interval, NULL) == -1)
- panic("setitimer failed - errno = %d\n", errno);
+ return -errno;
+
+ return 0;
}
+#ifdef CONFIG_MODE_TT
void enable_timer(void)
{
- set_interval(ITIMER_VIRTUAL);
+ set_interval(1);
}
+#endif
void disable_timer(void)
{
@@ -40,8 +45,8 @@ void disable_timer(void)
printk("disnable_timer - setitimer failed, errno = %d\n",
errno);
/* If there are signals already queued, after unblocking ignore them */
- set_handler(SIGALRM, SIG_IGN, 0, -1);
- set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGVTALRM, SIG_IGN);
}
void switch_timers(int to_real)
@@ -74,7 +79,7 @@ void uml_idle_timer(void)
set_handler(SIGALRM, (__sighandler_t) alarm_handler,
SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_interval(ITIMER_REAL);
+ set_interval(0);
}
#endif
@@ -94,8 +99,3 @@ void idle_sleep(int secs)
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
}
-
-void user_time_init(void)
-{
- set_interval(ITIMER_VIRTUAL);
-}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 90b29ae9af4..1df231a2624 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <signal.h>
-#include <setjmp.h>
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 865f6a6a259..bbb73a65037 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -4,8 +4,7 @@
* Licensed under the GPL
*/
-#include <setjmp.h>
-#include <string.h>
+#include <stddef.h>
#include "longjmp.h"
unsigned long __do_user_copy(void *to, const void *from, int n,
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c47a2a7ce70..3f5b1514e8a 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
-#include <setjmp.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/utsname.h>
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
jmp_buf buf;
int n;
- n = sigsetjmp(buf, 1);
+ n = UML_SETJMP(&buf);
if(n == 0){
va_start(args, proc);
(*proc)(&buf, &args);
}
va_end(args);
- return(n);
+ return n;
}
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 374d61a1943..0e32adf03be 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,10 +1,10 @@
obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
- ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \
+ ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
sys_call_table.o tls.o
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
-subarch-obj-y = lib/bitops.o kernel/semaphore.o
+subarch-obj-y = lib/bitops.o lib/semaphore.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 41b0ab2fe83..f1bcd399ac9 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -13,6 +13,7 @@
#include "sysdep/ptrace.h"
#include "task.h"
#include "os.h"
+#include "user_util.h"
#define MAXTOKEN 64
@@ -104,17 +105,17 @@ int cpu_feature(char *what, char *buf, int len)
static int check_cpu_flag(char *feature, int *have_it)
{
char buf[MAXTOKEN], c;
- int fd, len = sizeof(buf)/sizeof(buf[0]);
+ int fd, len = ARRAY_SIZE(buf);
printk("Checking for host processor %s support...", feature);
fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
if(fd < 0){
printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
- return(0);
+ return 0;
}
*have_it = 0;
- if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+ if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
goto out;
c = token(fd, buf, len - 1, ' ');
@@ -138,7 +139,7 @@ static int check_cpu_flag(char *feature, int *have_it)
if(*have_it == 0) printk("No\n");
else if(*have_it == 1) printk("Yes\n");
os_close_file(fd);
- return(1);
+ return 1;
}
#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index fe0877b3509..69971b78bea 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -424,9 +424,8 @@ void ldt_get_host_info(void)
size++;
}
- if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) {
+ if(size < ARRAY_SIZE(dummy_list))
host_ldt_entries = dummy_list;
- }
else {
size = (size + 1) * sizeof(dummy_list[0]);
host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 40aa8853144..5f3cc668582 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -15,6 +15,7 @@
#include "user.h"
#include "os.h"
#include "uml-config.h"
+#include "user_util.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
@@ -51,7 +52,7 @@ static void write_debugregs(int pid, unsigned long *regs)
int nregs, i;
dummy = NULL;
- nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
+ nregs = ARRAY_SIZE(dummy->u_debugreg);
for(i = 0; i < nregs; i++){
if((i == 4) || (i == 5)) continue;
if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
@@ -68,7 +69,7 @@ static void read_debugregs(int pid, unsigned long *regs)
int nregs, i;
dummy = NULL;
- nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
+ nregs = ARRAY_SIZE(dummy->u_debugreg);
for(i = 0; i < nregs; i++){
regs[i] = ptrace(PTRACE_PEEKUSR, pid,
&dummy->u_debugreg[i], 0);
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S
new file mode 100644
index 00000000000..b766792c993
--- /dev/null
+++ b/arch/um/sys-i386/setjmp.S
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+# %ebx
+# %esp
+# %ebp
+# %esi
+# %edi
+# <return address>
+#
+
+ .text
+ .align 4
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+ movl %eax,%edx
+#else
+ movl 4(%esp),%edx
+#endif
+ popl %ecx # Return address, and adjust the stack
+ xorl %eax,%eax # Return value
+ movl %ebx,(%edx)
+ movl %esp,4(%edx) # Post-return %esp!
+ pushl %ecx # Make the call/return stack happy
+ movl %ebp,8(%edx)
+ movl %esi,12(%edx)
+ movl %edi,16(%edx)
+ movl %ecx,20(%edx) # Return address
+ ret
+
+ .size setjmp,.-setjmp
+
+ .text
+ .align 4
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+ xchgl %eax,%edx
+#else
+ movl 4(%esp),%edx # jmp_ptr address
+ movl 8(%esp),%eax # Return value
+#endif
+ movl (%edx),%ebx
+ movl 4(%edx),%esp
+ movl 8(%edx),%ebp
+ movl 12(%edx),%esi
+ movl 16(%edx),%edi
+ jmp *20(%edx)
+
+ .size longjmp,.-longjmp
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c19794d435d..f41768b8e25 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,8 +5,8 @@
#
obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
- sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \
- tls.o
+ setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
+ ksyms.o tls.o
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
obj-$(CONFIG_MODULES) += um_module.o
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S
new file mode 100644
index 00000000000..45f547b4043
--- /dev/null
+++ b/arch/um/sys-x86_64/setjmp.S
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+# %rbx
+# %rsp (post-return)
+# %rbp
+# %r12
+# %r13
+# %r14
+# %r15
+# <return address>
+#
+
+ .text
+ .align 4
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
+ pop %rsi # Return address, and adjust the stack
+ xorl %eax,%eax # Return value
+ movq %rbx,(%rdi)
+ movq %rsp,8(%rdi) # Post-return %rsp!
+ push %rsi # Make the call/return stack happy
+ movq %rbp,16(%rdi)
+ movq %r12,24(%rdi)
+ movq %r13,32(%rdi)
+ movq %r14,40(%rdi)
+ movq %r15,48(%rdi)
+ movq %rsi,56(%rdi) # Return address
+ ret
+
+ .size setjmp,.-setjmp
+
+ .text
+ .align 4
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
+ movl %esi,%eax # Return value (int)
+ movq (%rdi),%rbx
+ movq 8(%rdi),%rsp
+ movq 16(%rdi),%rbp
+ movq 24(%rdi),%r12
+ movq 32(%rdi),%r13
+ movq 40(%rdi),%r14
+ movq 48(%rdi),%r15
+ jmp *56(%rdi)
+
+ .size longjmp,.-longjmp
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 6cd4878625f..32ae1378f35 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -24,6 +24,10 @@ config X86
bool
default y
+config ZONE_DMA32
+ bool
+ default y
+
config LOCKDEP_SUPPORT
bool
default y
@@ -81,6 +85,9 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
config DMI
bool
default y
@@ -105,6 +112,7 @@ config X86_PC
config X86_VSMP
bool "Support for ScaleMP vSMP"
+ depends on PCI
help
Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
supposed to run on these EM64T-based machines. Only choose this option
@@ -163,6 +171,7 @@ config X86_GOOD_APIC
config MICROCODE
tristate "/dev/cpu/microcode - Intel CPU microcode support"
+ select FW_LOADER
---help---
If you say Y here the 'File systems' section, you will be
able to update the microcode on Intel processors. You will
@@ -178,6 +187,11 @@ config MICROCODE
If you use modprobe or kmod you may also want to add the line
'alias char-major-10-184 microcode' to your /etc/modules.conf file.
+config MICROCODE_OLD_INTERFACE
+ bool
+ depends on MICROCODE
+ default y
+
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
help
@@ -291,7 +305,7 @@ config NUMA
config K8_NUMA
bool "Old style AMD Opteron NUMA detection"
- depends on NUMA
+ depends on NUMA && PCI
default y
help
Enable K8 NUMA node topology detection. You should say Y here if
@@ -421,7 +435,6 @@ config IOMMU
config CALGARY_IOMMU
bool "IBM Calgary IOMMU support"
- default y
select SWIOTLB
depends on PCI && EXPERIMENTAL
help
@@ -468,8 +481,7 @@ config X86_MCE_AMD
the DRAM Error Threshold.
config KEXEC
- bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "kexec system call"
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -488,7 +500,14 @@ config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
- Generate crash dump after being started by kexec.
+ Generate crash dump after being started by kexec.
+ This should be normally only set in special crash dump kernels
+ which are loaded in the main kernel with kexec-tools into
+ a specially reserved region and then later executed after
+ a crash by kdump/kexec. The crash dump kernel must be compiled
+ to a memory address not used by the main kernel or BIOS using
+ PHYSICAL_START.
+ For more details see Documentation/kdump/kdump.txt
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
@@ -526,6 +545,30 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
+config CC_STACKPROTECTOR
+ bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ This option turns on the -fstack-protector GCC feature. This
+ feature puts, at the beginning of critical functions, a canary
+ value on the stack just before the return address, and validates
+ the value just before actually returning. Stack based buffer
+ overflows (that need to overwrite this return address) now also
+ overwrite the canary, which gets detected and the attack is then
+ neutralized via a kernel panic.
+
+ This feature requires gcc version 4.2 or above, or a distribution
+ gcc with the feature backported. Older versions are automatically
+ detected and for those versions, this configuration option is ignored.
+
+config CC_STACKPROTECTOR_ALL
+ bool "Use stack-protector for all functions"
+ depends on CC_STACKPROTECTOR
+ help
+ Normally, GCC only inserts the canary value protection for
+ functions that use large-ish on-stack buffers. By enabling
+ this option, GCC will be asked to do this for ALL functions.
+
source kernel/Kconfig.hz
config REORDER
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 431bb4bc36c..1c0f18d4f88 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -54,6 +54,16 @@ endif
cflags-y += $(call cc-option,-funit-at-a-time)
# prevent gcc from generating any FP code by mistake
cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+# do binutils support CFI?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
+# is .cfi_signal_frame supported too?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+
+cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector )
+cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector-all )
CFLAGS += $(cflags-y)
CFLAGS_KERNEL += $(cflags-kernel-y)
diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile
index f89d96f11a9..e70fa6e1da0 100644
--- a/arch/x86_64/boot/compressed/Makefile
+++ b/arch/x86_64/boot/compressed/Makefile
@@ -7,7 +7,8 @@
#
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS := -traditional -m32
+EXTRA_AFLAGS := -traditional
+AFLAGS := $(subst -m64,-m32,$(AFLAGS))
# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
# -m32
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
index a50b631f4d2..c3bfd223ab4 100644
--- a/arch/x86_64/boot/setup.S
+++ b/arch/x86_64/boot/setup.S
@@ -526,12 +526,12 @@ is_disk1:
movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG
movw %ax, %ds
- movw $0, (0x1ff) # default is no pointing device
+ movb $0, (0x1ff) # default is no pointing device
int $0x11 # int 0x11: equipment list
testb $0x04, %al # check if mouse installed
jz no_psmouse
- movw $0xAA, (0x1ff) # device present
+ movb $0xAA, (0x1ff) # device present
no_psmouse:
#include "../../i386/boot/edd.S"
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 5fb97071594..647610ecb58 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc4
-# Thu Aug 24 21:05:55 2006
+# Linux kernel version: 2.6.18-git5
+# Tue Sep 26 09:30:47 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -19,6 +19,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -38,16 +39,16 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -56,12 +57,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -160,6 +161,7 @@ CONFIG_X86_MCE_AMD=y
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x200000
CONFIG_SECCOMP=y
+# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
@@ -307,18 +309,23 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -345,7 +352,6 @@ CONFIG_IPV6=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -487,6 +493,7 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
#
@@ -508,12 +515,13 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
CONFIG_SCSI_SAS_ATTRS=y
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -532,29 +540,14 @@ CONFIG_AIC79XX_RESET_DELAY_MS=4000
# CONFIG_AIC79XX_DEBUG_ENABLE is not set
CONFIG_AIC79XX_DEBUG_MASK=0
# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
CONFIG_MEGARAID_NEWGEN=y
CONFIG_MEGARAID_MM=y
CONFIG_MEGARAID_MAILBOX=y
# CONFIG_MEGARAID_LEGACY is not set
CONFIG_MEGARAID_SAS=y
-CONFIG_SCSI_SATA=y
-CONFIG_SCSI_SATA_AHCI=y
-CONFIG_SCSI_SATA_SVW=y
-CONFIG_SCSI_ATA_PIIX=y
-# CONFIG_SCSI_SATA_MV is not set
-CONFIG_SCSI_SATA_NV=y
-# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_SATA_QSTOR is not set
-# CONFIG_SCSI_SATA_PROMISE is not set
-# CONFIG_SCSI_SATA_SX4 is not set
-CONFIG_SCSI_SATA_SIL=y
-# CONFIG_SCSI_SATA_SIL24 is not set
-# CONFIG_SCSI_SATA_SIS is not set
-# CONFIG_SCSI_SATA_ULI is not set
-CONFIG_SCSI_SATA_VIA=y
-# CONFIG_SCSI_SATA_VITESSE is not set
-CONFIG_SCSI_SATA_INTEL_COMBINED=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -563,6 +556,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -573,6 +567,62 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
# CONFIG_SCSI_DEBUG is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_SVW=y
+CONFIG_ATA_PIIX=y
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=y
+# 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=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+CONFIG_SATA_VIA=y
+# CONFIG_SATA_VITESSE is not set
+CONFIG_SATA_INTEL_COMBINED=y
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP 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_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX 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_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_QDI 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
+
+#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
@@ -678,6 +728,7 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
CONFIG_B44=y
CONFIG_FORCEDETH=y
+# CONFIG_FORCEDETH_NAPI is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
@@ -714,6 +765,7 @@ CONFIG_E1000=y
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
CONFIG_BNX2=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -1036,6 +1088,7 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
+CONFIG_OSS_OBSOLETE_DRIVER=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
@@ -1046,7 +1099,6 @@ CONFIG_SOUND_ICH=y
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_VIA82CXXX is not set
# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
#
# USB support
@@ -1203,7 +1255,6 @@ CONFIG_USB_MON=y
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
-# CONFIG_IPATH_CORE is not set
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1449,10 +1500,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 3bf58af9893..396d3c10001 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -333,7 +333,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return error;
}
- error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
+ error = bprm->file->f_op->read(bprm->file,
+ (char __user *)text_addr,
ex.a_text+ex.a_data, &pos);
if ((signed long)error < 0) {
send_sig(SIGKILL, current, 0);
@@ -366,7 +367,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
up_write(&current->mm->mmap_sem);
- bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
flush_icache_range((unsigned long) N_TXTADDR(ex),
(unsigned long) N_TXTADDR(ex) +
@@ -477,7 +479,7 @@ static int load_aout_library(struct file *file)
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
up_write(&current->mm->mmap_sem);
- file->f_op->read(file, (char *)start_addr,
+ file->f_op->read(file, (char __user *)start_addr,
ex.a_text + ex.a_data, &pos);
flush_icache_range((unsigned long) start_addr,
(unsigned long) start_addr + ex.a_text + ex.a_data);
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index 25e5ca22204..a6ba9951e86 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -113,25 +113,19 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
}
asmlinkage long
-sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
- struct pt_regs *regs)
+sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs->rax = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage long
@@ -437,15 +431,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
- {
- struct exec_domain *ed = current_thread_info()->exec_domain;
- err |= __put_user((ed
- && ed->signal_invmap
- && sig < 32
- ? ed->signal_invmap[sig]
- : sig),
- &frame->sig);
- }
+ err |= __put_user(sig, &frame->sig);
if (err)
goto give_sigsegv;
@@ -492,6 +478,11 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
+ /* Make -mregparm=3 work */
+ regs->rax = sig;
+ regs->rdx = 0;
+ regs->rcx = 0;
+
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
@@ -499,20 +490,20 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
regs->ss = __USER32_DS;
set_fs(USER_DS);
- regs->eflags &= ~TF_MASK;
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return 1;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
- return 0;
+ return -EFAULT;
}
int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -595,18 +586,18 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->ss = __USER32_DS;
set_fs(USER_DS);
- regs->eflags &= ~TF_MASK;
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return 1;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
- return 0;
+ return -EFAULT;
}
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5d4a7d125ed..b4aa875e175 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -71,6 +71,7 @@
*/
ENTRY(ia32_sysenter_target)
CFI_STARTPROC32 simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,0
CFI_REGISTER rsp,rbp
swapgs
@@ -186,6 +187,7 @@ ENDPROC(ia32_sysenter_target)
*/
ENTRY(ia32_cstar_target)
CFI_STARTPROC32 simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,PDA_STACKOFFSET
CFI_REGISTER rip,rcx
/*CFI_REGISTER rflags,r11*/
@@ -293,6 +295,7 @@ ia32_badarg:
ENTRY(ia32_syscall)
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,SS+8-RIP
/*CFI_REL_OFFSET ss,SS-RIP*/
CFI_REL_OFFSET rsp,RSP-RIP
@@ -370,6 +373,7 @@ ENTRY(ia32_ptregs_common)
popq %r11
CFI_ENDPROC
CFI_STARTPROC32 simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,SS+8-ARGOFFSET
CFI_REL_OFFSET rax,RAX-ARGOFFSET
CFI_REL_OFFSET rcx,RCX-ARGOFFSET
@@ -703,8 +707,8 @@ ia32_sys_call_table:
.quad sys_readlinkat /* 305 */
.quad sys_fchmodat
.quad sys_faccessat
- .quad quiet_ni_syscall /* pselect6 for now */
- .quad quiet_ni_syscall /* ppoll for now */
+ .quad compat_sys_pselect6
+ .quad compat_sys_ppoll
.quad sys_unshare /* 310 */
.quad compat_sys_set_robust_list
.quad compat_sys_get_robust_list
@@ -713,4 +717,5 @@ ia32_sys_call_table:
.quad sys_tee
.quad compat_sys_vmsplice
.quad compat_sys_move_pages
+ .quad sys_getcpu
ia32_syscall_end:
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
index 659c0722f6b..d18198ed636 100644
--- a/arch/x86_64/ia32/ptrace32.c
+++ b/arch/x86_64/ia32/ptrace32.c
@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
return -EIO;
child->thread.debugreg7 = val;
+ if (val)
+ set_tsk_thread_flag(child, TIF_DEBUG);
+ else
+ clear_tsk_thread_flag(child, TIF_DEBUG);
break;
default:
@@ -371,8 +375,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
ret = -EIO;
if (!access_ok(VERIFY_READ, u, sizeof(*u)))
break;
- /* no checking to be bug-to-bug compatible with i386 */
- __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
+ /* no checking to be bug-to-bug compatible with i386. */
+ /* but silence warning */
+ if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)))
+ ;
set_stopped_child_used_math(child);
child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
ret = 0;
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 9c130993380..f280d3665f4 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -60,6 +60,7 @@
#include <linux/highuid.h>
#include <linux/vmalloc.h>
#include <linux/fsnotify.h>
+#include <linux/sysctl.h>
#include <asm/mman.h>
#include <asm/types.h>
#include <asm/uaccess.h>
@@ -389,7 +390,9 @@ sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
}
}
set_fs (KERNEL_DS);
- ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
+ ret = sys_rt_sigprocmask(how,
+ set ? (sigset_t __user *)&s : NULL,
+ oset ? (sigset_t __user *)&s : NULL,
sigsetsize);
set_fs (old_fs);
if (ret) return ret;
@@ -541,7 +544,7 @@ sys32_sysinfo(struct sysinfo32 __user *info)
int bitcount = 0;
set_fs (KERNEL_DS);
- ret = sys_sysinfo(&s);
+ ret = sys_sysinfo((struct sysinfo __user *)&s);
set_fs (old_fs);
/* Check to see if any memory value is too large for 32-bit and scale
@@ -589,7 +592,7 @@ sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *int
mm_segment_t old_fs = get_fs ();
set_fs (KERNEL_DS);
- ret = sys_sched_rr_get_interval(pid, &t);
+ ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
set_fs (old_fs);
if (put_compat_timespec(&t, interval))
return -EFAULT;
@@ -605,7 +608,7 @@ sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
- ret = sys_rt_sigpending(&s, sigsetsize);
+ ret = sys_rt_sigpending((sigset_t __user *)&s, sigsetsize);
set_fs (old_fs);
if (!ret) {
switch (_NSIG_WORDS) {
@@ -630,7 +633,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT;
set_fs (KERNEL_DS);
- ret = sys_rt_sigqueueinfo(pid, sig, &info);
+ ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
set_fs (old_fs);
return ret;
}
@@ -645,7 +648,7 @@ sys32_pause(void)
}
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
struct sysctl_ia32 {
unsigned int name;
int nlen;
@@ -666,9 +669,6 @@ sys32_sysctl(struct sysctl_ia32 __user *args32)
size_t oldlen;
int __user *namep;
long ret;
- extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
- void *newval, size_t newlen);
-
if (copy_from_user(&a32, args32, sizeof (a32)))
return -EFAULT;
@@ -692,7 +692,8 @@ sys32_sysctl(struct sysctl_ia32 __user *args32)
set_fs(KERNEL_DS);
lock_kernel();
- ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
+ ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *)&oldlen,
+ newvalp, (size_t) a32.newlen);
unlock_kernel();
set_fs(old_fs);
@@ -743,7 +744,8 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
return -EFAULT;
set_fs(KERNEL_DS);
- ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
+ count);
set_fs(old_fs);
if (offset && put_user(of, offset))
@@ -778,7 +780,7 @@ asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
asmlinkage long sys32_olduname(struct oldold_utsname __user * name)
{
- int error;
+ int err;
if (!name)
return -EFAULT;
@@ -787,27 +789,31 @@ asmlinkage long sys32_olduname(struct oldold_utsname __user * name)
down_read(&uts_sem);
- error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
- __put_user(0,name->sysname+__OLD_UTS_LEN);
- __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
- __put_user(0,name->nodename+__OLD_UTS_LEN);
- __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
- __put_user(0,name->release+__OLD_UTS_LEN);
- __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
- __put_user(0,name->version+__OLD_UTS_LEN);
+ err = __copy_to_user(&name->sysname,&system_utsname.sysname,
+ __OLD_UTS_LEN);
+ err |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ err |= __copy_to_user(&name->nodename,&system_utsname.nodename,
+ __OLD_UTS_LEN);
+ err |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ err |= __copy_to_user(&name->release,&system_utsname.release,
+ __OLD_UTS_LEN);
+ err |= __put_user(0,name->release+__OLD_UTS_LEN);
+ err |= __copy_to_user(&name->version,&system_utsname.version,
+ __OLD_UTS_LEN);
+ err |= __put_user(0,name->version+__OLD_UTS_LEN);
{
char *arch = "x86_64";
if (personality(current->personality) == PER_LINUX32)
arch = "i686";
- __copy_to_user(&name->machine,arch,strlen(arch)+1);
+ err |= __copy_to_user(&name->machine,arch,strlen(arch)+1);
}
up_read(&uts_sem);
- error = error ? -EFAULT : 0;
+ err = err ? -EFAULT : 0;
- return error;
+ return err;
}
long sys32_uname(struct old_utsname __user * name)
@@ -831,7 +837,7 @@ long sys32_ustat(unsigned dev, struct ustat32 __user *u32p)
seg = get_fs();
set_fs(KERNEL_DS);
- ret = sys_ustat(dev,&u);
+ ret = sys_ustat(dev, (struct ustat __user *)&u);
set_fs(seg);
if (ret >= 0) {
if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) ||
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index b5aaeafc1cd..3c7cbff04d3 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
pci-dma.o pci-nommu.o alternative.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
-obj-$(CONFIG_X86_MCE) += mce.o
+obj-$(CONFIG_X86_MCE) += mce.o therm_throt.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o
obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/
@@ -20,8 +20,8 @@ obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
-obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
-obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
+obj-y += apic.o nmi.o
+obj-y += io_apic.o mpparse.o \
genapic.o genapic_cluster.o genapic_flat.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
@@ -39,12 +39,14 @@ obj-$(CONFIG_K8_NB) += k8.o
obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_PCI) += early-quirks.o
obj-y += topology.o
obj-y += intel_cacheinfo.o
CFLAGS_vsyscall.o := $(PROFILING) -g0
+therm_throt-y += ../../i386/kernel/cpu/mcheck/therm_throt.o
bootflag-y += ../../i386/kernel/bootflag.o
cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o
topology-y += ../../i386/kernel/topology.o
@@ -54,4 +56,3 @@ quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
alternative-y += ../../i386/kernel/alternative.o
-
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index 58af8e73738..b487396c4c5 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -17,6 +17,7 @@
#include <linux/pci_ids.h>
#include <linux/pci.h>
#include <linux/bitops.h>
+#include <linux/ioport.h>
#include <asm/e820.h>
#include <asm/io.h>
#include <asm/proto.h>
@@ -33,6 +34,18 @@ int fallback_aper_force __initdata = 0;
int fix_aperture __initdata = 1;
+static struct resource gart_resource = {
+ .name = "GART",
+ .flags = IORESOURCE_MEM,
+};
+
+static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
+{
+ gart_resource.start = aper_base;
+ gart_resource.end = aper_base + aper_size - 1;
+ insert_resource(&iomem_resource, &gart_resource);
+}
+
/* This code runs before the PCI subsystem is initialized, so just
access the northbridge directly. */
@@ -48,7 +61,7 @@ static u32 __init allocate_aperture(void)
/*
* Aperture has to be naturally aligned. This means an 2GB aperture won't
- * have much chances to find a place in the lower 4GB of memory.
+ * have much chance of finding a place in the lower 4GB of memory.
* Unfortunately we cannot move it up because that would make the
* IOMMU useless.
*/
@@ -62,6 +75,7 @@ static u32 __init allocate_aperture(void)
}
printk("Mapping aperture over %d KB of RAM @ %lx\n",
aper_size >> 10, __pa(p));
+ insert_aperture_resource((u32)__pa(p), aper_size);
return (u32)__pa(p);
}
@@ -198,7 +212,7 @@ void __init iommu_hole_init(void)
u64 aper_base, last_aper_base = 0;
int valid_agp = 0;
- if (iommu_aperture_disabled || !fix_aperture)
+ if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed())
return;
printk("Checking aperture...\n");
@@ -233,8 +247,13 @@ void __init iommu_hole_init(void)
last_aper_base = aper_base;
}
- if (!fix && !fallback_aper_force)
+ if (!fix && !fallback_aper_force) {
+ if (last_aper_base) {
+ unsigned long n = (32 * 1024 * 1024) << last_aper_order;
+ insert_aperture_resource((u32)last_aper_base, n);
+ }
return;
+ }
if (!fallback_aper_force)
aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 2b8cef037a6..135ff25e6b4 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -25,6 +25,7 @@
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/module.h>
+#include <linux/ioport.h>
#include <asm/atomic.h>
#include <asm/smp.h>
@@ -36,13 +37,20 @@
#include <asm/idle.h>
#include <asm/proto.h>
#include <asm/timex.h>
+#include <asm/apic.h>
+int apic_mapped;
int apic_verbosity;
int apic_runs_main_timer;
int apic_calibrate_pmtmr __initdata;
int disable_apic_timer __initdata;
+static struct resource lapic_resource = {
+ .name = "Local APIC",
+ .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
+};
+
/*
* cpu_mask that denotes the CPUs that needs timer interrupt coming in as
* IPIs in place of local APIC timers
@@ -136,72 +144,40 @@ void clear_local_APIC(void)
apic_read(APIC_ESR);
}
-void __init connect_bsp_APIC(void)
-{
- if (pic_mode) {
- /*
- * Do not trust the local APIC being empty at bootup.
- */
- clear_local_APIC();
- /*
- * PIC mode, enable APIC mode in the IMCR, i.e.
- * connect BSP's local APIC to INT and NMI lines.
- */
- apic_printk(APIC_VERBOSE, "leaving PIC mode, enabling APIC mode.\n");
- outb(0x70, 0x22);
- outb(0x01, 0x23);
- }
-}
-
void disconnect_bsp_APIC(int virt_wire_setup)
{
- if (pic_mode) {
- /*
- * Put the board back into PIC mode (has an effect
- * only on certain older boards). Note that APIC
- * interrupts, including IPIs, won't work beyond
- * this point! The only exception are INIT IPIs.
- */
- apic_printk(APIC_QUIET, "disabling APIC mode, entering PIC mode.\n");
- outb(0x70, 0x22);
- outb(0x00, 0x23);
- }
- else {
- /* Go back to Virtual Wire compatibility mode */
- unsigned long value;
-
- /* For the spurious interrupt use vector F, and enable it */
- value = apic_read(APIC_SPIV);
- value &= ~APIC_VECTOR_MASK;
- value |= APIC_SPIV_APIC_ENABLED;
- value |= 0xf;
- apic_write(APIC_SPIV, value);
-
- if (!virt_wire_setup) {
- /* For LVT0 make it edge triggered, active high, external and enabled */
- value = apic_read(APIC_LVT0);
- value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
- APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
- APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
- value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
- value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
- apic_write(APIC_LVT0, value);
- }
- else {
- /* Disable LVT0 */
- apic_write(APIC_LVT0, APIC_LVT_MASKED);
- }
+ /* Go back to Virtual Wire compatibility mode */
+ unsigned long value;
+
+ /* For the spurious interrupt use vector F, and enable it */
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_VECTOR_MASK;
+ value |= APIC_SPIV_APIC_ENABLED;
+ value |= 0xf;
+ apic_write(APIC_SPIV, value);
- /* For LVT1 make it edge triggered, active high, nmi and enabled */
- value = apic_read(APIC_LVT1);
- value &= ~(
- APIC_MODE_MASK | APIC_SEND_PENDING |
+ if (!virt_wire_setup) {
+ /* For LVT0 make it edge triggered, active high, external and enabled */
+ value = apic_read(APIC_LVT0);
+ value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
- APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
- value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
- apic_write(APIC_LVT1, value);
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+ apic_write(APIC_LVT0, value);
+ } else {
+ /* Disable LVT0 */
+ apic_write(APIC_LVT0, APIC_LVT_MASKED);
}
+
+ /* For LVT1 make it edge triggered, active high, nmi and enabled */
+ value = apic_read(APIC_LVT1);
+ value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+ apic_write(APIC_LVT1, value);
}
void disable_local_APIC(void)
@@ -297,8 +273,6 @@ void __init sync_Arb_IDs(void)
| APIC_DM_INIT);
}
-extern void __error_in_apic_c (void);
-
/*
* An initial setup of the virtual wire mode.
*/
@@ -345,8 +319,7 @@ void __cpuinit setup_local_APIC (void)
value = apic_read(APIC_LVR);
- if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
- __error_in_apic_c();
+ BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);
/*
* Double-check whether this APIC is really registered.
@@ -399,32 +372,8 @@ void __cpuinit setup_local_APIC (void)
*/
value |= APIC_SPIV_APIC_ENABLED;
- /*
- * Some unknown Intel IO/APIC (or APIC) errata is biting us with
- * certain networking cards. If high frequency interrupts are
- * happening on a particular IOAPIC pin, plus the IOAPIC routing
- * entry is masked/unmasked at a high rate as well then sooner or
- * later IOAPIC line gets 'stuck', no more interrupts are received
- * from the device. If focus CPU is disabled then the hang goes
- * away, oh well :-(
- *
- * [ This bug can be reproduced easily with a level-triggered
- * PCI Ne2000 networking cards and PII/PIII processors, dual
- * BX chipset. ]
- */
- /*
- * Actually disabling the focus CPU check just makes the hang less
- * frequent as it makes the interrupt distributon model be more
- * like LRU than MRU (the short-term load is more even across CPUs).
- * See also the comment in end_level_ioapic_irq(). --macro
- */
-#if 1
- /* Enable focus processor (bit==0) */
- value &= ~APIC_SPIV_FOCUS_DISABLED;
-#else
- /* Disable focus processor (bit==1) */
- value |= APIC_SPIV_FOCUS_DISABLED;
-#endif
+ /* We always use processor focus */
+
/*
* Set spurious IRQ vector
*/
@@ -442,7 +391,7 @@ void __cpuinit setup_local_APIC (void)
* TODO: set up through-local-APIC from through-I/O-APIC? --macro
*/
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
- if (!smp_processor_id() && (pic_mode || !value)) {
+ if (!smp_processor_id() && !value) {
value = APIC_DM_EXTINT;
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id());
} else {
@@ -479,8 +428,7 @@ void __cpuinit setup_local_APIC (void)
}
nmi_watchdog_default();
- if (nmi_watchdog == NMI_LOCAL_APIC)
- setup_apic_nmi_watchdog();
+ setup_apic_nmi_watchdog(NULL);
apic_pm_activate();
}
@@ -527,8 +475,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
- local_save_flags(flags);
- local_irq_disable();
+ local_irq_save(flags);
disable_local_APIC();
local_irq_restore(flags);
return 0;
@@ -606,18 +553,24 @@ static void apic_pm_activate(void) { }
static int __init apic_set_verbosity(char *str)
{
+ if (str == NULL) {
+ skip_ioapic_setup = 0;
+ ioapic_force = 1;
+ return 0;
+ }
if (strcmp("debug", str) == 0)
apic_verbosity = APIC_DEBUG;
else if (strcmp("verbose", str) == 0)
apic_verbosity = APIC_VERBOSE;
- else
+ else {
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
- " use apic=verbose or apic=debug", str);
+ " use apic=verbose or apic=debug\n", str);
+ return -EINVAL;
+ }
- return 1;
+ return 0;
}
-
-__setup("apic=", apic_set_verbosity);
+early_param("apic", apic_set_verbosity);
/*
* Detect and enable local APICs on non-SMP boards.
@@ -638,6 +591,40 @@ static int __init detect_init_APIC (void)
return 0;
}
+#ifdef CONFIG_X86_IO_APIC
+static struct resource * __init ioapic_setup_resources(void)
+{
+#define IOAPIC_RESOURCE_NAME_SIZE 11
+ unsigned long n;
+ struct resource *res;
+ char *mem;
+ int i;
+
+ if (nr_ioapics <= 0)
+ return NULL;
+
+ n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+ n *= nr_ioapics;
+
+ res = alloc_bootmem(n);
+
+ if (!res)
+ return NULL;
+
+ memset(res, 0, n);
+ mem = (void *)&res[nr_ioapics];
+
+ for (i = 0; i < nr_ioapics; i++) {
+ res[i].name = mem;
+ res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
+ mem += IOAPIC_RESOURCE_NAME_SIZE;
+ }
+
+ return res;
+}
+#endif
+
void __init init_apic_mappings(void)
{
unsigned long apic_phys;
@@ -654,19 +641,26 @@ void __init init_apic_mappings(void)
apic_phys = mp_lapic_addr;
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+ apic_mapped = 1;
apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
+ /* Put local APIC into the resource map. */
+ lapic_resource.start = apic_phys;
+ lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
+ insert_resource(&iomem_resource, &lapic_resource);
+
/*
* Fetch the APIC ID of the BSP in case we have a
* default configuration (or the MP table is broken).
*/
boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
-#ifdef CONFIG_X86_IO_APIC
{
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
int i;
+ struct resource *ioapic_res;
+ ioapic_res = ioapic_setup_resources();
for (i = 0; i < nr_ioapics; i++) {
if (smp_found_config) {
ioapic_phys = mp_ioapics[i].mpc_apicaddr;
@@ -678,9 +672,15 @@ void __init init_apic_mappings(void)
apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
__fix_to_virt(idx), ioapic_phys);
idx++;
+
+ if (ioapic_res) {
+ ioapic_res->start = ioapic_phys;
+ ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+ insert_resource(&iomem_resource, ioapic_res);
+ ioapic_res++;
+ }
}
}
-#endif
}
/*
@@ -951,7 +951,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
* We take the 'long' return path, and there every subsystem
* grabs the appropriate locks (kernel lock/ irq lock).
*
- * we might want to decouple profiling from the 'long path',
+ * We might want to decouple profiling from the 'long path',
* and do the profiling totally in assembly.
*
* Currently this isn't too much of an issue (performance wise),
@@ -1123,19 +1123,15 @@ int __init APIC_init_uniprocessor (void)
verify_local_APIC();
- connect_bsp_APIC();
-
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id));
setup_local_APIC();
-#ifdef CONFIG_X86_IO_APIC
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
- setup_IO_APIC();
+ setup_IO_APIC();
else
nr_ioapics = 0;
-#endif
setup_boot_APIC_clock();
check_nmi_watchdog();
return 0;
@@ -1144,14 +1140,17 @@ int __init APIC_init_uniprocessor (void)
static __init int setup_disableapic(char *str)
{
disable_apic = 1;
- return 1;
-}
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+ return 0;
+}
+early_param("disableapic", setup_disableapic);
+/* same as disableapic, for compatibility */
static __init int setup_nolapic(char *str)
{
- disable_apic = 1;
- return 1;
+ return setup_disableapic(str);
}
+early_param("nolapic", setup_nolapic);
static __init int setup_noapictimer(char *str)
{
@@ -1184,11 +1183,5 @@ static __init int setup_apicpmtimer(char *s)
}
__setup("apicpmtimer", setup_apicpmtimer);
-/* dummy parsing: see setup.c */
-
-__setup("disableapic", setup_disableapic);
-__setup("nolapic", setup_nolapic); /* same as disableapic, for compatibility */
-
__setup("noapictimer", setup_noapictimer);
-/* no "lapic" flag - we only use the lapic when the BIOS tells us so. */
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index d8d5750d610..3525f884af8 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -23,6 +23,7 @@
#include <asm/nmi.h>
#include <asm/hw_irq.h>
#include <asm/mach_apic.h>
+#include <asm/kdebug.h>
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
@@ -68,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
* for the data I pass, and I need tags
* on the data to indicate what information I have
* squirrelled away. ELF notes happen to provide
- * all of that that no need to invent something new.
+ * all of that, no need to invent something new.
*/
buf = (u32*)per_cpu_ptr(crash_notes, cpu);
@@ -95,15 +96,25 @@ static void crash_save_self(struct pt_regs *regs)
#ifdef CONFIG_SMP
static atomic_t waiting_for_crash_ipi;
-static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+static int crash_nmi_callback(struct notifier_block *self,
+ unsigned long val, void *data)
{
+ struct pt_regs *regs;
+ int cpu;
+
+ if (val != DIE_NMI_IPI)
+ return NOTIFY_OK;
+
+ regs = ((struct die_args *)data)->regs;
+ cpu = raw_smp_processor_id();
+
/*
* Don't do anything if this handler is invoked on crashing cpu.
* Otherwise, system will completely hang. Crashing cpu can get
* an NMI if system was initially booted with nmi_watchdog parameter.
*/
if (cpu == crashing_cpu)
- return 1;
+ return NOTIFY_STOP;
local_irq_disable();
crash_save_this_cpu(regs, cpu);
@@ -127,12 +138,17 @@ static void smp_send_nmi_allbutself(void)
* cpu hotplug shouldn't matter.
*/
+static struct notifier_block crash_nmi_nb = {
+ .notifier_call = crash_nmi_callback,
+};
+
static void nmi_shootdown_cpus(void)
{
unsigned long msecs;
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
- set_nmi_callback(crash_nmi_callback);
+ if (register_die_notifier(&crash_nmi_nb))
+ return; /* return what? */
/*
* Ensure the new callback function is set before sending
@@ -178,9 +194,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
if(cpu_has_apic)
disable_local_APIC();
-#if defined(CONFIG_X86_IO_APIC)
disable_IO_APIC();
-#endif
crash_save_self(regs);
}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index d6d7f731f6f..b3f0908668e 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/kexec.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -24,6 +25,8 @@
#include <asm/bootsetup.h>
#include <asm/sections.h>
+struct e820map e820 __initdata;
+
/*
* PFN of last memory page.
*/
@@ -40,7 +43,7 @@ unsigned long end_pfn_map;
/*
* Last pfn which the user wants to use.
*/
-unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;
+static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
extern struct resource code_resource, data_resource;
@@ -69,12 +72,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
return 1;
}
#endif
- /* kernel code + 640k memory hole (later should not be needed, but
- be paranoid for now) */
- if (last >= 640*1024 && addr < 1024*1024) {
- *addrp = 1024*1024;
- return 1;
- }
+ /* kernel code */
if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
*addrp = __pa_symbol(&_end);
return 1;
@@ -164,59 +162,14 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
return -1UL;
}
-/*
- * Free bootmem based on the e820 table for a node.
- */
-void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
-{
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- unsigned long last, addr;
-
- if (ei->type != E820_RAM ||
- ei->addr+ei->size <= start ||
- ei->addr >= end)
- continue;
-
- addr = round_up(ei->addr, PAGE_SIZE);
- if (addr < start)
- addr = start;
-
- last = round_down(ei->addr + ei->size, PAGE_SIZE);
- if (last >= end)
- last = end;
-
- if (last > addr && last-addr >= PAGE_SIZE)
- free_bootmem_node(pgdat, addr, last-addr);
- }
-}
-
/*
* Find the highest page frame number we have available
*/
unsigned long __init e820_end_of_ram(void)
{
- int i;
unsigned long end_pfn = 0;
+ end_pfn = find_max_pfn_with_active_regions();
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- unsigned long start, end;
-
- start = round_up(ei->addr, PAGE_SIZE);
- end = round_down(ei->addr + ei->size, PAGE_SIZE);
- if (start >= end)
- continue;
- if (ei->type == E820_RAM) {
- if (end > end_pfn<<PAGE_SHIFT)
- end_pfn = end>>PAGE_SHIFT;
- } else {
- if (end > end_pfn_map<<PAGE_SHIFT)
- end_pfn_map = end>>PAGE_SHIFT;
- }
- }
-
if (end_pfn > end_pfn_map)
end_pfn_map = end_pfn;
if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
@@ -226,43 +179,10 @@ unsigned long __init e820_end_of_ram(void)
if (end_pfn > end_pfn_map)
end_pfn = end_pfn_map;
+ printk("end_pfn_map = %lu\n", end_pfn_map);
return end_pfn;
}
-/*
- * Compute how much memory is missing in a range.
- * Unlike the other functions in this file the arguments are in page numbers.
- */
-unsigned long __init
-e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
-{
- unsigned long ram = 0;
- unsigned long start = start_pfn << PAGE_SHIFT;
- unsigned long end = end_pfn << PAGE_SHIFT;
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- unsigned long last, addr;
-
- if (ei->type != E820_RAM ||
- ei->addr+ei->size <= start ||
- ei->addr >= end)
- continue;
-
- addr = round_up(ei->addr, PAGE_SIZE);
- if (addr < start)
- addr = start;
-
- last = round_down(ei->addr + ei->size, PAGE_SIZE);
- if (last >= end)
- last = end;
-
- if (last > addr)
- ram += last - addr;
- }
- return ((end - start) - ram) >> PAGE_SHIFT;
-}
-
/*
* Mark e820 reserved areas as busy for the resource manager.
*/
@@ -297,6 +217,96 @@ void __init e820_reserve_resources(void)
}
}
+/* Mark pages corresponding to given address range as nosave */
+static void __init
+e820_mark_nosave_range(unsigned long start, unsigned long end)
+{
+ unsigned long pfn, max_pfn;
+
+ if (start >= end)
+ return;
+
+ printk("Nosave address range: %016lx - %016lx\n", start, end);
+ max_pfn = end >> PAGE_SHIFT;
+ for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
+ if (pfn_valid(pfn))
+ SetPageNosave(pfn_to_page(pfn));
+}
+
+/*
+ * Find the ranges of physical addresses that do not correspond to
+ * e820 RAM areas and mark the corresponding pages as nosave for software
+ * suspend and suspend to RAM.
+ *
+ * This function requires the e820 map to be sorted and without any
+ * overlapping entries and assumes the first e820 area to be RAM.
+ */
+void __init e820_mark_nosave_regions(void)
+{
+ int i;
+ unsigned long paddr;
+
+ paddr = round_down(e820.map[0].addr + e820.map[0].size, PAGE_SIZE);
+ for (i = 1; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+
+ if (paddr < ei->addr)
+ e820_mark_nosave_range(paddr,
+ round_up(ei->addr, PAGE_SIZE));
+
+ paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
+ if (ei->type != E820_RAM)
+ e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE),
+ paddr);
+
+ if (paddr >= (end_pfn << PAGE_SHIFT))
+ break;
+ }
+}
+
+/* Walk the e820 map and register active regions within a node */
+void __init
+e820_register_active_regions(int nid, unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ int i;
+ unsigned long ei_startpfn, ei_endpfn;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
+ ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
+ >> PAGE_SHIFT;
+
+ /* Skip map entries smaller than a page */
+ if (ei_startpfn > ei_endpfn)
+ continue;
+
+ /* Check if end_pfn_map should be updated */
+ if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
+ end_pfn_map = ei_endpfn;
+
+ /* Skip if map is outside the node */
+ if (ei->type != E820_RAM ||
+ ei_endpfn <= start_pfn ||
+ ei_startpfn >= end_pfn)
+ continue;
+
+ /* Check for overlaps */
+ if (ei_startpfn < start_pfn)
+ ei_startpfn = start_pfn;
+ if (ei_endpfn > end_pfn)
+ ei_endpfn = end_pfn;
+
+ /* Obey end_user_pfn to save on memmap */
+ if (ei_startpfn >= end_user_pfn)
+ continue;
+ if (ei_endpfn > end_user_pfn)
+ ei_endpfn = end_user_pfn;
+
+ add_active_range(nid, ei_startpfn, ei_endpfn);
+ }
+}
+
/*
* Add a memory region to the kernel e820 map.
*/
@@ -517,13 +527,6 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
* If we're lucky and live on a modern system, the setup code
* will have given us a memory map that we can use to properly
* set up memory. If we aren't, we'll fake a memory map.
- *
- * We check to see that the memory map contains at least 2 elements
- * before we'll use it, because the detection code in setup.S may
- * not be perfect and most every PC known to man has two memory
- * regions: one from 0 to 640k, and one from 1mb up. (The IBM
- * thinkpad 560x, for example, does not cooperate with the memory
- * detection code.)
*/
static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
{
@@ -541,34 +544,19 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
if (start > end)
return -1;
- /*
- * Some BIOSes claim RAM in the 640k - 1M region.
- * Not right. Fix it up.
- *
- * This should be removed on Hammer which is supposed to not
- * have non e820 covered ISA mappings there, but I had some strange
- * problems so it stays for now. -AK
- */
- if (type == E820_RAM) {
- if (start < 0x100000ULL && end > 0xA0000ULL) {
- if (start < 0xA0000ULL)
- add_memory_region(start, 0xA0000ULL-start, type);
- if (end <= 0x100000ULL)
- continue;
- start = 0x100000ULL;
- size = end - start;
- }
- }
-
add_memory_region(start, size, type);
} while (biosmap++,--nr_map);
return 0;
}
-void __init setup_memory_region(void)
+void early_panic(char *msg)
{
- char *who = "BIOS-e820";
+ early_printk(msg);
+ panic(msg);
+}
+void __init setup_memory_region(void)
+{
/*
* Try to copy the BIOS-supplied E820-map.
*
@@ -576,51 +564,70 @@ void __init setup_memory_region(void)
* the next section from 1mb->appropriate_mem_k
*/
sanitize_e820_map(E820_MAP, &E820_MAP_NR);
- if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
- unsigned long mem_size;
-
- /* compare results from other methods and take the greater */
- if (ALT_MEM_K < EXT_MEM_K) {
- mem_size = EXT_MEM_K;
- who = "BIOS-88";
- } else {
- mem_size = ALT_MEM_K;
- who = "BIOS-e801";
- }
-
- e820.nr_map = 0;
- add_memory_region(0, LOWMEMSIZE(), E820_RAM);
- add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
- }
+ if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
+ early_panic("Cannot find a valid memory map");
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
- e820_print_map(who);
+ e820_print_map("BIOS-e820");
}
-void __init parse_memopt(char *p, char **from)
-{
- end_user_pfn = memparse(p, from);
+static int __init parse_memopt(char *p)
+{
+ if (!p)
+ return -EINVAL;
+ end_user_pfn = memparse(p, &p);
end_user_pfn >>= PAGE_SHIFT;
+ return 0;
}
+early_param("mem", parse_memopt);
+
+static int userdef __initdata;
-void __init parse_memmapopt(char *p, char **from)
+static int __init parse_memmap_opt(char *p)
{
+ char *oldp;
unsigned long long start_at, mem_size;
- mem_size = memparse(p, from);
- p = *from;
+ if (!strcmp(p, "exactmap")) {
+#ifdef CONFIG_CRASH_DUMP
+ /* If we are doing a crash dump, we
+ * still need to know the real mem
+ * size before original memory map is
+ * reset.
+ */
+ saved_max_pfn = e820_end_of_ram();
+#endif
+ end_pfn_map = 0;
+ e820.nr_map = 0;
+ userdef = 1;
+ return 0;
+ }
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
if (*p == '@') {
- start_at = memparse(p+1, from);
+ start_at = memparse(p+1, &p);
add_memory_region(start_at, mem_size, E820_RAM);
} else if (*p == '#') {
- start_at = memparse(p+1, from);
+ start_at = memparse(p+1, &p);
add_memory_region(start_at, mem_size, E820_ACPI);
} else if (*p == '$') {
- start_at = memparse(p+1, from);
+ start_at = memparse(p+1, &p);
add_memory_region(start_at, mem_size, E820_RESERVED);
} else {
end_user_pfn = (mem_size >> PAGE_SHIFT);
}
- p = *from;
+ return *p == '\0' ? 0 : -EINVAL;
+}
+early_param("memmap", parse_memmap_opt);
+
+void finish_e820_parsing(void)
+{
+ if (userdef) {
+ printk(KERN_INFO "user-defined physical RAM map:\n");
+ e820_print_map("user");
+ }
}
unsigned long pci_mem_start = 0xaeedbabe;
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
new file mode 100644
index 00000000000..208e38a372c
--- /dev/null
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -0,0 +1,122 @@
+/* Various workarounds for chipset bugs.
+ This code runs very early and can't use the regular PCI subsystem
+ The entries are keyed to PCI bridges which usually identify chipsets
+ uniquely.
+ This is only for whole classes of chipsets with specific problems which
+ need early invasive action (e.g. before the timers are initialized).
+ Most PCI device specific workarounds can be done later and should be
+ in standard PCI quirks
+ Mainboard specific bugs should be handled by DMI entries.
+ CPU specific bugs in setup.c */
+
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <linux/pci_ids.h>
+#include <asm/pci-direct.h>
+#include <asm/proto.h>
+#include <asm/dma.h>
+
+static void via_bugs(void)
+{
+#ifdef CONFIG_IOMMU
+ if ((end_pfn > MAX_DMA32_PFN || force_iommu) &&
+ !iommu_aperture_allowed) {
+ printk(KERN_INFO
+ "Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n");
+ iommu_aperture_disabled = 1;
+ }
+#endif
+}
+
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+ nvidia_hpet_detected = 1;
+ return 0;
+}
+#endif
+
+static void nvidia_bugs(void)
+{
+#ifdef CONFIG_ACPI
+ /*
+ * All timer overrides on Nvidia are
+ * wrong unless HPET is enabled.
+ */
+ nvidia_hpet_detected = 0;
+ acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
+ if (nvidia_hpet_detected == 0) {
+ acpi_skip_timer_override = 1;
+ printk(KERN_INFO "Nvidia board "
+ "detected. Ignoring ACPI "
+ "timer override.\n");
+ }
+#endif
+ /* RED-PEN skip them on mptables too? */
+
+}
+
+static void ati_bugs(void)
+{
+#if 1 /* for testing */
+ printk("ATI board detected\n");
+#endif
+ /* No bugs right now */
+}
+
+struct chipset {
+ u16 vendor;
+ void (*f)(void);
+};
+
+static struct chipset early_qrk[] = {
+ { PCI_VENDOR_ID_NVIDIA, nvidia_bugs },
+ { PCI_VENDOR_ID_VIA, via_bugs },
+ { PCI_VENDOR_ID_ATI, ati_bugs },
+ {}
+};
+
+void __init early_quirks(void)
+{
+ int num, slot, func;
+
+ if (!early_pci_allowed())
+ return;
+
+ /* Poor man's PCI discovery */
+ for (num = 0; num < 32; num++) {
+ for (slot = 0; slot < 32; slot++) {
+ for (func = 0; func < 8; func++) {
+ u32 class;
+ u32 vendor;
+ u8 type;
+ int i;
+ class = read_pci_config(num,slot,func,
+ PCI_CLASS_REVISION);
+ if (class == 0xffffffff)
+ break;
+
+ if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ continue;
+
+ vendor = read_pci_config(num, slot, func,
+ PCI_VENDOR_ID);
+ vendor &= 0xffff;
+
+ for (i = 0; early_qrk[i].f; i++)
+ if (early_qrk[i].vendor == vendor) {
+ early_qrk[i].f();
+ return;
+ }
+
+ type = read_pci_config_byte(num, slot, func,
+ PCI_HEADER_TYPE);
+ if (!(type & 0x80))
+ break;
+ }
+ }
+ }
+}
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 140051e07fa..e22ecd54870 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -215,20 +215,16 @@ void early_printk(const char *fmt, ...)
static int __initdata keep_early;
-int __init setup_early_printk(char *opt)
+static int __init setup_early_printk(char *buf)
{
- char *space;
- char buf[256];
+ if (!buf)
+ return 0;
if (early_console_initialized)
- return 1;
-
- strlcpy(buf,opt,sizeof(buf));
- space = strchr(buf, ' ');
- if (space)
- *space = 0;
+ return 0;
+ early_console_initialized = 1;
- if (strstr(buf,"keep"))
+ if (!strcmp(buf,"keep"))
keep_early = 1;
if (!strncmp(buf, "serial", 6)) {
@@ -248,11 +244,12 @@ int __init setup_early_printk(char *opt)
early_console = &simnow_console;
keep_early = 1;
}
- early_console_initialized = 1;
register_console(early_console);
return 0;
}
+early_param("earlyprintk", setup_early_printk);
+
void __init disable_early_printk(void)
{
if (!early_console_initialized || !early_console)
@@ -266,4 +263,3 @@ void __init disable_early_printk(void)
}
}
-__setup("earlyprintk=", setup_early_printk);
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index aa8d8939abc..2802524104f 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -4,8 +4,6 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs
* Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
- *
- * $Id$
*/
/*
@@ -22,15 +20,25 @@
* at the top of the kernel process stack.
* - partial stack frame: partially saved registers upto R11.
* - full stack frame: Like partial stack frame, but all register saved.
- *
- * TODO:
- * - schedule it carefully for the final hardware.
+ *
+ * Some macro usage:
+ * - CFI macros are used to generate dwarf2 unwind information for better
+ * backtraces. They don't change any code.
+ * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
+ * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
+ * There are unfortunately lots of special cases where some registers
+ * not touched. The macro is a big mess that should be cleaned up.
+ * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
+ * Gives a full stack frame.
+ * - ENTRY/END Define functions in the symbol table.
+ * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
+ * frame that is otherwise undefined after a SYSCALL
+ * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
+ * - errorentry/paranoidentry/zeroentry - Define exception entry points.
*/
-#define ASSEMBLY 1
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/smp.h>
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/dwarf2.h>
@@ -115,6 +123,7 @@
.macro CFI_DEFAULT_STACK start=1
.if \start
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,SS+8
.else
CFI_DEF_CFA_OFFSET SS+8
@@ -146,6 +155,10 @@
/* rdi: prev */
ENTRY(ret_from_fork)
CFI_DEFAULT_STACK
+ push kernel_eflags(%rip)
+ CFI_ADJUST_CFA_OFFSET 4
+ popf # reset kernel eflags
+ CFI_ADJUST_CFA_OFFSET -4
call schedule_tail
GET_THREAD_INFO(%rcx)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
@@ -199,6 +212,7 @@ END(ret_from_fork)
ENTRY(system_call)
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,PDA_STACKOFFSET
CFI_REGISTER rip,rcx
/*CFI_REGISTER rflags,r11*/
@@ -316,6 +330,7 @@ END(system_call)
*/
ENTRY(int_ret_from_sys_call)
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,SS+8-ARGOFFSET
/*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
CFI_REL_OFFSET rsp,RSP-ARGOFFSET
@@ -476,6 +491,7 @@ END(stub_rt_sigreturn)
*/
.macro _frame ref
CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
CFI_DEF_CFA rsp,SS+8-\ref
/*CFI_REL_OFFSET ss,SS-\ref*/
CFI_REL_OFFSET rsp,RSP-\ref
@@ -511,7 +527,12 @@ END(stub_rt_sigreturn)
testl $3,CS(%rdi)
je 1f
swapgs
-1: incl %gs:pda_irqcount # RED-PEN should check preempt count
+ /* irqcount is used to check if a CPU is already on an interrupt
+ stack or not. While this is essentially redundant with preempt_count
+ it is a little cheaper to use a separate counter in the PDA
+ (short of moving irq_enter into assembly, which would be too
+ much work) */
+1: incl %gs:pda_irqcount
cmoveq %gs:pda_irqstackptr,%rsp
push %rbp # backlink for old unwinder
/*
@@ -619,8 +640,7 @@ retint_signal:
#ifdef CONFIG_PREEMPT
/* Returning to kernel space. Check if we need preemption */
/* rcx: threadinfo. interrupts off. */
- .p2align
-retint_kernel:
+ENTRY(retint_kernel)
cmpl $0,threadinfo_preempt_count(%rcx)
jnz retint_restore_args
bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
@@ -679,7 +699,6 @@ ENTRY(call_function_interrupt)
END(call_function_interrupt)
#endif
-#ifdef CONFIG_X86_LOCAL_APIC
ENTRY(apic_timer_interrupt)
apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
END(apic_timer_interrupt)
@@ -691,7 +710,6 @@ END(error_interrupt)
ENTRY(spurious_interrupt)
apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
END(spurious_interrupt)
-#endif
/*
* Exception entry points.
@@ -768,7 +786,9 @@ paranoid_exit\trace:
testl $3,CS(%rsp)
jnz paranoid_userspace\trace
paranoid_swapgs\trace:
+ .if \trace
TRACE_IRQS_IRETQ 0
+ .endif
swapgs
paranoid_restore\trace:
RESTORE_ALL 8
@@ -814,7 +834,7 @@ paranoid_schedule\trace:
* Exception entry point. This expects an error code/orig_rax on the stack
* and the exception handler in %rax.
*/
-ENTRY(error_entry)
+KPROBE_ENTRY(error_entry)
_frame RDI
/* rdi slot contains rax, oldrax contains error code */
cld
@@ -898,7 +918,7 @@ error_kernelspace:
cmpq $gs_change,RIP(%rsp)
je error_swapgs
jmp error_sti
-END(error_entry)
+KPROBE_END(error_entry)
/* Reload gs selector with exception handling */
/* edi: new selector */
@@ -1020,8 +1040,7 @@ ENDPROC(execve)
KPROBE_ENTRY(page_fault)
errorentry do_page_fault
-END(page_fault)
- .previous .text
+KPROBE_END(page_fault)
ENTRY(coprocessor_error)
zeroentry do_coprocessor_error
@@ -1042,8 +1061,7 @@ KPROBE_ENTRY(debug)
CFI_ADJUST_CFA_OFFSET 8
paranoidentry do_debug, DEBUG_STACK
paranoidexit
-END(debug)
- .previous .text
+KPROBE_END(debug)
/* runs on exception stack */
KPROBE_ENTRY(nmi)
@@ -1057,8 +1075,7 @@ KPROBE_ENTRY(nmi)
jmp paranoid_exit1
CFI_ENDPROC
#endif
-END(nmi)
- .previous .text
+KPROBE_END(nmi)
KPROBE_ENTRY(int3)
INTR_FRAME
@@ -1067,8 +1084,7 @@ KPROBE_ENTRY(int3)
paranoidentry do_int3, DEBUG_STACK
jmp paranoid_exit1
CFI_ENDPROC
-END(int3)
- .previous .text
+KPROBE_END(int3)
ENTRY(overflow)
zeroentry do_overflow
@@ -1116,8 +1132,7 @@ END(stack_segment)
KPROBE_ENTRY(general_protection)
errorentry do_general_protection
-END(general_protection)
- .previous .text
+KPROBE_END(general_protection)
ENTRY(alignment_check)
errorentry do_alignment_check
diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
index 3020917546d..cdb90e671b8 100644
--- a/arch/x86_64/kernel/genapic_cluster.c
+++ b/arch/x86_64/kernel/genapic_cluster.c
@@ -118,7 +118,6 @@ struct genapic apic_cluster = {
.name = "clustered",
.int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
- .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
.target_cpus = cluster_target_cpus,
.apic_id_registered = cluster_apic_id_registered,
.init_apic_ldr = cluster_init_apic_ldr,
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index eb86d374813..50ad153eaac 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -49,8 +49,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
unsigned long cfg;
unsigned long flags;
- local_save_flags(flags);
- local_irq_disable();
+ local_irq_save(flags);
/*
* Wait for idle.
@@ -121,7 +120,6 @@ struct genapic apic_flat = {
.name = "flat",
.int_delivery_mode = dest_LowestPrio,
.int_dest_mode = (APIC_DEST_LOGICAL != 0),
- .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
.target_cpus = flat_target_cpus,
.apic_id_registered = flat_apic_id_registered,
.init_apic_ldr = flat_init_apic_ldr,
@@ -180,7 +178,6 @@ struct genapic apic_physflat = {
.name = "physical flat",
.int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
- .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
.target_cpus = physflat_target_cpus,
.apic_id_registered = flat_apic_id_registered,
.init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index c9739ca81d0..1e6f8087067 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -5,8 +5,6 @@
* Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
* Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
* Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
- *
- * $Id: head.S,v 1.49 2002/03/19 17:39:25 ak Exp $
*/
@@ -187,12 +185,15 @@ startup_64:
/* Finally jump to run C code and to be on real kernel address
* Since we are running on identity-mapped space we have to jump
- * to the full 64bit address , this is only possible as indirect
- * jump
+ * to the full 64bit address, this is only possible as indirect
+ * jump. In addition we need to ensure %cs is set so we make this
+ * a far return.
*/
movq initial_code(%rip),%rax
- pushq $0 # fake return address
- jmp *%rax
+ pushq $0 # fake return address to stop unwinder
+ pushq $__KERNEL_CS # set correct cs
+ pushq %rax # target address in negative space
+ lretq
/* SMP bootup changes these two */
.align 8
@@ -371,7 +372,7 @@ ENTRY(cpu_gdt_table)
.quad 0,0 /* TSS */
.quad 0,0 /* LDT */
.quad 0,0,0 /* three TLS descriptors */
- .quad 0 /* unused */
+ .quad 0x0000f40000000000 /* node/CPU stored in limit */
gdt_end:
/* asm/segment.h:GDT_ENTRIES must match this */
/* This should be a multiple of the cache line size */
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 36647ce6aec..9561eb3c5b5 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -45,38 +45,16 @@ static void __init copy_bootdata(char *real_mode_data)
new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
if (!new_data) {
if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
- printk("so old bootloader that it does not support commandline?!\n");
return;
}
new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
- printk("old bootloader convention, maybe loadlin?\n");
}
command_line = (char *) ((u64)(new_data));
memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
- printk("Bootdata ok (command line is %s)\n", saved_command_line);
-}
-
-static void __init setup_boot_cpu_data(void)
-{
- unsigned int dummy, eax;
-
- /* get vendor info */
- cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
- (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
- (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
- (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);
-
- /* get cpu type */
- cpuid(1, &eax, &dummy, &dummy,
- (unsigned int *) &boot_cpu_data.x86_capability);
- boot_cpu_data.x86 = (eax >> 8) & 0xf;
- boot_cpu_data.x86_model = (eax >> 4) & 0xf;
- boot_cpu_data.x86_mask = eax & 0xf;
}
void __init x86_64_start_kernel(char * real_mode_data)
{
- char *s;
int i;
for (i = 0; i < 256; i++)
@@ -84,10 +62,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
asm volatile("lidt %0" :: "m" (idt_descr));
clear_bss();
- /*
- * This must be called really, really early:
- */
- lockdep_init();
+ early_printk("Kernel alive\n");
/*
* switch to init_level4_pgt from boot_level4_pgt
@@ -103,22 +78,5 @@ void __init x86_64_start_kernel(char * real_mode_data)
#ifdef CONFIG_SMP
cpu_set(0, cpu_online_map);
#endif
- s = strstr(saved_command_line, "earlyprintk=");
- if (s != NULL)
- setup_early_printk(strchr(s, '=') + 1);
-#ifdef CONFIG_NUMA
- s = strstr(saved_command_line, "numa=");
- if (s != NULL)
- numa_setup(s+5);
-#endif
-#ifdef CONFIG_X86_IO_APIC
- if (strstr(saved_command_line, "disableapic"))
- disable_apic = 1;
-#endif
- /* You need early console to see that */
- if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE)
- panic("Kernel too big for kernel mapping\n");
-
- setup_boot_cpu_data();
start_kernel();
}
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 0434b1f8e3d..2dd51f364ea 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -55,7 +55,6 @@
*/
BUILD_16_IRQS(0x0)
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* The IO-APIC gives us many more interrupt sources. Most of these
* are unused but an SMP system is supposed to have enough memory ...
@@ -75,8 +74,6 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
BUILD_15_IRQS(0xe)
#endif
-#endif
-
#undef BUILD_16_IRQS
#undef BUILD_15_IRQS
#undef BI
@@ -100,7 +97,6 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
void (*interrupt[NR_IRQS])(void) = {
IRQLIST_16(0x0),
-#ifdef CONFIG_X86_IO_APIC
IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
@@ -110,7 +106,6 @@ void (*interrupt[NR_IRQS])(void) = {
, IRQLIST_15(0xe)
#endif
-#endif
};
#undef IRQ
@@ -128,6 +123,8 @@ void (*interrupt[NR_IRQS])(void) = {
DEFINE_SPINLOCK(i8259A_lock);
+static int i8259A_auto_eoi;
+
static void end_8259A_irq (unsigned int irq)
{
if (irq > 256) {
@@ -341,6 +338,8 @@ void init_8259A(int auto_eoi)
{
unsigned long flags;
+ i8259A_auto_eoi = auto_eoi;
+
spin_lock_irqsave(&i8259A_lock, flags);
outb(0xff, 0x21); /* mask all of 8259A-1 */
@@ -399,7 +398,7 @@ static void save_ELCR(char *trigger)
static int i8259A_resume(struct sys_device *dev)
{
- init_8259A(0);
+ init_8259A(i8259A_auto_eoi);
restore_ELCR(irq_trigger);
return 0;
}
@@ -453,9 +452,7 @@ void __init init_ISA_irqs (void)
{
int i;
-#ifdef CONFIG_X86_LOCAL_APIC
init_bsp_APIC();
-#endif
init_8259A(0);
for (i = 0; i < NR_IRQS; i++) {
@@ -581,14 +578,12 @@ void __init init_IRQ(void)
set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
-#ifdef CONFIG_X86_LOCAL_APIC
/* self generated IPI for local APIC timer */
set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
/* IPI vectors for APIC spurious and error interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-#endif
/*
* Set the clock to HZ Hz, we already have a valid
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 924a4a33295..0491019d4c8 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -48,7 +48,7 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
static int no_timer_check;
-int disable_timer_pin_1 __initdata;
+static int disable_timer_pin_1 __initdata;
int timer_over_8254 __initdata = 0;
@@ -111,6 +111,33 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
FINAL; \
}
+union entry_union {
+ struct { u32 w1, w2; };
+ struct IO_APIC_route_entry entry;
+};
+
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+ union entry_union eu;
+ unsigned long flags;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+ eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ return eu.entry;
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+ unsigned long flags;
+ union entry_union eu;
+ eu.entry = e;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+ io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
#ifdef CONFIG_SMP
static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
{
@@ -196,13 +223,9 @@ static void unmask_IO_APIC_irq (unsigned int irq)
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
- unsigned long flags;
/* Check delivery_mode to be sure we're not clearing an SMI pin */
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
- *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry = ioapic_read_entry(apic, pin);
if (entry.delivery_mode == dest_SMI)
return;
/*
@@ -210,10 +233,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
*/
memset(&entry, 0, sizeof(entry));
entry.mask = 1;
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(apic, pin, entry);
}
static void clear_IO_APIC (void)
@@ -225,14 +245,6 @@ static void clear_IO_APIC (void)
clear_IO_APIC_pin(apic, pin);
}
-/*
- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
- * specific CPU-side IRQs.
- */
-
-#define MAX_PIRQS 8
-static int pirq_entries [MAX_PIRQS];
-static int pirqs_enabled;
int skip_ioapic_setup;
int ioapic_force;
@@ -241,18 +253,17 @@ int ioapic_force;
static int __init disable_ioapic_setup(char *str)
{
skip_ioapic_setup = 1;
- return 1;
+ return 0;
}
+early_param("noapic", disable_ioapic_setup);
-static int __init enable_ioapic_setup(char *str)
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+static int __init disable_timer_pin_setup(char *arg)
{
- ioapic_force = 1;
- skip_ioapic_setup = 0;
+ disable_timer_pin_1 = 1;
return 1;
}
-
-__setup("noapic", disable_ioapic_setup);
-__setup("apic", enable_ioapic_setup);
+__setup("disable_timer_pin_1", disable_timer_pin_setup);
static int __init setup_disable_8254_timer(char *s)
{
@@ -268,135 +279,6 @@ static int __init setup_enable_8254_timer(char *s)
__setup("disable_8254_timer", setup_disable_8254_timer);
__setup("enable_8254_timer", setup_enable_8254_timer);
-#include <asm/pci-direct.h>
-#include <linux/pci_ids.h>
-#include <linux/pci.h>
-
-
-#ifdef CONFIG_ACPI
-
-static int nvidia_hpet_detected __initdata;
-
-static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
-{
- nvidia_hpet_detected = 1;
- return 0;
-}
-#endif
-
-/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
- off. Check for an Nvidia or VIA PCI bridge and turn it off.
- Use pci direct infrastructure because this runs before the PCI subsystem.
-
- Can be overwritten with "apic"
-
- And another hack to disable the IOMMU on VIA chipsets.
-
- ... and others. Really should move this somewhere else.
-
- Kludge-O-Rama. */
-void __init check_ioapic(void)
-{
- int num,slot,func;
- /* Poor man's PCI discovery */
- for (num = 0; num < 32; num++) {
- for (slot = 0; slot < 32; slot++) {
- for (func = 0; func < 8; func++) {
- u32 class;
- u32 vendor;
- u8 type;
- class = read_pci_config(num,slot,func,
- PCI_CLASS_REVISION);
- if (class == 0xffffffff)
- break;
-
- if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
- continue;
-
- vendor = read_pci_config(num, slot, func,
- PCI_VENDOR_ID);
- vendor &= 0xffff;
- switch (vendor) {
- case PCI_VENDOR_ID_VIA:
-#ifdef CONFIG_IOMMU
- if ((end_pfn > MAX_DMA32_PFN ||
- force_iommu) &&
- !iommu_aperture_allowed) {
- printk(KERN_INFO
- "Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
- iommu_aperture_disabled = 1;
- }
-#endif
- return;
- case PCI_VENDOR_ID_NVIDIA:
-#ifdef CONFIG_ACPI
- /*
- * All timer overrides on Nvidia are
- * wrong unless HPET is enabled.
- */
- nvidia_hpet_detected = 0;
- acpi_table_parse(ACPI_HPET,
- nvidia_hpet_check);
- if (nvidia_hpet_detected == 0) {
- acpi_skip_timer_override = 1;
- printk(KERN_INFO "Nvidia board "
- "detected. Ignoring ACPI "
- "timer override.\n");
- }
-#endif
- /* RED-PEN skip them on mptables too? */
- return;
-
- /* This should be actually default, but
- for 2.6.16 let's do it for ATI only where
- it's really needed. */
- case PCI_VENDOR_ID_ATI:
- if (timer_over_8254 == 1) {
- timer_over_8254 = 0;
- printk(KERN_INFO
- "ATI board detected. Disabling timer routing over 8254.\n");
- }
- return;
- }
-
-
- /* No multi-function device? */
- type = read_pci_config_byte(num,slot,func,
- PCI_HEADER_TYPE);
- if (!(type & 0x80))
- break;
- }
- }
- }
-}
-
-static int __init ioapic_pirq_setup(char *str)
-{
- int i, max;
- int ints[MAX_PIRQS+1];
-
- get_options(str, ARRAY_SIZE(ints), ints);
-
- for (i = 0; i < MAX_PIRQS; i++)
- pirq_entries[i] = -1;
-
- pirqs_enabled = 1;
- apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
- max = MAX_PIRQS;
- if (ints[0] < MAX_PIRQS)
- max = ints[0];
-
- for (i = 0; i < max; i++) {
- apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
- /*
- * PIRQs are mapped upside down, usually.
- */
- pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
- }
- return 1;
-}
-
-__setup("pirq=", ioapic_pirq_setup);
/*
* Find the IRQ entry number of a certain pin.
@@ -425,9 +307,7 @@ static int __init find_isa_irq_pin(int irq, int type)
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;
- if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+ if (test_bit(lbus, mp_bus_not_pci) &&
(mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq))
@@ -443,9 +323,7 @@ static int __init find_isa_irq_apic(int irq, int type)
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;
- if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+ if (test_bit(lbus, mp_bus_not_pci) &&
(mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq))
break;
@@ -485,7 +363,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
break;
- if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
+ if (!test_bit(lbus, mp_bus_not_pci) &&
!mp_irqs[i].mpc_irqtype &&
(bus == lbus) &&
(slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
@@ -508,27 +386,6 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
return best_guess;
}
-/*
- * EISA Edge/Level control register, ELCR
- */
-static int EISA_ELCR(unsigned int irq)
-{
- if (irq < 16) {
- unsigned int port = 0x4d0 + (irq >> 3);
- return (inb(port) >> (irq & 7)) & 1;
- }
- apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
- return 0;
-}
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value. If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
-#define default_EISA_polarity(idx) (0)
-
/* ISA interrupts are always polarity zero edge triggered,
* when listed as conforming in the MP table. */
@@ -541,12 +398,6 @@ static int EISA_ELCR(unsigned int irq)
#define default_PCI_trigger(idx) (1)
#define default_PCI_polarity(idx) (1)
-/* MCA interrupts are always polarity zero level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_MCA_trigger(idx) (1)
-#define default_MCA_polarity(idx) (0)
-
static int __init MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
@@ -558,38 +409,11 @@ static int __init MPBIOS_polarity(int idx)
switch (mp_irqs[idx].mpc_irqflag & 3)
{
case 0: /* conforms, ie. bus-type dependent polarity */
- {
- switch (mp_bus_id_to_type[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- {
- polarity = default_ISA_polarity(idx);
- break;
- }
- case MP_BUS_EISA: /* EISA pin */
- {
- polarity = default_EISA_polarity(idx);
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- polarity = default_PCI_polarity(idx);
- break;
- }
- case MP_BUS_MCA: /* MCA pin */
- {
- polarity = default_MCA_polarity(idx);
- break;
- }
- default:
- {
- printk(KERN_WARNING "broken BIOS!!\n");
- polarity = 1;
- break;
- }
- }
+ if (test_bit(bus, mp_bus_not_pci))
+ polarity = default_ISA_polarity(idx);
+ else
+ polarity = default_PCI_polarity(idx);
break;
- }
case 1: /* high active */
{
polarity = 0;
@@ -627,38 +451,11 @@ static int MPBIOS_trigger(int idx)
switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
{
case 0: /* conforms, ie. bus-type dependent */
- {
- switch (mp_bus_id_to_type[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- {
- trigger = default_ISA_trigger(idx);
- break;
- }
- case MP_BUS_EISA: /* EISA pin */
- {
- trigger = default_EISA_trigger(idx);
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- trigger = default_PCI_trigger(idx);
- break;
- }
- case MP_BUS_MCA: /* MCA pin */
- {
- trigger = default_MCA_trigger(idx);
- break;
- }
- default:
- {
- printk(KERN_WARNING "broken BIOS!!\n");
- trigger = 1;
- break;
- }
- }
+ if (test_bit(bus, mp_bus_not_pci))
+ trigger = default_ISA_trigger(idx);
+ else
+ trigger = default_PCI_trigger(idx);
break;
- }
case 1: /* edge */
{
trigger = 0;
@@ -764,49 +561,17 @@ static int pin_2_irq(int idx, int apic, int pin)
if (mp_irqs[idx].mpc_dstirq != pin)
printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
- switch (mp_bus_id_to_type[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- case MP_BUS_EISA:
- case MP_BUS_MCA:
- {
- irq = mp_irqs[idx].mpc_srcbusirq;
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- /*
- * PCI IRQs are mapped in order
- */
- i = irq = 0;
- while (i < apic)
- irq += nr_ioapic_registers[i++];
- irq += pin;
- irq = gsi_irq_sharing(irq);
- break;
- }
- default:
- {
- printk(KERN_ERR "unknown bus type %d.\n",bus);
- irq = 0;
- break;
- }
- }
- BUG_ON(irq >= NR_IRQS);
-
- /*
- * PCI IRQ command line redirection. Yes, limits are hardcoded.
- */
- if ((pin >= 16) && (pin <= 23)) {
- if (pirq_entries[pin-16] != -1) {
- if (!pirq_entries[pin-16]) {
- apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
- } else {
- irq = pirq_entries[pin-16];
- apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
- pin-16, irq);
- }
- }
+ if (test_bit(bus, mp_bus_not_pci)) {
+ irq = mp_irqs[idx].mpc_srcbusirq;
+ } else {
+ /*
+ * PCI IRQs are mapped in order
+ */
+ i = irq = 0;
+ while (i < apic)
+ irq += nr_ioapic_registers[i++];
+ irq += pin;
+ irq = gsi_irq_sharing(irq);
}
BUG_ON(irq >= NR_IRQS);
return irq;
@@ -943,9 +708,9 @@ static void __init setup_IO_APIC_irqs(void)
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}
+ ioapic_write_entry(apic, pin, entry);
+
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
@@ -1083,10 +848,7 @@ void __apicdebuginit print_IO_APIC(void)
for (i = 0; i <= reg_01.bits.entries; i++) {
struct IO_APIC_route_entry entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
- *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ entry = ioapic_read_entry(apic, i);
printk(KERN_DEBUG " %02x %03X %02X ",
i,
@@ -1281,9 +1043,6 @@ static void __init enable_IO_APIC(void)
irq_2_pin[i].pin = -1;
irq_2_pin[i].next = 0;
}
- if (!pirqs_enabled)
- for (i = 0; i < MAX_PIRQS; i++)
- pirq_entries[i] = -1;
/*
* The number of IO-APIC IRQ registers (== #pins):
@@ -1299,11 +1058,7 @@ static void __init enable_IO_APIC(void)
/* See if any of the pins is in ExtINT mode */
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
- *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
+ entry = ioapic_read_entry(apic, pin);
/* If the interrupt line is enabled and in ExtInt mode
* I have found the pin where the i8259 is connected.
@@ -1355,7 +1110,6 @@ void disable_IO_APIC(void)
*/
if (ioapic_i8259.pin != -1) {
struct IO_APIC_route_entry entry;
- unsigned long flags;
memset(&entry, 0, sizeof(entry));
entry.mask = 0; /* Enabled */
@@ -1372,84 +1126,13 @@ void disable_IO_APIC(void)
/*
* Add it to the IO-APIC irq-routing table:
*/
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
- *(((int *)&entry)+1));
- io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
- *(((int *)&entry)+0));
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
}
disconnect_bsp_APIC(ioapic_i8259.pin != -1);
}
/*
- * function to set the IO-APIC physical IDs based on the
- * values stored in the MPC table.
- *
- * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
- */
-
-static void __init setup_ioapic_ids_from_mpc (void)
-{
- union IO_APIC_reg_00 reg_00;
- int apic;
- int i;
- unsigned char old_id;
- unsigned long flags;
-
- /*
- * Set the IOAPIC ID to the value stored in the MPC table.
- */
- for (apic = 0; apic < nr_ioapics; apic++) {
-
- /* Read the register 0 value */
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic, 0);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
- old_id = mp_ioapics[apic].mpc_apicid;
-
-
- printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
-
-
- /*
- * We need to adjust the IRQ routing table
- * if the ID changed.
- */
- if (old_id != mp_ioapics[apic].mpc_apicid)
- for (i = 0; i < mp_irq_entries; i++)
- if (mp_irqs[i].mpc_dstapic == old_id)
- mp_irqs[i].mpc_dstapic
- = mp_ioapics[apic].mpc_apicid;
-
- /*
- * Read the right value from the MPC table and
- * write it into the ID register.
- */
- apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
- mp_ioapics[apic].mpc_apicid);
-
- reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0, reg_00.raw);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
- /*
- * Sanity check
- */
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic, 0);
- spin_unlock_irqrestore(&ioapic_lock, flags);
- if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
- printk("could not set ID!\n");
- else
- apic_printk(APIC_VERBOSE," ok.\n");
- }
-}
-
-/*
* There is a nasty bug in some older SMP boards, their mptable lies
* about the timer IRQ. We do the following to work around the situation:
*
@@ -1964,11 +1647,6 @@ void __init setup_IO_APIC(void)
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
- /*
- * Set up the IO-APIC IRQ routing table.
- */
- if (!acpi_ioapic)
- setup_ioapic_ids_from_mpc();
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
@@ -1987,17 +1665,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
{
struct IO_APIC_route_entry *entry;
struct sysfs_ioapic_data *data;
- unsigned long flags;
int i;
data = container_of(dev, struct sysfs_ioapic_data, dev);
entry = data->entry;
- spin_lock_irqsave(&ioapic_lock, flags);
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
- *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
- }
- spin_unlock_irqrestore(&ioapic_lock, flags);
+ for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+ *entry = ioapic_read_entry(dev->id, i);
return 0;
}
@@ -2019,11 +1692,9 @@ static int ioapic_resume(struct sys_device *dev)
reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
io_apic_write(dev->id, 0, reg_00.raw);
}
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
- io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
- }
spin_unlock_irqrestore(&ioapic_lock, flags);
+ for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+ ioapic_write_entry(dev->id, i, entry[i]);
return 0;
}
@@ -2077,19 +1748,6 @@ device_initcall(ioapic_init_sysfs);
#define IO_APIC_MAX_ID 0xFE
-int __init io_apic_get_version (int ioapic)
-{
- union IO_APIC_reg_01 reg_01;
- unsigned long flags;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(ioapic, 1);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
- return reg_01.bits.version;
-}
-
-
int __init io_apic_get_redir_entries (int ioapic)
{
union IO_APIC_reg_01 reg_01;
@@ -2148,10 +1806,10 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
if (!ioapic && (irq < 16))
disable_8259A_irq(irq);
+ ioapic_write_entry(ioapic, pin, entry);
+
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
- set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
+ set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
return 0;
diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
index b81614970ec..fe063d3cfe4 100644
--- a/arch/x86_64/kernel/ioport.c
+++ b/arch/x86_64/kernel/ioport.c
@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
memset(bitmap, 0xff, IO_BITMAP_BYTES);
t->io_bitmap_ptr = bitmap;
+ set_thread_flag(TIF_IO_BITMAP);
}
/*
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 5221a53e90c..b3677e6ccc6 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -20,11 +20,6 @@
#include <asm/idle.h>
atomic_t irq_err_count;
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
-atomic_t irq_mis_count;
-#endif
-#endif
#ifdef CONFIG_DEBUG_STACKOVERFLOW
/*
@@ -92,18 +87,11 @@ skip:
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
seq_putc(p, '\n');
-#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
seq_putc(p, '\n');
-#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
- seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
-#endif
-#endif
}
return 0;
}
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
index 106076b370f..0497e3bd5bf 100644
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -15,6 +15,15 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+static u64 kexec_pgd[512] PAGE_ALIGNED;
+static u64 kexec_pud0[512] PAGE_ALIGNED;
+static u64 kexec_pmd0[512] PAGE_ALIGNED;
+static u64 kexec_pte0[512] PAGE_ALIGNED;
+static u64 kexec_pud1[512] PAGE_ALIGNED;
+static u64 kexec_pmd1[512] PAGE_ALIGNED;
+static u64 kexec_pte1[512] PAGE_ALIGNED;
+
static void init_level2_page(pmd_t *level2p, unsigned long addr)
{
unsigned long end_addr;
@@ -144,32 +153,19 @@ static void load_segments(void)
);
}
-typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page,
- unsigned long control_code_buffer,
- unsigned long start_address,
- unsigned long pgtable) ATTRIB_NORET;
-
-extern const unsigned char relocate_new_kernel[];
-extern const unsigned long relocate_new_kernel_size;
-
int machine_kexec_prepare(struct kimage *image)
{
- unsigned long start_pgtable, control_code_buffer;
+ unsigned long start_pgtable;
int result;
/* Calculate the offsets */
start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
- control_code_buffer = start_pgtable + PAGE_SIZE;
/* Setup the identity mapped 64bit page table */
result = init_pgtable(image, start_pgtable);
if (result)
return result;
- /* Place the code in the reboot code buffer */
- memcpy(__va(control_code_buffer), relocate_new_kernel,
- relocate_new_kernel_size);
-
return 0;
}
@@ -184,28 +180,34 @@ void machine_kexec_cleanup(struct kimage *image)
*/
NORET_TYPE void machine_kexec(struct kimage *image)
{
- unsigned long page_list;
- unsigned long control_code_buffer;
- unsigned long start_pgtable;
- relocate_new_kernel_t rnk;
+ unsigned long page_list[PAGES_NR];
+ void *control_page;
/* Interrupts aren't acceptable while we reboot */
local_irq_disable();
- /* Calculate the offsets */
- page_list = image->head;
- start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
- control_code_buffer = start_pgtable + PAGE_SIZE;
-
- /* Set the low half of the page table to my identity mapped
- * page table for kexec. Leave the high half pointing at the
- * kernel pages. Don't bother to flush the global pages
- * as that will happen when I fully switch to my identity mapped
- * page table anyway.
- */
- memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2);
- __flush_tlb();
-
+ control_page = page_address(image->control_code_page) + PAGE_SIZE;
+ memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+ page_list[PA_CONTROL_PAGE] = __pa(control_page);
+ page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
+ page_list[PA_PGD] = __pa(kexec_pgd);
+ page_list[VA_PGD] = (unsigned long)kexec_pgd;
+ page_list[PA_PUD_0] = __pa(kexec_pud0);
+ page_list[VA_PUD_0] = (unsigned long)kexec_pud0;
+ page_list[PA_PMD_0] = __pa(kexec_pmd0);
+ page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
+ page_list[PA_PTE_0] = __pa(kexec_pte0);
+ page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
+ page_list[PA_PUD_1] = __pa(kexec_pud1);
+ page_list[VA_PUD_1] = (unsigned long)kexec_pud1;
+ page_list[PA_PMD_1] = __pa(kexec_pmd1);
+ page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
+ page_list[PA_PTE_1] = __pa(kexec_pte1);
+ page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
+
+ page_list[PA_TABLE_PAGE] =
+ (unsigned long)__pa(page_address(image->control_code_page));
/* The segment registers are funny things, they have both a
* visible and an invisible part. Whenever the visible part is
@@ -222,7 +224,36 @@ NORET_TYPE void machine_kexec(struct kimage *image)
*/
set_gdt(phys_to_virt(0),0);
set_idt(phys_to_virt(0),0);
+
/* now call it */
- rnk = (relocate_new_kernel_t) control_code_buffer;
- (*rnk)(page_list, control_code_buffer, image->start, start_pgtable);
+ relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
+ image->start);
}
+
+/* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel. By reserving this memory we guarantee
+ * that linux never set's it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+static int __init setup_crashkernel(char *arg)
+{
+ unsigned long size, base;
+ char *p;
+ if (!arg)
+ return -EINVAL;
+ size = memparse(arg, &p);
+ if (arg == p)
+ return -EINVAL;
+ if (*p == '@') {
+ base = memparse(p+1, &p);
+ /* FIXME: Do I want a sanity check to validate the
+ * memory range? Yes you do, but it's too early for
+ * e820 -AK */
+ crashk_res.start = base;
+ crashk_res.end = base + size - 1;
+ }
+ return 0;
+}
+early_param("crashkernel", setup_crashkernel);
+
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 4e017fb30fb..bbea88801d8 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -182,7 +182,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
goto out2;
memset(&m, 0, sizeof(struct mce));
- m.cpu = safe_smp_processor_id();
+ m.cpu = smp_processor_id();
rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
if (!(m.mcgstatus & MCG_STATUS_RIPV))
kill_it = 1;
@@ -274,6 +274,33 @@ void do_machine_check(struct pt_regs * regs, long error_code)
atomic_dec(&mce_entry);
}
+#ifdef CONFIG_X86_MCE_INTEL
+/***
+ * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog
+ * @cpu: The CPU on which the event occured.
+ * @status: Event status information
+ *
+ * This function should be called by the thermal interrupt after the
+ * event has been processed and the decision was made to log the event
+ * further.
+ *
+ * The status parameter will be saved to the 'status' field of 'struct mce'
+ * and historically has been the register value of the
+ * MSR_IA32_THERMAL_STATUS (Intel) msr.
+ */
+void mce_log_therm_throt_event(unsigned int cpu, __u64 status)
+{
+ struct mce m;
+
+ memset(&m, 0, sizeof(m));
+ m.cpu = cpu;
+ m.bank = MCE_THERMAL_BANK;
+ m.status = status;
+ rdtscll(m.tsc);
+ mce_log(&m);
+}
+#endif /* CONFIG_X86_MCE_INTEL */
+
/*
* Periodic polling timer for "silent" machine check errors.
*/
diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c
index 8f533d2c40c..6551505d8a2 100644
--- a/arch/x86_64/kernel/mce_intel.c
+++ b/arch/x86_64/kernel/mce_intel.c
@@ -11,36 +11,21 @@
#include <asm/mce.h>
#include <asm/hw_irq.h>
#include <asm/idle.h>
-
-static DEFINE_PER_CPU(unsigned long, next_check);
+#include <asm/therm_throt.h>
asmlinkage void smp_thermal_interrupt(void)
{
- struct mce m;
+ __u64 msr_val;
ack_APIC_irq();
exit_idle();
irq_enter();
- if (time_before(jiffies, __get_cpu_var(next_check)))
- goto done;
-
- __get_cpu_var(next_check) = jiffies + HZ*300;
- memset(&m, 0, sizeof(m));
- m.cpu = smp_processor_id();
- m.bank = MCE_THERMAL_BANK;
- rdtscll(m.tsc);
- rdmsrl(MSR_IA32_THERM_STATUS, m.status);
- if (m.status & 0x1) {
- printk(KERN_EMERG
- "CPU%d: Temperature above threshold, cpu clock throttled\n", m.cpu);
- add_taint(TAINT_MACHINE_CHECK);
- } else {
- printk(KERN_EMERG "CPU%d: Temperature/speed normal\n", m.cpu);
- }
- mce_log(&m);
-done:
+ rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+ if (therm_throt_process(msr_val & 1))
+ mce_log_therm_throt_event(smp_processor_id(), msr_val);
+
irq_exit();
}
@@ -92,6 +77,9 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
cpu, tm2 ? "TM2" : "TM1");
+
+ /* enable thermal throttle processing */
+ atomic_set(&therm_throt_en, 1);
return;
}
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index a1ab4197f8a..20e88f4b564 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -41,8 +41,7 @@ int acpi_found_madt;
* Various Linux-internal data structures created from the
* MP-table.
*/
-unsigned char apic_version [MAX_APICS];
-unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
static int mp_current_pci_id = 0;
@@ -56,7 +55,6 @@ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
int mp_irq_entries;
int nr_ioapics;
-int pic_mode;
unsigned long mp_lapic_addr = 0;
@@ -71,19 +69,6 @@ unsigned disabled_cpus __initdata;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
-/* ACPI MADT entry parsing functions */
-#ifdef CONFIG_ACPI
-extern struct acpi_boot_flags acpi_boot;
-#ifdef CONFIG_X86_LOCAL_APIC
-extern int acpi_parse_lapic (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_LOCAL_APIC*/
-#ifdef CONFIG_X86_IO_APIC
-extern int acpi_parse_ioapic (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_IO_APIC*/
-#endif /*CONFIG_ACPI*/
-
u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
@@ -108,24 +93,20 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
{
int cpu;
- unsigned char ver;
cpumask_t tmp_map;
+ char *bootup_cpu = "";
if (!(m->mpc_cpuflag & CPU_ENABLED)) {
disabled_cpus++;
return;
}
-
- printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
- m->mpc_apicid,
- (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
- (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
- m->mpc_apicver);
-
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
- Dprintk(" Bootup CPU\n");
+ bootup_cpu = " (Bootup-CPU)";
boot_cpu_id = m->mpc_apicid;
}
+
+ printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+
if (num_processors >= NR_CPUS) {
printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
" Processor ignored.\n", NR_CPUS);
@@ -136,24 +117,7 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
cpus_complement(tmp_map, cpu_present_map);
cpu = first_cpu(tmp_map);
-#if MAX_APICS < 255
- if ((int)m->mpc_apicid > MAX_APICS) {
- printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
- return;
- }
-#endif
- ver = m->mpc_apicver;
-
physid_set(m->mpc_apicid, phys_cpu_present_map);
- /*
- * Validate version
- */
- if (ver == 0x0) {
- printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
- ver = 0x10;
- }
- apic_version[m->mpc_apicid] = ver;
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
/*
* bios_cpu_apicid is required to have processors listed
@@ -178,15 +142,11 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
if (strncmp(str, "ISA", 3) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
- } else if (strncmp(str, "EISA", 4) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+ set_bit(m->mpc_busid, mp_bus_not_pci);
} else if (strncmp(str, "PCI", 3) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+ clear_bit(m->mpc_busid, mp_bus_not_pci);
mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
mp_current_pci_id++;
- } else if (strncmp(str, "MCA", 3) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
} else {
printk(KERN_ERR "Unknown bustype %s\n", str);
}
@@ -197,8 +157,8 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
if (!(m->mpc_flags & MPC_APIC_USABLE))
return;
- printk("I/O APIC #%d Version %d at 0x%X.\n",
- m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+ printk("I/O APIC #%d at 0x%X.\n",
+ m->mpc_apicid, m->mpc_apicaddr);
if (nr_ioapics >= MAX_IO_APICS) {
printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
MAX_IO_APICS, nr_ioapics);
@@ -232,19 +192,6 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
- /*
- * Well it seems all SMP boards in existence
- * use ExtINT/LVT1 == LINT0 and
- * NMI/LVT2 == LINT1 - the following check
- * will show us if this assumptions is false.
- * Until then we do not have to add baggage.
- */
- if ((m->mpc_irqtype == mp_ExtINT) &&
- (m->mpc_destapiclint != 0))
- BUG();
- if ((m->mpc_irqtype == mp_NMI) &&
- (m->mpc_destapiclint != 1))
- BUG();
}
/*
@@ -258,7 +205,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
unsigned char *mpt=((unsigned char *)mpc)+count;
if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
- printk("SMP mptable: bad signature [%c%c%c%c]!\n",
+ printk("MPTABLE: bad signature [%c%c%c%c]!\n",
mpc->mpc_signature[0],
mpc->mpc_signature[1],
mpc->mpc_signature[2],
@@ -266,31 +213,31 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
return 0;
}
if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
- printk("SMP mptable: checksum error!\n");
+ printk("MPTABLE: checksum error!\n");
return 0;
}
if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
- printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
+ printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
mpc->mpc_spec);
return 0;
}
if (!mpc->mpc_lapic) {
- printk(KERN_ERR "SMP mptable: null local APIC address!\n");
+ printk(KERN_ERR "MPTABLE: null local APIC address!\n");
return 0;
}
memcpy(str,mpc->mpc_oem,8);
- str[8]=0;
- printk(KERN_INFO "OEM ID: %s ",str);
+ str[8] = 0;
+ printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
memcpy(str,mpc->mpc_productid,12);
- str[12]=0;
- printk("Product ID: %s ",str);
+ str[12] = 0;
+ printk("MPTABLE: Product ID: %s ",str);
- printk("APIC at: 0x%X\n",mpc->mpc_lapic);
+ printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
- mp_lapic_addr = mpc->mpc_lapic;
+ mp_lapic_addr = mpc->mpc_lapic;
/*
* Now process the configuration blocks.
@@ -302,7 +249,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
struct mpc_config_processor *m=
(struct mpc_config_processor *)mpt;
if (!acpi_lapic)
- MP_processor_info(m);
+ MP_processor_info(m);
mpt += sizeof(*m);
count += sizeof(*m);
break;
@@ -321,8 +268,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
struct mpc_config_ioapic *m=
(struct mpc_config_ioapic *)mpt;
MP_ioapic_info(m);
- mpt+=sizeof(*m);
- count+=sizeof(*m);
+ mpt += sizeof(*m);
+ count += sizeof(*m);
break;
}
case MP_INTSRC:
@@ -331,8 +278,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
(struct mpc_config_intsrc *)mpt;
MP_intsrc_info(m);
- mpt+=sizeof(*m);
- count+=sizeof(*m);
+ mpt += sizeof(*m);
+ count += sizeof(*m);
break;
}
case MP_LINTSRC:
@@ -340,15 +287,15 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
struct mpc_config_lintsrc *m=
(struct mpc_config_lintsrc *)mpt;
MP_lintsrc_info(m);
- mpt+=sizeof(*m);
- count+=sizeof(*m);
+ mpt += sizeof(*m);
+ count += sizeof(*m);
break;
}
}
}
clustered_apic_check();
if (!num_processors)
- printk(KERN_ERR "SMP mptable: no processors registered!\n");
+ printk(KERN_ERR "MPTABLE: no processors registered!\n");
return num_processors;
}
@@ -444,13 +391,10 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
* 2 CPUs, numbered 0 & 1.
*/
processor.mpc_type = MP_PROCESSOR;
- /* Either an integrated APIC or a discrete 82489DX. */
- processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ processor.mpc_apicver = 0;
processor.mpc_cpuflag = CPU_ENABLED;
- processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
- (boot_cpu_data.x86_model << 4) |
- boot_cpu_data.x86_mask;
- processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+ processor.mpc_cpufeature = 0;
+ processor.mpc_featureflag = 0;
processor.mpc_reserved[0] = 0;
processor.mpc_reserved[1] = 0;
for (i = 0; i < 2; i++) {
@@ -469,14 +413,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
case 5:
memcpy(bus.mpc_bustype, "ISA ", 6);
break;
- case 2:
- case 6:
- case 3:
- memcpy(bus.mpc_bustype, "EISA ", 6);
- break;
- case 4:
- case 7:
- memcpy(bus.mpc_bustype, "MCA ", 6);
}
MP_bus_info(&bus);
if (mpc_default_type > 4) {
@@ -487,7 +423,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
ioapic.mpc_type = MP_IOAPIC;
ioapic.mpc_apicid = 2;
- ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ ioapic.mpc_apicver = 0;
ioapic.mpc_flags = MPC_APIC_USABLE;
ioapic.mpc_apicaddr = 0xFEC00000;
MP_ioapic_info(&ioapic);
@@ -530,13 +466,6 @@ void __init get_smp_config (void)
printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
- if (mpf->mpf_feature2 & (1<<7)) {
- printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
- pic_mode = 1;
- } else {
- printk(KERN_INFO " Virtual Wire compatibility mode.\n");
- pic_mode = 0;
- }
/*
* Now see if we need to read further.
@@ -616,7 +545,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
return 0;
}
-void __init find_intel_smp (void)
+void __init find_smp_config(void)
{
unsigned int address;
@@ -633,9 +562,7 @@ void __init find_intel_smp (void)
smp_scan_config(0xF0000,0x10000))
return;
/*
- * If it is an SMP machine we should know now, unless the
- * configuration is in an EISA/MCA bus machine with an
- * extended bios data area.
+ * If it is an SMP machine we should know now.
*
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E, calculate and scan it here.
@@ -656,69 +583,41 @@ void __init find_intel_smp (void)
printk(KERN_INFO "No mptable found.\n");
}
-/*
- * - Intel MP Configuration Table
- */
-void __init find_smp_config (void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
- find_intel_smp();
-#endif
-}
-
-
/* --------------------------------------------------------------------------
ACPI-based MP Configuration
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI
-void __init mp_register_lapic_address (
- u64 address)
+void __init mp_register_lapic_address(u64 address)
{
mp_lapic_addr = (unsigned long) address;
-
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
-
if (boot_cpu_id == -1U)
boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
-
- Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
}
-
-void __cpuinit mp_register_lapic (
- u8 id,
- u8 enabled)
+void __cpuinit mp_register_lapic (u8 id, u8 enabled)
{
struct mpc_config_processor processor;
int boot_cpu = 0;
- if (id >= MAX_APICS) {
- printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
- id, MAX_APICS);
- return;
- }
-
- if (id == boot_cpu_physical_apicid)
+ if (id == boot_cpu_id)
boot_cpu = 1;
processor.mpc_type = MP_PROCESSOR;
processor.mpc_apicid = id;
- processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ processor.mpc_apicver = 0;
processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
- processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
- (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
- processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+ processor.mpc_cpufeature = 0;
+ processor.mpc_featureflag = 0;
processor.mpc_reserved[0] = 0;
processor.mpc_reserved[1] = 0;
MP_processor_info(&processor);
}
-#ifdef CONFIG_X86_IO_APIC
-
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
@@ -729,11 +628,9 @@ static struct mp_ioapic_routing {
u32 pin_programmed[4];
} mp_ioapic_routing[MAX_IO_APICS];
-
-static int mp_find_ioapic (
- int gsi)
+static int mp_find_ioapic(int gsi)
{
- int i = 0;
+ int i = 0;
/* Find the IOAPIC that manages this GSI. */
for (i = 0; i < nr_ioapics; i++) {
@@ -743,17 +640,12 @@ static int mp_find_ioapic (
}
printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
-
return -1;
}
-
-void __init mp_register_ioapic (
- u8 id,
- u32 address,
- u32 gsi_base)
+void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
{
- int idx = 0;
+ int idx = 0;
if (nr_ioapics >= MAX_IO_APICS) {
printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
@@ -774,7 +666,7 @@ void __init mp_register_ioapic (
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
mp_ioapics[idx].mpc_apicid = id;
- mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+ mp_ioapics[idx].mpc_apicver = 0;
/*
* Build basic IRQ lookup table to facilitate gsi->io_apic lookups
@@ -785,21 +677,15 @@ void __init mp_register_ioapic (
mp_ioapic_routing[idx].gsi_end = gsi_base +
io_apic_get_redir_entries(idx);
- printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+ printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
- mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+ mp_ioapics[idx].mpc_apicaddr,
mp_ioapic_routing[idx].gsi_start,
mp_ioapic_routing[idx].gsi_end);
-
- return;
}
-
-void __init mp_override_legacy_irq (
- u8 bus_irq,
- u8 polarity,
- u8 trigger,
- u32 gsi)
+void __init
+mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
{
struct mpc_config_intsrc intsrc;
int ioapic = -1;
@@ -837,22 +723,18 @@ void __init mp_override_legacy_irq (
mp_irqs[mp_irq_entries] = intsrc;
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!\n");
-
- return;
}
-
-void __init mp_config_acpi_legacy_irqs (void)
+void __init mp_config_acpi_legacy_irqs(void)
{
struct mpc_config_intsrc intsrc;
- int i = 0;
- int ioapic = -1;
+ int i = 0;
+ int ioapic = -1;
/*
* Fabricate the legacy ISA bus (bus #31).
*/
- mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
- Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+ set_bit(MP_ISA_BUS, mp_bus_not_pci);
/*
* Locate the IOAPIC that manages the ISA IRQs (0-15).
@@ -905,24 +787,22 @@ void __init mp_config_acpi_legacy_irqs (void)
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!\n");
}
-
- return;
}
#define MAX_GSI_NUM 4096
int mp_register_gsi(u32 gsi, int triggering, int polarity)
{
- int ioapic = -1;
- int ioapic_pin = 0;
- int idx, bit = 0;
- static int pci_irq = 16;
+ int ioapic = -1;
+ int ioapic_pin = 0;
+ int idx, bit = 0;
+ static int pci_irq = 16;
/*
* Mapping between Global System Interrupts, which
* represent all possible interrupts, to the IRQs
* assigned to actual devices.
*/
- static int gsi_to_irq[MAX_GSI_NUM];
+ static int gsi_to_irq[MAX_GSI_NUM];
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -996,6 +876,4 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
return gsi;
}
-
-#endif /*CONFIG_X86_IO_APIC*/
#endif /*CONFIG_ACPI*/
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 5baa0c726e9..4d6fb047952 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -28,71 +28,138 @@
#include <asm/mce.h>
#include <asm/intel_arch_perfmon.h>
-/*
- * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
- * - it may be reserved by some other driver, or not
- * - when not reserved by some other driver, it may be used for
- * the NMI watchdog, or not
- *
- * This is maintained separately from nmi_active because the NMI
- * watchdog may also be driven from the I/O APIC timer.
+/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
+ * evtsel_nmi_owner tracks the ownership of the event selection
+ * - different performance counters/ event selection may be reserved for
+ * different subsystems this reservation system just tries to coordinate
+ * things a little
*/
-static DEFINE_SPINLOCK(lapic_nmi_owner_lock);
-static unsigned int lapic_nmi_owner;
-#define LAPIC_NMI_WATCHDOG (1<<0)
-#define LAPIC_NMI_RESERVED (1<<1)
+static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner);
+static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[2]);
+
+/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
+ * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now)
+ */
+#define NMI_MAX_COUNTER_BITS 66
/* nmi_active:
- * +1: the lapic NMI watchdog is active, but can be disabled
- * 0: the lapic NMI watchdog has not been set up, and cannot
+ * >0: the lapic NMI watchdog is active, but can be disabled
+ * <0: the lapic NMI watchdog has not been set up, and cannot
* be enabled
- * -1: the lapic NMI watchdog is disabled, but can be enabled
+ * 0: the lapic NMI watchdog is disabled, but can be enabled
*/
-int nmi_active; /* oprofile uses this */
+atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */
int panic_on_timeout;
unsigned int nmi_watchdog = NMI_DEFAULT;
static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
-/* Note that these events don't tick when the CPU idles. This means
- the frequency varies with CPU load. */
+struct nmi_watchdog_ctlblk {
+ int enabled;
+ u64 check_bit;
+ unsigned int cccr_msr;
+ unsigned int perfctr_msr; /* the MSR to reset in NMI handler */
+ unsigned int evntsel_msr; /* the MSR to select the events to handle */
+};
+static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
-#define K7_EVNTSEL_ENABLE (1 << 22)
-#define K7_EVNTSEL_INT (1 << 20)
-#define K7_EVNTSEL_OS (1 << 17)
-#define K7_EVNTSEL_USR (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
-#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+/* local prototypes */
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
-#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+{
+ /* returns the bit offset of the performance counter register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_PERFCTR0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+ else
+ return (msr - MSR_P4_BPU_PERFCTR0);
+ }
+ return 0;
+}
-#define MSR_P4_MISC_ENABLE 0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
-#define MSR_P4_PERFCTR0 0x300
-#define MSR_P4_CCCR0 0x360
-#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
-#define P4_ESCR_OS (1<<3)
-#define P4_ESCR_USR (1<<2)
-#define P4_CCCR_OVF_PMI0 (1<<26)
-#define P4_CCCR_OVF_PMI1 (1<<27)
-#define P4_CCCR_THRESHOLD(N) ((N)<<20)
-#define P4_CCCR_COMPLEMENT (1<<19)
-#define P4_CCCR_COMPARE (1<<18)
-#define P4_CCCR_REQUIRED (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE (1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
- CRU_ESCR0 (with any non-null event selector) through a complemented
- max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0 0x30C
-#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0 \
- (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
- P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+{
+ /* returns the bit offset of the event selection register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_EVNTSEL0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+ else
+ return (msr - MSR_P4_BSU_ESCR0);
+ }
+ return 0;
+}
+
+/* checks for a bit availability (hack for oprofile) */
+int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
+{
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+/* checks the an msr for availability */
+int avail_to_resrv_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+int reserve_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner)))
+ return 1;
+ return 0;
+}
+
+void release_perfctr_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_perfctr_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner));
+}
+
+int reserve_evntsel_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_evntsel_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner)))
+ return 1;
+ return 0;
+}
+
+void release_evntsel_nmi(unsigned int msr)
+{
+ unsigned int counter;
+
+ counter = nmi_evntsel_msr_to_bit(msr);
+ BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+ clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner));
+}
static __cpuinit inline int nmi_known_cpu(void)
{
@@ -109,7 +176,7 @@ static __cpuinit inline int nmi_known_cpu(void)
}
/* Run after command line and cpu_init init, but before all other checks */
-void __cpuinit nmi_watchdog_default(void)
+void nmi_watchdog_default(void)
{
if (nmi_watchdog != NMI_DEFAULT)
return;
@@ -145,6 +212,12 @@ int __init check_nmi_watchdog (void)
int *counts;
int cpu;
+ if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
+ return 0;
+
+ if (!atomic_read(&nmi_active))
+ return 0;
+
counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
if (!counts)
return -1;
@@ -162,26 +235,43 @@ int __init check_nmi_watchdog (void)
mdelay((10*1000)/nmi_hz); // wait 10 ticks
for_each_online_cpu(cpu) {
+ if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+ continue;
if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) {
- endflag = 1;
printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
cpu,
counts[cpu],
cpu_pda(cpu)->__nmi_count);
- nmi_active = 0;
- lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
- nmi_perfctr_msr = 0;
- kfree(counts);
- return -1;
+ per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+ atomic_dec(&nmi_active);
}
}
+ if (!atomic_read(&nmi_active)) {
+ kfree(counts);
+ atomic_set(&nmi_active, -1);
+ return -1;
+ }
endflag = 1;
printk("OK.\n");
/* now that we know it works we can reduce NMI frequency to
something more reasonable; makes a difference in some configs */
- if (nmi_watchdog == NMI_LOCAL_APIC)
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
nmi_hz = 1;
+ /*
+ * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
+ * are writable, with higher bits sign extending from bit 31.
+ * So, we can only program the counter with 31 bit values and
+ * 32nd bit should be 1, for 33.. to be 1.
+ * Find the appropriate nmi_hz
+ */
+ if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
+ ((u64)cpu_khz * 1000) > 0x7fffffffULL) {
+ nmi_hz = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
+ }
+ }
kfree(counts);
return 0;
@@ -201,91 +291,65 @@ int __init setup_nmi_watchdog(char *str)
get_option(&str, &nmi);
- if (nmi >= NMI_INVALID)
+ if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
return 0;
+
+ if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
+ return 0; /* no lapic support */
nmi_watchdog = nmi;
return 1;
}
__setup("nmi_watchdog=", setup_nmi_watchdog);
-static void disable_intel_arch_watchdog(void);
-
static void disable_lapic_nmi_watchdog(void)
{
- if (nmi_active <= 0)
+ BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+ if (atomic_read(&nmi_active) <= 0)
return;
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
- wrmsr(MSR_K7_EVNTSEL0, 0, 0);
- break;
- case X86_VENDOR_INTEL:
- if (boot_cpu_data.x86 == 15) {
- wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
- wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
- } else if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
- disable_intel_arch_watchdog();
- }
- break;
- }
- nmi_active = -1;
- /* tell do_nmi() and others that we're not active any more */
- nmi_watchdog = 0;
-}
-static void enable_lapic_nmi_watchdog(void)
-{
- if (nmi_active < 0) {
- nmi_watchdog = NMI_LOCAL_APIC;
- touch_nmi_watchdog();
- setup_apic_nmi_watchdog();
- }
+ on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+ BUG_ON(atomic_read(&nmi_active) != 0);
}
-int reserve_lapic_nmi(void)
+static void enable_lapic_nmi_watchdog(void)
{
- unsigned int old_owner;
+ BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
- spin_lock(&lapic_nmi_owner_lock);
- old_owner = lapic_nmi_owner;
- lapic_nmi_owner |= LAPIC_NMI_RESERVED;
- spin_unlock(&lapic_nmi_owner_lock);
- if (old_owner & LAPIC_NMI_RESERVED)
- return -EBUSY;
- if (old_owner & LAPIC_NMI_WATCHDOG)
- disable_lapic_nmi_watchdog();
- return 0;
-}
+ /* are we already enabled */
+ if (atomic_read(&nmi_active) != 0)
+ return;
-void release_lapic_nmi(void)
-{
- unsigned int new_owner;
+ /* are we lapic aware */
+ if (nmi_known_cpu() <= 0)
+ return;
- spin_lock(&lapic_nmi_owner_lock);
- new_owner = lapic_nmi_owner & ~LAPIC_NMI_RESERVED;
- lapic_nmi_owner = new_owner;
- spin_unlock(&lapic_nmi_owner_lock);
- if (new_owner & LAPIC_NMI_WATCHDOG)
- enable_lapic_nmi_watchdog();
+ on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+ touch_nmi_watchdog();
}
void disable_timer_nmi_watchdog(void)
{
- if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+ BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+ if (atomic_read(&nmi_active) <= 0)
return;
disable_irq(0);
- unset_nmi_callback();
- nmi_active = -1;
- nmi_watchdog = NMI_NONE;
+ on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+ BUG_ON(atomic_read(&nmi_active) != 0);
}
void enable_timer_nmi_watchdog(void)
{
- if (nmi_active < 0) {
- nmi_watchdog = NMI_IO_APIC;
+ BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+ if (atomic_read(&nmi_active) == 0) {
touch_nmi_watchdog();
- nmi_active = 1;
+ on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
enable_irq(0);
}
}
@@ -296,15 +360,20 @@ static int nmi_pm_active; /* nmi_active before suspend */
static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
{
- nmi_pm_active = nmi_active;
- disable_lapic_nmi_watchdog();
+ /* only CPU0 goes here, other CPUs should be offline */
+ nmi_pm_active = atomic_read(&nmi_active);
+ stop_apic_nmi_watchdog(NULL);
+ BUG_ON(atomic_read(&nmi_active) != 0);
return 0;
}
static int lapic_nmi_resume(struct sys_device *dev)
{
- if (nmi_pm_active > 0)
- enable_lapic_nmi_watchdog();
+ /* only CPU0 goes here, other CPUs should be offline */
+ if (nmi_pm_active > 0) {
+ setup_apic_nmi_watchdog(NULL);
+ touch_nmi_watchdog();
+ }
return 0;
}
@@ -323,7 +392,13 @@ static int __init init_lapic_nmi_sysfs(void)
{
int error;
- if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)
+ /* should really be a BUG_ON but b/c this is an
+ * init call, it just doesn't work. -dcz
+ */
+ if (nmi_watchdog != NMI_LOCAL_APIC)
+ return 0;
+
+ if ( atomic_read(&nmi_active) < 0 )
return 0;
error = sysdev_class_register(&nmi_sysclass);
@@ -341,74 +416,209 @@ late_initcall(init_lapic_nmi_sysfs);
* Original code written by Keith Owens.
*/
-static void clear_msr_range(unsigned int base, unsigned int n)
-{
- unsigned int i;
+/* Note that these events don't tick when the CPU idles. This means
+ the frequency varies with CPU load. */
- for(i = 0; i < n; ++i)
- wrmsr(base+i, 0, 0);
-}
+#define K7_EVNTSEL_ENABLE (1 << 22)
+#define K7_EVNTSEL_INT (1 << 20)
+#define K7_EVNTSEL_OS (1 << 17)
+#define K7_EVNTSEL_USR (1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
+#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-static void setup_k7_watchdog(void)
+static int setup_k7_watchdog(void)
{
- int i;
+ unsigned int perfctr_msr, evntsel_msr;
unsigned int evntsel;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- nmi_perfctr_msr = MSR_K7_PERFCTR0;
+ perfctr_msr = MSR_K7_PERFCTR0;
+ evntsel_msr = MSR_K7_EVNTSEL0;
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
- for(i = 0; i < 4; ++i) {
- /* Simulator may not support it */
- if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
- nmi_perfctr_msr = 0;
- return;
- }
- wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
- }
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
+
+ /* Simulator may not support it */
+ if (checking_wrmsrl(evntsel_msr, 0UL))
+ goto fail2;
+ wrmsrl(perfctr_msr, 0UL);
evntsel = K7_EVNTSEL_INT
| K7_EVNTSEL_OS
| K7_EVNTSEL_USR
| K7_NMI_EVENT;
- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
+ /* setup the timer */
+ wrmsr(evntsel_msr, evntsel, 0);
+ wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+ wrmsr(evntsel_msr, evntsel, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = 0; //unused
+ wd->check_bit = 1ULL<<63;
+ return 1;
+fail2:
+ release_evntsel_nmi(evntsel_msr);
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
}
-static void disable_intel_arch_watchdog(void)
+static void stop_k7_watchdog(void)
{
- unsigned ebx;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- /*
- * Check whether the Architectural PerfMon supports
- * Unhalted Core Cycles Event or not.
- * NOTE: Corresponding bit = 0 in ebp indicates event present.
+ wrmsr(wd->evntsel_msr, 0, 0);
+
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
+}
+
+/* Note that these events don't tick when the CPU idles. This means
+ the frequency varies with CPU load. */
+
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
+#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
+#define P4_ESCR_OS (1<<3)
+#define P4_ESCR_USR (1<<2)
+#define P4_CCCR_OVF_PMI0 (1<<26)
+#define P4_CCCR_OVF_PMI1 (1<<27)
+#define P4_CCCR_THRESHOLD(N) ((N)<<20)
+#define P4_CCCR_COMPLEMENT (1<<19)
+#define P4_CCCR_COMPARE (1<<18)
+#define P4_CCCR_REQUIRED (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE (1<<12)
+#define P4_CCCR_OVF (1<<31)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+ CRU_ESCR0 (with any non-null event selector) through a complemented
+ max threshold. [IA32-Vol3, Section 14.9.9] */
+
+static int setup_p4_watchdog(void)
+{
+ unsigned int perfctr_msr, evntsel_msr, cccr_msr;
+ unsigned int evntsel, cccr_val;
+ unsigned int misc_enable, dummy;
+ unsigned int ht_num;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
+ if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+ return 0;
+
+#ifdef CONFIG_SMP
+ /* detect which hyperthread we are on */
+ if (smp_num_siblings == 2) {
+ unsigned int ebx, apicid;
+
+ ebx = cpuid_ebx(1);
+ apicid = (ebx >> 24) & 0xff;
+ ht_num = apicid & 1;
+ } else
+#endif
+ ht_num = 0;
+
+ /* performance counters are shared resources
+ * assign each hyperthread its own set
+ * (re-use the ESCR0 register, seems safe
+ * and keeps the cccr_val the same)
*/
- ebx = cpuid_ebx(10);
- if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+ if (!ht_num) {
+ /* logical cpu 0 */
+ perfctr_msr = MSR_P4_IQ_PERFCTR0;
+ evntsel_msr = MSR_P4_CRU_ESCR0;
+ cccr_msr = MSR_P4_IQ_CCCR0;
+ cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
+ } else {
+ /* logical cpu 1 */
+ perfctr_msr = MSR_P4_IQ_PERFCTR1;
+ evntsel_msr = MSR_P4_CRU_ESCR0;
+ cccr_msr = MSR_P4_IQ_CCCR1;
+ cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
+ }
+
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
+
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
+
+ evntsel = P4_ESCR_EVENT_SELECT(0x3F)
+ | P4_ESCR_OS
+ | P4_ESCR_USR;
+
+ cccr_val |= P4_CCCR_THRESHOLD(15)
+ | P4_CCCR_COMPLEMENT
+ | P4_CCCR_COMPARE
+ | P4_CCCR_REQUIRED;
+
+ wrmsr(evntsel_msr, evntsel, 0);
+ wrmsr(cccr_msr, cccr_val, 0);
+ wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ cccr_val |= P4_CCCR_ENABLE;
+ wrmsr(cccr_msr, cccr_val, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = cccr_msr;
+ wd->check_bit = 1ULL<<39;
+ return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
+}
+
+static void stop_p4_watchdog(void)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ wrmsr(wd->cccr_msr, 0, 0);
+ wrmsr(wd->evntsel_msr, 0, 0);
+
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
}
+#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
static int setup_intel_arch_watchdog(void)
{
+ unsigned int ebx;
+ union cpuid10_eax eax;
+ unsigned int unused;
+ unsigned int perfctr_msr, evntsel_msr;
unsigned int evntsel;
- unsigned ebx;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
/*
* Check whether the Architectural PerfMon supports
* Unhalted Core Cycles Event or not.
- * NOTE: Corresponding bit = 0 in ebp indicates event present.
+ * NOTE: Corresponding bit = 0 in ebx indicates event present.
*/
- ebx = cpuid_ebx(10);
- if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
- return 0;
+ cpuid(10, &(eax.full), &ebx, &unused, &unused);
+ if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+ (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+ goto fail;
+
+ perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+ evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
- nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+ if (!reserve_perfctr_nmi(perfctr_msr))
+ goto fail;
- clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
- clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+ if (!reserve_evntsel_nmi(evntsel_msr))
+ goto fail1;
+
+ wrmsrl(perfctr_msr, 0UL);
evntsel = ARCH_PERFMON_EVENTSEL_INT
| ARCH_PERFMON_EVENTSEL_OS
@@ -416,84 +626,122 @@ static int setup_intel_arch_watchdog(void)
| ARCH_PERFMON_NMI_EVENT_SEL
| ARCH_PERFMON_NMI_EVENT_UMASK;
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
- wrmsrl(MSR_ARCH_PERFMON_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
+ /* setup the timer */
+ wrmsr(evntsel_msr, evntsel, 0);
+ wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
- wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+ wrmsr(evntsel_msr, evntsel, 0);
+
+ wd->perfctr_msr = perfctr_msr;
+ wd->evntsel_msr = evntsel_msr;
+ wd->cccr_msr = 0; //unused
+ wd->check_bit = 1ULL << (eax.split.bit_width - 1);
return 1;
+fail1:
+ release_perfctr_nmi(perfctr_msr);
+fail:
+ return 0;
}
-
-static int setup_p4_watchdog(void)
+static void stop_intel_arch_watchdog(void)
{
- unsigned int misc_enable, dummy;
+ unsigned int ebx;
+ union cpuid10_eax eax;
+ unsigned int unused;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
- if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
- return 0;
+ /*
+ * Check whether the Architectural PerfMon supports
+ * Unhalted Core Cycles Event or not.
+ * NOTE: Corresponding bit = 0 in ebx indicates event present.
+ */
+ cpuid(10, &(eax.full), &ebx, &unused, &unused);
+ if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+ (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+ return;
- nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
- nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
-#ifdef CONFIG_SMP
- if (smp_num_siblings == 2)
- nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
-#endif
+ wrmsr(wd->evntsel_msr, 0, 0);
- if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
- clear_msr_range(0x3F1, 2);
- /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
- docs doesn't fully define it, so leave it alone for now. */
- if (boot_cpu_data.x86_model >= 0x3) {
- /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
- clear_msr_range(0x3A0, 26);
- clear_msr_range(0x3BC, 3);
- } else {
- clear_msr_range(0x3A0, 31);
- }
- clear_msr_range(0x3C0, 6);
- clear_msr_range(0x3C8, 6);
- clear_msr_range(0x3E0, 2);
- clear_msr_range(MSR_P4_CCCR0, 18);
- clear_msr_range(MSR_P4_PERFCTR0, 18);
-
- wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz));
- wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz));
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
- return 1;
+ release_evntsel_nmi(wd->evntsel_msr);
+ release_perfctr_nmi(wd->perfctr_msr);
}
-void setup_apic_nmi_watchdog(void)
+void setup_apic_nmi_watchdog(void *unused)
{
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 != 15)
- return;
- if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
- return;
- setup_k7_watchdog();
- break;
- case X86_VENDOR_INTEL:
- if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
- if (!setup_intel_arch_watchdog())
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+ /* only support LOCAL and IO APICs for now */
+ if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+ (nmi_watchdog != NMI_IO_APIC))
+ return;
+
+ if (wd->enabled == 1)
+ return;
+
+ /* cheap hack to support suspend/resume */
+ /* if cpu0 is not active neither should the other cpus */
+ if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
+ return;
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
return;
- } else if (boot_cpu_data.x86 == 15) {
+ if (!setup_k7_watchdog())
+ return;
+ break;
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ if (!setup_intel_arch_watchdog())
+ return;
+ break;
+ }
if (!setup_p4_watchdog())
return;
- } else {
+ break;
+ default:
return;
}
+ }
+ wd->enabled = 1;
+ atomic_inc(&nmi_active);
+}
+
+void stop_apic_nmi_watchdog(void *unused)
+{
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
- break;
+ /* only support LOCAL and IO APICs for now */
+ if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+ (nmi_watchdog != NMI_IO_APIC))
+ return;
- default:
+ if (wd->enabled == 0)
return;
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
+ return;
+ stop_k7_watchdog();
+ break;
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ stop_intel_arch_watchdog();
+ break;
+ }
+ stop_p4_watchdog();
+ break;
+ default:
+ return;
+ }
}
- lapic_nmi_owner = LAPIC_NMI_WATCHDOG;
- nmi_active = 1;
+ wd->enabled = 0;
+ atomic_dec(&nmi_active);
}
/*
@@ -526,93 +774,109 @@ void touch_nmi_watchdog (void)
touch_softlockup_watchdog();
}
-void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
+int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
{
int sum;
int touched = 0;
+ struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+ u64 dummy;
+ int rc=0;
+
+ /* check for other users first */
+ if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+ == NOTIFY_STOP) {
+ rc = 1;
+ touched = 1;
+ }
sum = read_pda(apic_timer_irqs);
if (__get_cpu_var(nmi_touch)) {
__get_cpu_var(nmi_touch) = 0;
touched = 1;
}
+
#ifdef CONFIG_X86_MCE
/* Could check oops_in_progress here too, but it's safer
not too */
if (atomic_read(&mce_entry) > 0)
touched = 1;
#endif
+ /* if the apic timer isn't firing, this cpu isn't doing much */
if (!touched && __get_cpu_var(last_irq_sum) == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
*/
local_inc(&__get_cpu_var(alert_counter));
- if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
- if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
- == NOTIFY_STOP) {
- local_set(&__get_cpu_var(alert_counter), 0);
- return;
- }
- die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
- }
+ if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz)
+ die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs,
+ panic_on_timeout);
} else {
__get_cpu_var(last_irq_sum) = sum;
local_set(&__get_cpu_var(alert_counter), 0);
}
- if (nmi_perfctr_msr) {
- if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
- /*
- * P4 quirks:
- * - An overflown perfctr will assert its interrupt
- * until the OVF flag in its CCCR is cleared.
- * - LVTPC is masked on interrupt and must be
- * unmasked by the LVTPC handler.
- */
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- } else if (nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
- /*
- * For Intel based architectural perfmon
- * - LVTPC is masked on interrupt and must be
- * unmasked by the LVTPC handler.
+
+ /* see if the nmi watchdog went off */
+ if (wd->enabled) {
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ rdmsrl(wd->perfctr_msr, dummy);
+ if (dummy & wd->check_bit){
+ /* this wasn't a watchdog timer interrupt */
+ goto done;
+ }
+
+ /* only Intel uses the cccr msr */
+ if (wd->cccr_msr != 0) {
+ /*
+ * P4 quirks:
+ * - An overflown perfctr will assert its interrupt
+ * until the OVF flag in its CCCR is cleared.
+ * - LVTPC is masked on interrupt and must be
+ * unmasked by the LVTPC handler.
+ */
+ rdmsrl(wd->cccr_msr, dummy);
+ dummy &= ~P4_CCCR_OVF;
+ wrmsrl(wd->cccr_msr, dummy);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ } else if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+ /*
+ * ArchPerfom/Core Duo needs to re-unmask
+ * the apic vector
+ */
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
+ /* start the cycle over again */
+ wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+ rc = 1;
+ } else if (nmi_watchdog == NMI_IO_APIC) {
+ /* don't know how to accurately check for this.
+ * just assume it was a watchdog timer interrupt
+ * This matches the old behaviour.
*/
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- }
- wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+ rc = 1;
+ } else
+ printk(KERN_WARNING "Unknown enabled NMI hardware?!\n");
}
+done:
+ return rc;
}
-static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu)
-{
- return 0;
-}
-
-static nmi_callback_t nmi_callback = dummy_nmi_callback;
-
asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
{
- int cpu = safe_smp_processor_id();
-
nmi_enter();
add_pda(__nmi_count,1);
- if (!rcu_dereference(nmi_callback)(regs, cpu))
- default_do_nmi(regs);
+ default_do_nmi(regs);
nmi_exit();
}
-void set_nmi_callback(nmi_callback_t callback)
+int do_nmi_callback(struct pt_regs * regs, int cpu)
{
- vmalloc_sync_all();
- rcu_assign_pointer(nmi_callback, callback);
-}
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-
-void unset_nmi_callback(void)
-{
- nmi_callback = dummy_nmi_callback;
+#ifdef CONFIG_SYSCTL
+ if (unknown_nmi_panic)
+ return unknown_nmi_panic_callback(regs, cpu);
+#endif
+ return 0;
}
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
#ifdef CONFIG_SYSCTL
@@ -621,36 +885,42 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
unsigned char reason = get_nmi_reason();
char buf[64];
- if (!(reason & 0xc0)) {
- sprintf(buf, "NMI received for unknown reason %02x\n", reason);
- die_nmi(buf,regs);
- }
+ sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+ die_nmi(buf, regs, 1); /* Always panic here */
return 0;
}
/*
- * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ * proc handler for /proc/sys/kernel/nmi
*/
-int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file,
+int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
void __user *buffer, size_t *length, loff_t *ppos)
{
int old_state;
- old_state = unknown_nmi_panic;
+ nmi_watchdog_enabled = (atomic_read(&nmi_active) > 0) ? 1 : 0;
+ old_state = nmi_watchdog_enabled;
proc_dointvec(table, write, file, buffer, length, ppos);
- if (!!old_state == !!unknown_nmi_panic)
+ if (!!old_state == !!nmi_watchdog_enabled)
return 0;
- if (unknown_nmi_panic) {
- if (reserve_lapic_nmi() < 0) {
- unknown_nmi_panic = 0;
- return -EBUSY;
- } else {
- set_nmi_callback(unknown_nmi_panic_callback);
- }
+ if (atomic_read(&nmi_active) < 0) {
+ printk( KERN_WARNING "NMI watchdog is permanently disabled\n");
+ return -EIO;
+ }
+
+ /* if nmi_watchdog is not set yet, then set it */
+ nmi_watchdog_default();
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ if (nmi_watchdog_enabled)
+ enable_lapic_nmi_watchdog();
+ else
+ disable_lapic_nmi_watchdog();
} else {
- release_lapic_nmi();
- unset_nmi_callback();
+ printk( KERN_WARNING
+ "NMI watchdog doesn't know what hardware to touch\n");
+ return -EIO;
}
return 0;
}
@@ -659,8 +929,12 @@ int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file
EXPORT_SYMBOL(nmi_active);
EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(reserve_lapic_nmi);
-EXPORT_SYMBOL(release_lapic_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
+EXPORT_SYMBOL(reserve_perfctr_nmi);
+EXPORT_SYMBOL(release_perfctr_nmi);
+EXPORT_SYMBOL(reserve_evntsel_nmi);
+EXPORT_SYMBOL(release_evntsel_nmi);
EXPORT_SYMBOL(disable_timer_nmi_watchdog);
EXPORT_SYMBOL(enable_timer_nmi_watchdog);
EXPORT_SYMBOL(touch_nmi_watchdog);
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 146924ba5df..cfb09b07ae9 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -86,7 +86,8 @@
#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
#define MAX_NUM_CHASSIS 8 /* max number of chassis */
-#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
+/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
+#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
#define PHBS_PER_CALGARY 4
/* register offsets in Calgary's internal register space */
@@ -111,31 +112,49 @@ static const unsigned long phb_offsets[] = {
0xB000 /* PHB3 */
};
-static char bus_to_phb[MAX_PHB_BUS_NUM];
-void* tce_table_kva[MAX_PHB_BUS_NUM];
unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
static int translate_empty_slots __read_mostly = 0;
static int calgary_detected __read_mostly = 0;
-/*
- * the bitmap of PHBs the user requested that we disable
- * translation on.
- */
-static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
+struct calgary_bus_info {
+ void *tce_space;
+ unsigned char translation_disabled;
+ signed char phbid;
+};
+
+static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
static void tce_cache_blast(struct iommu_table *tbl);
/* enable this to stress test the chip's TCE cache */
#ifdef CONFIG_IOMMU_DEBUG
-static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+int debugging __read_mostly = 1;
+
+static inline unsigned long verify_bit_range(unsigned long* bitmap,
+ int expected, unsigned long start, unsigned long end)
{
- tce_cache_blast(tbl);
+ unsigned long idx = start;
+
+ BUG_ON(start >= end);
+
+ while (idx < end) {
+ if (!!test_bit(idx, bitmap) != expected)
+ return idx;
+ ++idx;
+ }
+
+ /* all bits have the expected value */
+ return ~0UL;
}
-#else
-static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+#else /* debugging is disabled */
+int debugging __read_mostly = 0;
+
+static inline unsigned long verify_bit_range(unsigned long* bitmap,
+ int expected, unsigned long start, unsigned long end)
{
+ return ~0UL;
}
-#endif /* BLAST_TCE_CACHE_ON_UNMAP */
+#endif /* CONFIG_IOMMU_DEBUG */
static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
{
@@ -149,7 +168,7 @@ static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
static inline int translate_phb(struct pci_dev* dev)
{
- int disabled = test_bit(dev->bus->number, translation_disabled);
+ int disabled = bus_info[dev->bus->number].translation_disabled;
return !disabled;
}
@@ -158,6 +177,7 @@ static void iommu_range_reserve(struct iommu_table *tbl,
{
unsigned long index;
unsigned long end;
+ unsigned long badbit;
index = start_addr >> PAGE_SHIFT;
@@ -169,14 +189,15 @@ static void iommu_range_reserve(struct iommu_table *tbl,
if (end > tbl->it_size) /* don't go off the table */
end = tbl->it_size;
- while (index < end) {
- if (test_bit(index, tbl->it_map))
+ badbit = verify_bit_range(tbl->it_map, 0, index, end);
+ if (badbit != ~0UL) {
+ if (printk_ratelimit())
printk(KERN_ERR "Calgary: entry already allocated at "
"0x%lx tbl %p dma 0x%lx npages %u\n",
- index, tbl, start_addr, npages);
- ++index;
+ badbit, tbl, start_addr, npages);
}
- set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages);
+
+ set_bit_string(tbl->it_map, index, npages);
}
static unsigned long iommu_range_alloc(struct iommu_table *tbl,
@@ -243,7 +264,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry;
- unsigned long i;
+ unsigned long badbit;
entry = dma_addr >> PAGE_SHIFT;
@@ -251,16 +272,15 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
tce_free(tbl, entry, npages);
- for (i = 0; i < npages; ++i) {
- if (!test_bit(entry + i, tbl->it_map))
+ badbit = verify_bit_range(tbl->it_map, 1, entry, entry + npages);
+ if (badbit != ~0UL) {
+ if (printk_ratelimit())
printk(KERN_ERR "Calgary: bit is off at 0x%lx "
"tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
- entry + i, tbl, dma_addr, entry, npages);
+ badbit, tbl, dma_addr, entry, npages);
}
__clear_bit_string(tbl->it_map, entry, npages);
-
- tce_cache_blast_stress(tbl);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -454,7 +474,7 @@ static struct dma_mapping_ops calgary_dma_ops = {
static inline int busno_to_phbid(unsigned char num)
{
- return bus_to_phb[num];
+ return bus_info[num].phbid;
}
static inline unsigned long split_queue_offset(unsigned char num)
@@ -631,6 +651,10 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
if (ret)
return ret;
+ tbl = dev->sysdata;
+ tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space;
+ tce_free(tbl, 0, tbl->it_size);
+
calgary_reserve_regions(dev);
/* set TARs for each PHB */
@@ -654,11 +678,12 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
return 0;
}
-static void __init calgary_free_tar(struct pci_dev *dev)
+static void __init calgary_free_bus(struct pci_dev *dev)
{
u64 val64;
struct iommu_table *tbl = dev->sysdata;
void __iomem *target;
+ unsigned int bitmapsz;
target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number));
val64 = be64_to_cpu(readq(target));
@@ -666,8 +691,15 @@ static void __init calgary_free_tar(struct pci_dev *dev)
writeq(cpu_to_be64(val64), target);
readq(target); /* flush */
+ bitmapsz = tbl->it_size / BITS_PER_BYTE;
+ free_pages((unsigned long)tbl->it_map, get_order(bitmapsz));
+ tbl->it_map = NULL;
+
kfree(tbl);
dev->sysdata = NULL;
+
+ /* Can't free bootmem allocated memory after system is up :-( */
+ bus_info[dev->bus->number].tce_space = NULL;
}
static void calgary_watchdog(unsigned long data)
@@ -772,12 +804,11 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
return address;
}
-static int __init calgary_init_one_nontraslated(struct pci_dev *dev)
+static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
{
+ pci_dev_get(dev);
dev->sysdata = NULL;
dev->bus->self = dev;
-
- return 0;
}
static int __init calgary_init_one(struct pci_dev *dev)
@@ -798,6 +829,7 @@ static int __init calgary_init_one(struct pci_dev *dev)
if (ret)
goto iounmap;
+ pci_dev_get(dev);
dev->bus->self = dev;
calgary_enable_translation(dev);
@@ -824,10 +856,9 @@ static int __init calgary_init(void)
calgary_init_one_nontraslated(dev);
continue;
}
- if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
- pci_dev_put(dev);
+ if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
continue;
- }
+
ret = calgary_init_one(dev);
if (ret)
goto error;
@@ -840,15 +871,18 @@ error:
dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
PCI_DEVICE_ID_IBM_CALGARY,
dev);
+ if (!dev)
+ break;
if (!translate_phb(dev)) {
pci_dev_put(dev);
continue;
}
- if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
+ if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
continue;
+
calgary_disable_translation(dev);
- calgary_free_tar(dev);
- pci_dev_put(dev);
+ calgary_free_bus(dev);
+ pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
}
return ret;
@@ -890,13 +924,15 @@ void __init detect_calgary(void)
if (swiotlb || no_iommu || iommu_detected)
return;
+ if (!early_pci_allowed())
+ return;
+
specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
int dev;
-
- tce_table_kva[bus] = NULL;
- bus_to_phb[bus] = -1;
+ struct calgary_bus_info *info = &bus_info[bus];
+ info->phbid = -1;
if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
continue;
@@ -907,12 +943,9 @@ void __init detect_calgary(void)
*/
phb = (phb + 1) % PHBS_PER_CALGARY;
- if (test_bit(bus, translation_disabled)) {
- printk(KERN_INFO "Calgary: translation is disabled for "
- "PHB 0x%x\n", bus);
- /* skip this phb, don't allocate a tbl for it */
+ if (info->translation_disabled)
continue;
- }
+
/*
* Scan the slots of the PCI bus to see if there is a device present.
* The parent bus will be the zero-ith device, so start at 1.
@@ -923,8 +956,8 @@ void __init detect_calgary(void)
tbl = alloc_tce_table();
if (!tbl)
goto cleanup;
- tce_table_kva[bus] = tbl;
- bus_to_phb[bus] = phb;
+ info->tce_space = tbl;
+ info->phbid = phb;
calgary_found = 1;
break;
}
@@ -934,15 +967,20 @@ void __init detect_calgary(void)
if (calgary_found) {
iommu_detected = 1;
calgary_detected = 1;
- printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
- "TCE table spec is %d.\n", specified_table_size);
+ printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected.\n");
+ printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
+ "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
+ debugging ? "enabled" : "disabled");
}
return;
cleanup:
- for (--bus; bus >= 0; --bus)
- if (tce_table_kva[bus])
- free_tce_table(tce_table_kva[bus]);
+ for (--bus; bus >= 0; --bus) {
+ struct calgary_bus_info *info = &bus_info[bus];
+
+ if (info->tce_space)
+ free_tce_table(info->tce_space);
+ }
}
int __init calgary_iommu_init(void)
@@ -1016,7 +1054,7 @@ static int __init calgary_parse_options(char *p)
if (bridge < MAX_PHB_BUS_NUM) {
printk(KERN_INFO "Calgary: disabling "
"translation for PHB 0x%x\n", bridge);
- set_bit(bridge, translation_disabled);
+ bus_info[bridge].translation_disabled = 1;
}
}
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 9c44f4f2433..4dcb671bd19 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -236,6 +236,9 @@ __init int iommu_setup(char *p)
{
iommu_merge = 1;
+ if (!p)
+ return -EINVAL;
+
while (*p) {
if (!strncmp(p,"off",3))
no_iommu = 1;
@@ -278,9 +281,9 @@ __init int iommu_setup(char *p)
if (*p == ',')
++p;
}
- return 1;
+ return 0;
}
-__setup("iommu=", iommu_setup);
+early_param("iommu", iommu_setup);
void __init pci_iommu_alloc(void)
{
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 6d3e61baf7a..16261a8a330 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -239,8 +239,6 @@ dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, int dir)
{
unsigned long phys_mem, bus;
- BUG_ON(dir == DMA_NONE);
-
if (!dev)
dev = &fallback_dev;
@@ -383,7 +381,6 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
unsigned long pages = 0;
int need = 0, nextneed;
- BUG_ON(dir == DMA_NONE);
if (nents == 0)
return 0;
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index aad7609d8e9..df09ab05a1b 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -59,7 +59,6 @@ int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
{
int i;
- BUG_ON(direction == DMA_NONE);
for (i = 0; i < nents; i++ ) {
struct scatterlist *s = &sg[i];
BUG_ON(!s->page);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index bb6745d13b8..458006ae19f 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -80,25 +80,25 @@ void idle_notifier_unregister(struct notifier_block *n)
}
EXPORT_SYMBOL(idle_notifier_unregister);
-enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
-static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
-
void enter_idle(void)
{
- __get_cpu_var(idle_state) = CPU_IDLE;
+ write_pda(isidle, 1);
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
static void __exit_idle(void)
{
- __get_cpu_var(idle_state) = CPU_NOT_IDLE;
+ if (read_pda(isidle) == 0)
+ return;
+ write_pda(isidle, 0);
atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
}
/* Called from interrupts to signify idle end */
void exit_idle(void)
{
- if (current->pid | read_pda(irqcount))
+ /* idle loop has pid 0 */
+ if (current->pid)
return;
__exit_idle();
}
@@ -220,6 +220,9 @@ void cpu_idle (void)
play_dead();
enter_idle();
idle();
+ /* In many cases the interrupt that ended idle
+ has already called exit_idle. But some idle
+ loops can be woken up without interrupt. */
__exit_idle();
}
@@ -350,6 +353,7 @@ void exit_thread(void)
kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL;
+ clear_thread_flag(TIF_IO_BITMAP);
/*
* Careful, clear this in the TSS too:
*/
@@ -369,6 +373,7 @@ void flush_thread(void)
if (t->flags & _TIF_IA32)
current_thread_info()->status |= TS_COMPAT;
}
+ t->flags &= ~_TIF_DEBUG;
tsk->thread.debugreg0 = 0;
tsk->thread.debugreg1 = 0;
@@ -461,7 +466,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
asm("mov %%es,%0" : "=m" (p->thread.es));
asm("mov %%ds,%0" : "=m" (p->thread.ds));
- if (unlikely(me->thread.io_bitmap_ptr != NULL)) {
+ if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!p->thread.io_bitmap_ptr) {
p->thread.io_bitmap_max = 0;
@@ -469,6 +474,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
}
memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
IO_BITMAP_BYTES);
+ set_tsk_thread_flag(p, TIF_IO_BITMAP);
}
/*
@@ -498,6 +504,40 @@ out:
*/
#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
+static inline void __switch_to_xtra(struct task_struct *prev_p,
+ struct task_struct *next_p,
+ struct tss_struct *tss)
+{
+ struct thread_struct *prev, *next;
+
+ prev = &prev_p->thread,
+ next = &next_p->thread;
+
+ if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ loaddebug(next, 0);
+ loaddebug(next, 1);
+ loaddebug(next, 2);
+ loaddebug(next, 3);
+ /* no 4 and 5 */
+ loaddebug(next, 6);
+ loaddebug(next, 7);
+ }
+
+ if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+ /*
+ * Copy the relevant range of the IO bitmap.
+ * Normally this is 128 bytes or less:
+ */
+ memcpy(tss->io_bitmap, next->io_bitmap_ptr,
+ max(prev->io_bitmap_max, next->io_bitmap_max));
+ } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
+ /*
+ * Clear any possible leftover bits:
+ */
+ memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
+ }
+}
+
/*
* switch_to(x,y) should switch tasks from x to y.
*
@@ -515,6 +555,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ /* we're going to use this soon, after a few expensive things */
+ if (next_p->fpu_counter>5)
+ prefetch(&next->i387.fxsave);
+
/*
* Reload esp0, LDT and the page table pointer:
*/
@@ -583,41 +627,29 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
And the AMD workaround requires it to be after DS reload. */
unlazy_fpu(prev_p);
write_pda(kernelstack,
- task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
-
+ (unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
+#ifdef CONFIG_CC_STACKPROTECTOR
+ write_pda(stack_canary, next_p->stack_canary);
/*
- * Now maybe reload the debug registers
+ * Build time only check to make sure the stack_canary is at
+ * offset 40 in the pda; this is a gcc ABI requirement
*/
- if (unlikely(next->debugreg7)) {
- loaddebug(next, 0);
- loaddebug(next, 1);
- loaddebug(next, 2);
- loaddebug(next, 3);
- /* no 4 and 5 */
- loaddebug(next, 6);
- loaddebug(next, 7);
- }
-
+ BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40);
+#endif
- /*
- * Handle the IO bitmap
- */
- if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
- if (next->io_bitmap_ptr)
- /*
- * Copy the relevant range of the IO bitmap.
- * Normally this is 128 bytes or less:
- */
- memcpy(tss->io_bitmap, next->io_bitmap_ptr,
- max(prev->io_bitmap_max, next->io_bitmap_max));
- else {
- /*
- * Clear any possible leftover bits:
- */
- memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
- }
- }
+ /*
+ * Now maybe reload the debug registers and handle I/O bitmaps
+ */
+ if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
+ || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+ __switch_to_xtra(prev_p, next_p, tss);
+ /* If the task has used fpu the last 5 timeslices, just do a full
+ * restore of the math state immediately to avoid the trap; the
+ * chances of needing FPU soon are obviously high now
+ */
+ if (next_p->fpu_counter>5)
+ math_state_restore();
return prev_p;
}
@@ -834,7 +866,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
unsigned long arch_align_stack(unsigned long sp)
{
- if (randomize_va_space)
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 2d50024c9f3..addc14af0c5 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -116,17 +116,17 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
return addr;
}
-static int is_at_popf(struct task_struct *child, struct pt_regs *regs)
+static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
{
int i, copied;
- unsigned char opcode[16];
+ unsigned char opcode[15];
unsigned long addr = convert_rip_to_linear(child, regs);
copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
for (i = 0; i < copied; i++) {
switch (opcode[i]) {
- /* popf */
- case 0x9d:
+ /* popf and iret */
+ case 0x9d: case 0xcf:
return 1;
/* CHECKME: 64 65 */
@@ -138,14 +138,17 @@ static int is_at_popf(struct task_struct *child, struct pt_regs *regs)
case 0x26: case 0x2e:
case 0x36: case 0x3e:
case 0x64: case 0x65:
- case 0xf0: case 0xf2: case 0xf3:
+ case 0xf2: case 0xf3:
continue;
- /* REX prefixes */
case 0x40 ... 0x4f:
+ if (regs->cs != __USER_CS)
+ /* 32-bit mode: register increment */
+ return 0;
+ /* 64-bit mode: REX prefix */
continue;
- /* CHECKME: f0, f2, f3 */
+ /* CHECKME: f2, f3 */
/*
* pushf: NOTE! We should probably not let
@@ -186,10 +189,8 @@ static void set_singlestep(struct task_struct *child)
* ..but if TF is changed by the instruction we will trace,
* don't mark it as being "us" that set it, so that we
* won't clear it by hand later.
- *
- * AK: this is not enough, LAHF and IRET can change TF in user space too.
*/
- if (is_at_popf(child, regs))
+ if (is_setting_trap_flag(child, regs))
return;
child->ptrace |= PT_DTRACE;
@@ -420,9 +421,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
break;
if (i == 4) {
- child->thread.debugreg7 = data;
+ child->thread.debugreg7 = data;
+ if (data)
+ set_tsk_thread_flag(child, TIF_DEBUG);
+ else
+ clear_tsk_thread_flag(child, TIF_DEBUG);
ret = 0;
- }
+ }
break;
}
break;
diff --git a/arch/x86_64/kernel/relocate_kernel.S b/arch/x86_64/kernel/relocate_kernel.S
index d24fa9b72a2..14e95872c6a 100644
--- a/arch/x86_64/kernel/relocate_kernel.S
+++ b/arch/x86_64/kernel/relocate_kernel.S
@@ -7,31 +7,169 @@
*/
#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/kexec.h>
- /*
- * Must be relocatable PIC code callable as a C function, that once
- * it starts can not use the previous processes stack.
- */
- .globl relocate_new_kernel
+/*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+#define PTR(x) (x << 3)
+#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+
+ .text
+ .align PAGE_ALIGNED
.code64
+ .globl relocate_kernel
+relocate_kernel:
+ /* %rdi indirection_page
+ * %rsi page_list
+ * %rdx start address
+ */
+
+ /* map the control page at its virtual address */
+
+ movq $0x0000ff8000000000, %r10 /* mask */
+ mov $(39 - 3), %cl /* bits to shift */
+ movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PGD)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PUD_0)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PUD_0)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PMD_0)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PMD_0)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PTE_0)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PTE_0)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ /* identity map the control page at its physical address */
+
+ movq $0x0000ff8000000000, %r10 /* mask */
+ mov $(39 - 3), %cl /* bits to shift */
+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PGD)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PUD_1)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PUD_1)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PMD_1)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PMD_1)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_PTE_1)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
+ shrq $9, %r10
+ sub $9, %cl
+
+ movq %r11, %r9
+ andq %r10, %r9
+ shrq %cl, %r9
+
+ movq PTR(VA_PTE_1)(%rsi), %r8
+ addq %r8, %r9
+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
+ orq $PAGE_ATTR, %r8
+ movq %r8, (%r9)
+
relocate_new_kernel:
- /* %rdi page_list
- * %rsi reboot_code_buffer
+ /* %rdi indirection_page
+ * %rsi page_list
* %rdx start address
- * %rcx page_table
- * %r8 arg5
- * %r9 arg6
*/
/* zero out flags, and disable interrupts */
pushq $0
popfq
- /* set a new stack at the bottom of our page... */
- lea 4096(%rsi), %rsp
+ /* get physical address of control page now */
+ /* this is impossible after page table switch */
+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
+
+ /* get physical address of page table now too */
+ movq PTR(PA_TABLE_PAGE)(%rsi), %rcx
- /* store the parameters back on the stack */
- pushq %rdx /* store the start address */
+ /* switch to new set of page tables */
+ movq PTR(PA_PGD)(%rsi), %r9
+ movq %r9, %cr3
+
+ /* setup a new stack at the end of the physical control page */
+ lea 4096(%r8), %rsp
+
+ /* jump to identity mapped page */
+ addq $(identity_mapped - relocate_kernel), %r8
+ pushq %r8
+ ret
+
+identity_mapped:
+ /* store the start address on the stack */
+ pushq %rdx
/* Set cr0 to a known state:
* 31 1 == Paging enabled
@@ -136,8 +274,3 @@ relocate_new_kernel:
xorq %r15, %r15
ret
-relocate_new_kernel_end:
-
- .globl relocate_new_kernel_size
-relocate_new_kernel_size:
- .quad relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 34afad70482..0b00bb2ea57 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -74,16 +74,6 @@ EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
-int acpi_disabled;
-EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI
-extern int __initdata acpi_ht;
-extern acpi_interrupt_flags acpi_sci_flags;
-int __initdata acpi_force = 0;
-#endif
-
-int acpi_numa __initdata;
-
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;
@@ -107,7 +97,6 @@ struct sys_desc_table_struct {
struct edid_info edid_info;
EXPORT_SYMBOL_GPL(edid_info);
-struct e820map e820;
extern int root_mountflags;
@@ -276,185 +265,22 @@ static void __init probe_roms(void)
}
}
-/* Check for full argument with no trailing characters */
-static int fullarg(char *p, char *arg)
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel. This option will be passed
+ * by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
{
- int l = strlen(arg);
- return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
+ char *end;
+ if (!arg)
+ return -EINVAL;
+ elfcorehdr_addr = memparse(arg, &end);
+ return end > arg ? 0 : -EINVAL;
}
-
-static __init void parse_cmdline_early (char ** cmdline_p)
-{
- char c = ' ', *to = command_line, *from = COMMAND_LINE;
- int len = 0;
- int userdef = 0;
-
- for (;;) {
- if (c != ' ')
- goto next_char;
-
-#ifdef CONFIG_SMP
- /*
- * If the BIOS enumerates physical processors before logical,
- * maxcpus=N at enumeration-time can be used to disable HT.
- */
- else if (!memcmp(from, "maxcpus=", 8)) {
- extern unsigned int maxcpus;
-
- maxcpus = simple_strtoul(from + 8, NULL, 0);
- }
-#endif
-#ifdef CONFIG_ACPI
- /* "acpi=off" disables both ACPI table parsing and interpreter init */
- if (fullarg(from,"acpi=off"))
- disable_acpi();
-
- if (fullarg(from, "acpi=force")) {
- /* add later when we do DMI horrors: */
- acpi_force = 1;
- acpi_disabled = 0;
- }
-
- /* acpi=ht just means: do ACPI MADT parsing
- at bootup, but don't enable the full ACPI interpreter */
- if (fullarg(from, "acpi=ht")) {
- if (!acpi_force)
- disable_acpi();
- acpi_ht = 1;
- }
- else if (fullarg(from, "pci=noacpi"))
- acpi_disable_pci();
- else if (fullarg(from, "acpi=noirq"))
- acpi_noirq_set();
-
- else if (fullarg(from, "acpi_sci=edge"))
- acpi_sci_flags.trigger = 1;
- else if (fullarg(from, "acpi_sci=level"))
- acpi_sci_flags.trigger = 3;
- else if (fullarg(from, "acpi_sci=high"))
- acpi_sci_flags.polarity = 1;
- else if (fullarg(from, "acpi_sci=low"))
- acpi_sci_flags.polarity = 3;
-
- /* acpi=strict disables out-of-spec workarounds */
- else if (fullarg(from, "acpi=strict")) {
- acpi_strict = 1;
- }
-#ifdef CONFIG_X86_IO_APIC
- else if (fullarg(from, "acpi_skip_timer_override"))
- acpi_skip_timer_override = 1;
-#endif
-#endif
-
- if (fullarg(from, "disable_timer_pin_1"))
- disable_timer_pin_1 = 1;
- if (fullarg(from, "enable_timer_pin_1"))
- disable_timer_pin_1 = -1;
-
- if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
- clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
- disable_apic = 1;
- }
-
- if (fullarg(from, "noapic"))
- skip_ioapic_setup = 1;
-
- if (fullarg(from,"apic")) {
- skip_ioapic_setup = 0;
- ioapic_force = 1;
- }
-
- if (!memcmp(from, "mem=", 4))
- parse_memopt(from+4, &from);
-
- if (!memcmp(from, "memmap=", 7)) {
- /* exactmap option is for used defined memory */
- if (!memcmp(from+7, "exactmap", 8)) {
-#ifdef CONFIG_CRASH_DUMP
- /* If we are doing a crash dump, we
- * still need to know the real mem
- * size before original memory map is
- * reset.
- */
- saved_max_pfn = e820_end_of_ram();
-#endif
- from += 8+7;
- end_pfn_map = 0;
- e820.nr_map = 0;
- userdef = 1;
- }
- else {
- parse_memmapopt(from+7, &from);
- userdef = 1;
- }
- }
-
-#ifdef CONFIG_NUMA
- if (!memcmp(from, "numa=", 5))
- numa_setup(from+5);
+early_param("elfcorehdr", setup_elfcorehdr);
#endif
- if (!memcmp(from,"iommu=",6)) {
- iommu_setup(from+6);
- }
-
- if (fullarg(from,"oops=panic"))
- panic_on_oops = 1;
-
- if (!memcmp(from, "noexec=", 7))
- nonx_setup(from + 7);
-
-#ifdef CONFIG_KEXEC
- /* crashkernel=size@addr specifies the location to reserve for
- * a crash kernel. By reserving this memory we guarantee
- * that linux never set's it up as a DMA target.
- * Useful for holding code to do something appropriate
- * after a kernel panic.
- */
- else if (!memcmp(from, "crashkernel=", 12)) {
- unsigned long size, base;
- size = memparse(from+12, &from);
- if (*from == '@') {
- base = memparse(from+1, &from);
- /* FIXME: Do I want a sanity check
- * to validate the memory range?
- */
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- }
-#endif
-
-#ifdef CONFIG_PROC_VMCORE
- /* elfcorehdr= specifies the location of elf core header
- * stored by the crashed kernel. This option will be passed
- * by kexec loader to the capture kernel.
- */
- else if(!memcmp(from, "elfcorehdr=", 11))
- elfcorehdr_addr = memparse(from+11, &from);
-#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
- else if (!memcmp(from, "additional_cpus=", 16))
- setup_additional_cpus(from+16);
-#endif
-
- next_char:
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- if (userdef) {
- printk(KERN_INFO "user-defined physical RAM map:\n");
- e820_print_map("user");
- }
- *to = '\0';
- *cmdline_p = command_line;
-}
-
#ifndef CONFIG_NUMA
static void __init
contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
@@ -466,7 +292,8 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
if (bootmap == -1L)
panic("Cannot find bootmem map of size %ld\n",bootmap_size);
bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
- e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+ e820_register_active_regions(0, start_pfn, end_pfn);
+ free_bootmem_with_active_regions(0, end_pfn);
reserve_bootmem(bootmap, bootmap_size);
}
#endif
@@ -521,6 +348,8 @@ static void discover_ebda(void)
void __init setup_arch(char **cmdline_p)
{
+ printk(KERN_INFO "Command line: %s\n", saved_command_line);
+
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
@@ -547,16 +376,22 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_phys(&_etext);
data_resource.end = virt_to_phys(&_edata)-1;
- parse_cmdline_early(cmdline_p);
-
early_identify_cpu(&boot_cpu_data);
+ strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+
+ parse_early_param();
+
+ finish_e820_parsing();
+
+ e820_register_active_regions(0, 0, -1UL);
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
- num_physpages = end_pfn; /* for pfn_valid */
+ num_physpages = end_pfn;
check_efer();
@@ -576,6 +411,14 @@ void __init setup_arch(char **cmdline_p)
acpi_boot_table_init();
#endif
+ /* How many end-of-memory variables you have, grandma! */
+ max_low_pfn = end_pfn;
+ max_pfn = end_pfn;
+ high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
+
+ /* Remove active ranges so rediscovery with NUMA-awareness happens */
+ remove_all_active_ranges();
+
#ifdef CONFIG_ACPI_NUMA
/*
* Parse SRAT to discover nodes.
@@ -625,12 +468,10 @@ void __init setup_arch(char **cmdline_p)
*/
acpi_reserve_bootmem();
#endif
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* Find and reserve possible boot-time SMP configuration:
*/
find_smp_config();
-#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
@@ -657,7 +498,9 @@ void __init setup_arch(char **cmdline_p)
paging_init();
- check_ioapic();
+#ifdef CONFIG_PCI
+ early_quirks();
+#endif
/*
* set this early, so we dont allocate cpu0
@@ -674,14 +517,12 @@ void __init setup_arch(char **cmdline_p)
init_cpu_to_node();
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* get boot-time SMP configuration:
*/
if (smp_found_config)
get_smp_config();
init_apic_mappings();
-#endif
/*
* Request address space for all standard RAM and ROM resources
@@ -689,6 +530,7 @@ void __init setup_arch(char **cmdline_p)
*/
probe_roms();
e820_reserve_resources();
+ e820_mark_nosave_regions();
request_resource(&iomem_resource, &video_ram_resource);
@@ -838,7 +680,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
#endif
}
-static void __init init_amd(struct cpuinfo_x86 *c)
+static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
unsigned level;
@@ -894,6 +736,12 @@ static void __init init_amd(struct cpuinfo_x86 *c)
/* Fix cpuid4 emulation for more */
num_cache_leaves = 3;
+
+ /* When there is only one core no need to synchronize RDTSC */
+ if (num_possible_cpus() == 1)
+ set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+ else
+ clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
}
static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -975,8 +823,7 @@ static void srat_detect_node(void)
node = first_node(node_online_map);
numa_set_node(cpu, node);
- if (acpi_numa > 0)
- printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+ printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
#endif
}
@@ -1010,6 +857,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
(c->x86 == 0x6 && c->x86_model >= 0x0e))
set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+ if (c->x86 == 6)
+ set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
c->x86_max_cores = intel_num_cpu_cores(c);
@@ -1228,8 +1077,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Intel-defined (#2) */
"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
- "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+ NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* VIA/Cyrix/Centaur-defined */
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 417de564456..8c4b80fe71a 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -24,7 +24,7 @@
#include <asm/proto.h>
#include <asm/sections.h>
-char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
+char x86_boot_params[BOOT_PARAM_SIZE] __initdata;
cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
@@ -46,8 +46,10 @@ Control non executable mappings for 64bit processes.
on Enable(default)
off Disable
*/
-int __init nonx_setup(char *str)
+static int __init nonx_setup(char *str)
{
+ if (!str)
+ return -EINVAL;
if (!strncmp(str, "on", 2)) {
__supported_pte_mask |= _PAGE_NX;
do_not_nx = 0;
@@ -55,9 +57,9 @@ int __init nonx_setup(char *str)
do_not_nx = 1;
__supported_pte_mask &= ~_PAGE_NX;
}
- return 1;
+ return 0;
}
-__setup("noexec=", nonx_setup); /* parsed early actually */
+early_param("noexec", nonx_setup);
int force_personality32 = 0;
@@ -93,12 +95,9 @@ void __init setup_per_cpu_areas(void)
#endif
/* Copy section for each CPU (we discard the original) */
- size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
-#ifdef CONFIG_MODULES
- if (size < PERCPU_ENOUGH_ROOM)
- size = PERCPU_ENOUGH_ROOM;
-#endif
+ size = PERCPU_ENOUGH_ROOM;
+ printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
for_each_cpu_mask (i, cpu_possible_map) {
char *ptr;
@@ -122,7 +121,10 @@ void pda_init(int cpu)
/* Setup up data that may be needed in __get_free_pages early */
asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+ /* Memory clobbers used to order PDA accessed */
+ mb();
wrmsrl(MSR_GS_BASE, pda);
+ mb();
pda->cpunumber = cpu;
pda->irqcount = -1;
@@ -178,6 +180,8 @@ void __cpuinit check_efer(void)
}
}
+unsigned long kernel_eflags;
+
/*
* cpu_init() initializes state that is per-CPU. Some data is already
* initialized (naturally) in the bootstrap process, such as the GDT
@@ -235,28 +239,17 @@ void __cpuinit cpu_init (void)
* set up and load the per-CPU TSS
*/
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+ static const unsigned int order[N_EXCEPTION_STACKS] = {
+ [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+ [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+ };
if (cpu) {
- static const unsigned int order[N_EXCEPTION_STACKS] = {
- [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
- [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
- };
-
estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
if (!estacks)
panic("Cannot allocate exception stack %ld %d\n",
v, cpu);
}
- switch (v + 1) {
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
- case DEBUG_STACK:
- cpu_pda(cpu)->debugstack = (unsigned long)estacks;
- estacks += DEBUG_STKSZ;
- break;
-#endif
- default:
- estacks += EXCEPTION_STKSZ;
- break;
- }
+ estacks += PAGE_SIZE << order[v];
orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
}
@@ -290,4 +283,6 @@ void __cpuinit cpu_init (void)
set_debugreg(0UL, 7);
fpu_init();
+
+ raw_local_save_flags(kernel_eflags);
}
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 28161170fb0..49ec324cd14 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -38,37 +38,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs);
asmlinkage long
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-#ifdef DEBUG_SIG
- printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n",
- saveset, newset, regs, regs->rip);
-#endif
- regs->rax = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage long
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
struct pt_regs *regs)
{
@@ -308,11 +277,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
/* Set up registers for signal handler */
- {
- struct exec_domain *ed = current_thread_info()->exec_domain;
- if (unlikely(ed && ed->signal_invmap && sig < 32))
- sig = ed->signal_invmap[sig];
- }
regs->rdi = sig;
/* In case the signal handler was declared without prototypes */
regs->rax = 0;
@@ -341,11 +305,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return 1;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
- return 0;
+ return -EFAULT;
}
/*
@@ -408,7 +372,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
#endif
ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret) {
+ if (ret == 0) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -425,11 +389,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
{
struct k_sigaction ka;
siginfo_t info;
int signr;
+ sigset_t *oldset;
/*
* We want the common case to go fast, which
@@ -438,9 +403,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* if so.
*/
if (!user_mode(regs))
- return 1;
+ return;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -454,30 +421,46 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
set_debugreg(current->thread.debugreg7, 7);
/* Whee! Actually deliver the signal. */
- return handle_signal(signr, &info, &ka, oldset, regs);
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ return;
}
/* Did we come from a system call? */
if ((long)regs->orig_rax >= 0) {
/* Restart the system call - no handlers present */
long res = regs->rax;
- if (res == -ERESTARTNOHAND ||
- res == -ERESTARTSYS ||
- res == -ERESTARTNOINTR) {
+ switch (res) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
regs->rax = regs->orig_rax;
regs->rip -= 2;
- }
- if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
+ break;
+ case -ERESTART_RESTARTBLOCK:
regs->rax = test_thread_flag(TIF_IA32) ?
__NR_ia32_restart_syscall :
__NR_restart_syscall;
regs->rip -= 2;
+ break;
}
}
- return 0;
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ back. */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
}
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_flags)
+void
+do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
{
#ifdef DEBUG_SIG
printk("do_notify_resume flags:%x rip:%lx rsp:%lx caller:%lx pending:%lx\n",
@@ -491,8 +474,8 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_
}
/* deal with pending signal delivery */
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(regs,oldset);
+ if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
+ do_signal(regs);
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 06af6ca6012..4f67697f503 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -522,26 +522,3 @@ asmlinkage void smp_call_function_interrupt(void)
}
}
-int safe_smp_processor_id(void)
-{
- unsigned apicid, i;
-
- if (disable_apic)
- return 0;
-
- apicid = hard_smp_processor_id();
- if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid)
- return apicid;
-
- for (i = 0; i < NR_CPUS; ++i) {
- if (x86_cpu_to_apicid[i] == apicid)
- return i;
- }
-
- /* No entries in x86_cpu_to_apicid? Either no MPS|ACPI,
- * or called too early. Either way, we must be CPU 0. */
- if (x86_cpu_to_apicid[0] == BAD_APICID)
- return 0;
-
- return 0; /* Should not happen */
-}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 975380207b4..7b7a6870288 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -46,9 +46,10 @@
#include <linux/bootmem.h>
#include <linux/thread_info.h>
#include <linux/module.h>
-
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
+#include <linux/smp.h>
+
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
#include <asm/desc.h>
@@ -1090,7 +1091,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/*
* Switch from PIC to APIC mode.
*/
- connect_bsp_APIC();
setup_local_APIC();
if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
@@ -1175,12 +1175,9 @@ int __cpuinit __cpu_up(unsigned int cpu)
void __init smp_cpus_done(unsigned int max_cpus)
{
smp_cleanup_boot();
-
-#ifdef CONFIG_X86_IO_APIC
setup_ioapic_dest();
-#endif
-
check_nmi_watchdog();
+ time_init_gtod();
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -1233,6 +1230,8 @@ int __cpu_disable(void)
if (cpu == 0)
return -EBUSY;
+ if (nmi_watchdog == NMI_LOCAL_APIC)
+ stop_apic_nmi_watchdog(NULL);
clear_local_APIC();
/*
@@ -1272,11 +1271,11 @@ void __cpu_die(unsigned int cpu)
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
-__init int setup_additional_cpus(char *s)
+static __init int setup_additional_cpus(char *s)
{
- return get_option(&s, &additional_cpus);
+ return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
}
-__setup("additional_cpus=", setup_additional_cpus);
+early_param("additional_cpus", setup_additional_cpus);
#else /* ... !CONFIG_HOTPLUG_CPU */
diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c
index 32cf55eb9af..6026b31d037 100644
--- a/arch/x86_64/kernel/stacktrace.c
+++ b/arch/x86_64/kernel/stacktrace.c
@@ -7,215 +7,49 @@
*/
#include <linux/sched.h>
#include <linux/stacktrace.h>
+#include <linux/module.h>
+#include <asm/stacktrace.h>
-#include <asm/smp.h>
-
-static inline int
-in_range(unsigned long start, unsigned long addr, unsigned long end)
+static void save_stack_warning(void *data, char *msg)
{
- return addr >= start && addr <= end;
}
-static unsigned long
-get_stack_end(struct task_struct *task, unsigned long stack)
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
{
- unsigned long stack_start, stack_end, flags;
- int i, cpu;
-
- /*
- * The most common case is that we are in the task stack:
- */
- stack_start = (unsigned long)task->thread_info;
- stack_end = stack_start + THREAD_SIZE;
-
- if (in_range(stack_start, stack, stack_end))
- return stack_end;
-
- /*
- * We are in an interrupt if irqstackptr is set:
- */
- raw_local_irq_save(flags);
- cpu = safe_smp_processor_id();
- stack_end = (unsigned long)cpu_pda(cpu)->irqstackptr;
-
- if (stack_end) {
- stack_start = stack_end & ~(IRQSTACKSIZE-1);
- if (in_range(stack_start, stack, stack_end))
- goto out_restore;
- /*
- * We get here if we are in an IRQ context but we
- * are also in an exception stack.
- */
- }
-
- /*
- * Iterate over all exception stacks, and figure out whether
- * 'stack' is in one of them:
- */
- for (i = 0; i < N_EXCEPTION_STACKS; i++) {
- /*
- * set 'end' to the end of the exception stack.
- */
- stack_end = per_cpu(init_tss, cpu).ist[i];
- stack_start = stack_end - EXCEPTION_STKSZ;
-
- /*
- * Is 'stack' above this exception frame's end?
- * If yes then skip to the next frame.
- */
- if (stack >= stack_end)
- continue;
- /*
- * Is 'stack' above this exception frame's start address?
- * If yes then we found the right frame.
- */
- if (stack >= stack_start)
- goto out_restore;
-
- /*
- * If this is a debug stack, and if it has a larger size than
- * the usual exception stacks, then 'stack' might still
- * be within the lower portion of the debug stack:
- */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
- if (i == DEBUG_STACK - 1 && stack >= stack_end - DEBUG_STKSZ) {
- /*
- * Black magic. A large debug stack is composed of
- * multiple exception stack entries, which we
- * iterate through now. Dont look:
- */
- do {
- stack_end -= EXCEPTION_STKSZ;
- stack_start -= EXCEPTION_STKSZ;
- } while (stack < stack_start);
-
- goto out_restore;
- }
-#endif
- }
- /*
- * Ok, 'stack' is not pointing to any of the system stacks.
- */
- stack_end = 0;
-
-out_restore:
- raw_local_irq_restore(flags);
-
- return stack_end;
}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer:
- */
-static inline unsigned long
-save_context_stack(struct stack_trace *trace, unsigned int skip,
- unsigned long stack, unsigned long stack_end)
+static int save_stack_stack(void *data, char *name)
{
- unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
- unsigned long prev_stack = 0;
+ struct stack_trace *trace = (struct stack_trace *)data;
+ return trace->all_contexts ? 0 : -1;
+}
- while (in_range(prev_stack, stack, stack_end)) {
- pr_debug("stack: %p\n", (void *)stack);
- addr = (unsigned long)(((unsigned long *)stack)[1]);
- pr_debug("addr: %p\n", (void *)addr);
- if (!skip)
- trace->entries[trace->nr_entries++] = addr-1;
- else
- skip--;
- if (trace->nr_entries >= trace->max_entries)
- break;
- if (!addr)
- return 0;
- /*
- * Stack frames must go forwards (otherwise a loop could
- * happen if the stackframe is corrupted), so we move
- * prev_stack forwards:
- */
- prev_stack = stack;
- stack = (unsigned long)(((unsigned long *)stack)[0]);
- }
- pr_debug("invalid: %p\n", (void *)stack);
-#else
- while (stack < stack_end) {
- addr = ((unsigned long *)stack)[0];
- stack += sizeof(long);
- if (__kernel_text_address(addr)) {
- if (!skip)
- trace->entries[trace->nr_entries++] = addr-1;
- else
- skip--;
- if (trace->nr_entries >= trace->max_entries)
- break;
- }
+static void save_stack_address(void *data, unsigned long addr)
+{
+ struct stack_trace *trace = (struct stack_trace *)data;
+ if (trace->skip > 0) {
+ trace->skip--;
+ return;
}
-#endif
- return stack;
+ if (trace->nr_entries < trace->max_entries - 1)
+ trace->entries[trace->nr_entries++] = addr;
}
-#define MAX_STACKS 10
+static struct stacktrace_ops save_stack_ops = {
+ .warning = save_stack_warning,
+ .warning_symbol = save_stack_warning_symbol,
+ .stack = save_stack_stack,
+ .address = save_stack_address,
+};
/*
* Save stack-backtrace addresses into a stack_trace buffer.
- * If all_contexts is set, all contexts (hardirq, softirq and process)
- * are saved. If not set then only the current context is saved.
*/
-void save_stack_trace(struct stack_trace *trace,
- struct task_struct *task, int all_contexts,
- unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
- unsigned long stack = (unsigned long)&stack;
- int i, nr_stacks = 0, stacks_done[MAX_STACKS];
-
- WARN_ON(trace->nr_entries || !trace->max_entries);
-
- if (!task)
- task = current;
-
- pr_debug("task: %p, ti: %p\n", task, task->thread_info);
-
- if (!task || task == current) {
- /* Grab rbp right from our regs: */
- asm ("mov %%rbp, %0" : "=r" (stack));
- pr_debug("rbp: %p\n", (void *)stack);
- } else {
- /* rbp is the last reg pushed by switch_to(): */
- stack = task->thread.rsp;
- pr_debug("other task rsp: %p\n", (void *)stack);
- stack = (unsigned long)(((unsigned long *)stack)[0]);
- pr_debug("other task rbp: %p\n", (void *)stack);
- }
-
- while (1) {
- unsigned long stack_end = get_stack_end(task, stack);
-
- pr_debug("stack: %p\n", (void *)stack);
- pr_debug("stack end: %p\n", (void *)stack_end);
-
- /*
- * Invalid stack addres?
- */
- if (!stack_end)
- return;
- /*
- * Were we in this stack already? (recursion)
- */
- for (i = 0; i < nr_stacks; i++)
- if (stacks_done[i] == stack_end)
- return;
- stacks_done[nr_stacks] = stack_end;
-
- stack = save_context_stack(trace, skip, stack, stack_end);
- if (!all_contexts || !stack ||
- trace->nr_entries >= trace->max_entries)
- return;
- trace->entries[trace->nr_entries++] = ULONG_MAX;
- if (trace->nr_entries >= trace->max_entries)
- return;
- if (++nr_stacks >= MAX_STACKS)
- return;
- }
+ dump_trace(task, NULL, NULL, &save_stack_ops, trace);
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
+EXPORT_SYMBOL(save_stack_trace);
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
index 320b6fb00cc..bfbe00763c6 100644
--- a/arch/x86_64/kernel/suspend_asm.S
+++ b/arch/x86_64/kernel/suspend_asm.S
@@ -54,7 +54,7 @@ ENTRY(restore_image)
movq %rcx, %cr3;
movq %rax, %cr4; # turn PGE back on
- movq pagedir_nosave(%rip), %rdx
+ movq restore_pblist(%rip), %rdx
loop:
testq %rdx, %rdx
jz done
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
index 5530dda3f27..cbabfdf78e0 100644
--- a/arch/x86_64/kernel/tce.c
+++ b/arch/x86_64/kernel/tce.c
@@ -1,4 +1,6 @@
/*
+ * This file manages the translation entries for the IBM Calgary IOMMU.
+ *
* Derived from arch/powerpc/platforms/pseries/iommu.c
*
* Copyright (C) IBM Corporation, 2006
@@ -104,14 +106,6 @@ static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
/* set the tce table size - measured in entries */
tbl->it_size = table_size_to_number_of_entries(specified_table_size);
- tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
- if (!tbl->it_base) {
- printk(KERN_ERR "Calgary: iommu_table_setparms: "
- "no table allocated?!\n");
- ret = -ENOMEM;
- goto done;
- }
-
/*
* number of bytes needed for the bitmap size in number of
* entries; we need one bit per entry
@@ -160,8 +154,6 @@ int build_tce_table(struct pci_dev *dev, void __iomem *bbar)
if (ret)
goto free_tbl;
- tce_free(tbl, 0, tbl->it_size);
-
tbl->bbar = bbar;
/*
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 7a9b1822418..1c255ee76e7 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -24,6 +24,8 @@
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/bcd.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
#include <linux/kallsyms.h>
#include <linux/acpi.h>
#ifdef CONFIG_ACPI
@@ -39,9 +41,7 @@
#include <asm/sections.h>
#include <linux/cpufreq.h>
#include <linux/hpet.h>
-#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
-#endif
#ifdef CONFIG_CPU_FREQ
static void cpufreq_delayed_get(void);
@@ -49,7 +49,7 @@ static void cpufreq_delayed_get(void);
extern void i8254_timer_resume(void);
extern int using_apic_timer;
-static char *time_init_gtod(void);
+static char *timename = NULL;
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
@@ -187,20 +187,15 @@ unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
- /* Assume the lock function has either no stack frame or only a single
- word. This checks if the address on the stack looks like a kernel
- text address.
- There is a small window for false hits, but in that case the tick
- is just accounted to the spinlock function.
- Better would be to write these functions in assembler again
- and check exactly. */
+ /* Assume the lock function has either no stack frame or a copy
+ of eflags from PUSHF
+ Eflags always has bits 22 and up cleared unlike kernel addresses. */
if (!user_mode(regs) && in_lock_functions(pc)) {
- char *v = *(char **)regs->rsp;
- if ((v >= _stext && v <= _etext) ||
- (v >= _sinittext && v <= _einittext) ||
- (v >= (char *)MODULES_VADDR && v <= (char *)MODULES_END))
- return (unsigned long)v;
- return ((unsigned long *)regs->rsp)[1];
+ unsigned long *sp = (unsigned long *)regs->rsp;
+ if (sp[0] >> 22)
+ return sp[0];
+ if (sp[1] >> 22)
+ return sp[1];
}
return pc;
}
@@ -281,6 +276,7 @@ static void set_rtc_mmss(unsigned long nowtime)
* Note: This function is required to return accurate
* time even in the absence of multiple timer ticks.
*/
+static inline unsigned long long cycles_2_ns(unsigned long long cyc);
unsigned long long monotonic_clock(void)
{
unsigned long seq;
@@ -305,8 +301,7 @@ unsigned long long monotonic_clock(void)
base = monotonic_base;
} while (read_seqretry(&xtime_lock, seq));
this_offset = get_cycles_sync();
- /* FIXME: 1000 or 1000000? */
- offset = (this_offset - last_offset)*1000 / cpu_khz;
+ offset = cycles_2_ns(this_offset - last_offset);
}
return base + offset;
}
@@ -410,8 +405,7 @@ void main_timer_handler(struct pt_regs *regs)
offset %= USEC_PER_TICK;
}
- /* FIXME: 1000 or 1000000? */
- monotonic_base += (tsc - vxtime.last_tsc) * 1000000 / cpu_khz;
+ monotonic_base += cycles_2_ns(tsc - vxtime.last_tsc);
vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
@@ -441,12 +435,8 @@ void main_timer_handler(struct pt_regs *regs)
* have to call the local interrupt handler.
*/
-#ifndef CONFIG_X86_LOCAL_APIC
- profile_tick(CPU_PROFILING, regs);
-#else
if (!using_apic_timer)
smp_local_timer_interrupt(regs);
-#endif
/*
* If we have an externally synchronized Linux clock, then update CMOS clock
@@ -470,10 +460,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (apic_runs_main_timer > 1)
return IRQ_HANDLED;
main_timer_handler(regs);
-#ifdef CONFIG_X86_LOCAL_APIC
if (using_apic_timer)
smp_send_timer_broadcast_ipi();
-#endif
return IRQ_HANDLED;
}
@@ -893,11 +881,17 @@ static struct irqaction irq0 = {
timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
};
-void __init time_init(void)
+static int __cpuinit
+time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu)
{
- char *timename;
- char *gtod;
+ unsigned cpu = (unsigned long) hcpu;
+ if (action == CPU_ONLINE)
+ vsyscall_set_cpu(cpu);
+ return NOTIFY_DONE;
+}
+void __init time_init(void)
+{
if (nohpet)
vxtime.hpet_address = 0;
@@ -931,18 +925,17 @@ void __init time_init(void)
}
vxtime.mode = VXTIME_TSC;
- gtod = time_init_gtod();
-
- printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
- vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
- printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
- cpu_khz / 1000, cpu_khz % 1000);
vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
vxtime.last_tsc = get_cycles_sync();
+ set_cyc2ns_scale(cpu_khz);
setup_irq(0, &irq0);
+ hotcpu_notifier(time_cpu_notifier, 0);
+ time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id());
- set_cyc2ns_scale(cpu_khz);
+#ifndef CONFIG_SMP
+ time_init_gtod();
+#endif
}
/*
@@ -973,12 +966,18 @@ __cpuinit int unsynchronized_tsc(void)
/*
* Decide what mode gettimeofday should use.
*/
-__init static char *time_init_gtod(void)
+void time_init_gtod(void)
{
char *timetype;
if (unsynchronized_tsc())
notsc = 1;
+
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
+ vgetcpu_mode = VGETCPU_RDTSCP;
+ else
+ vgetcpu_mode = VGETCPU_LSL;
+
if (vxtime.hpet_address && notsc) {
timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
if (hpet_use_timer)
@@ -1001,7 +1000,16 @@ __init static char *time_init_gtod(void)
timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
vxtime.mode = VXTIME_TSC;
}
- return timetype;
+
+ printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
+ vxtime_hz / 1000000, vxtime_hz % 1000000, timename, timetype);
+ printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
+ cpu_khz / 1000, cpu_khz % 1000);
+ vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
+ vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
+ vxtime.last_tsc = get_cycles_sync();
+
+ set_cyc2ns_scale(cpu_khz);
}
__setup("report_lost_ticks", time_setup);
@@ -1031,8 +1039,16 @@ static int timer_resume(struct sys_device *dev)
unsigned long flags;
unsigned long sec;
unsigned long ctime = get_cmos_time();
- unsigned long sleep_length = (ctime - sleep_start) * HZ;
+ long sleep_length = (ctime - sleep_start) * HZ;
+ if (sleep_length < 0) {
+ printk(KERN_WARNING "Time skew detected in timer resume!\n");
+ /* The time after the resume must not be earlier than the time
+ * before the suspend or some nasty things will happen
+ */
+ sleep_length = 0;
+ ctime = sleep_start;
+ }
if (vxtime.hpet_address)
hpet_reenable();
else
@@ -1148,23 +1164,25 @@ int hpet_rtc_timer_init(void)
hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
local_irq_save(flags);
+
cnt = hpet_readl(HPET_COUNTER);
cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
hpet_writel(cnt, HPET_T1_CMP);
hpet_t1_cmp = cnt;
- local_irq_restore(flags);
cfg = hpet_readl(HPET_T1_CFG);
cfg &= ~HPET_TN_PERIODIC;
cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
hpet_writel(cfg, HPET_T1_CFG);
+ local_irq_restore(flags);
+
return 1;
}
static void hpet_rtc_timer_reinit(void)
{
- unsigned int cfg, cnt;
+ unsigned int cfg, cnt, ticks_per_int, lost_ints;
if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
cfg = hpet_readl(HPET_T1_CFG);
@@ -1179,10 +1197,33 @@ static void hpet_rtc_timer_reinit(void)
hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
/* It is more accurate to use the comparator value than current count.*/
- cnt = hpet_t1_cmp;
- cnt += hpet_tick*HZ/hpet_rtc_int_freq;
- hpet_writel(cnt, HPET_T1_CMP);
- hpet_t1_cmp = cnt;
+ ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
+ hpet_t1_cmp += ticks_per_int;
+ hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+ /*
+ * If the interrupt handler was delayed too long, the write above tries
+ * to schedule the next interrupt in the past and the hardware would
+ * not interrupt until the counter had wrapped around.
+ * So we have to check that the comparator wasn't set to a past time.
+ */
+ cnt = hpet_readl(HPET_COUNTER);
+ if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
+ lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
+ /* Make sure that, even with the time needed to execute
+ * this code, the next scheduled interrupt has been moved
+ * back to the future: */
+ lost_ints++;
+
+ hpet_t1_cmp += lost_ints * ticks_per_int;
+ hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+ if (PIE_on)
+ PIE_count += lost_ints;
+
+ printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+ hpet_rtc_int_freq);
+ }
}
/*
diff --git a/arch/x86_64/kernel/trampoline.S b/arch/x86_64/kernel/trampoline.S
index 23a03eb91fc..c79b99a9e2f 100644
--- a/arch/x86_64/kernel/trampoline.S
+++ b/arch/x86_64/kernel/trampoline.S
@@ -64,7 +64,7 @@ idt_48:
.word 0, 0 # idt base = 0L
gdt_48:
- .short __KERNEL32_CS + 7 # gdt limit
+ .short GDT_ENTRIES*8 - 1 # gdt limit
.long cpu_gdt_table-__START_KERNEL_map
.globl trampoline_end
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index b1249774d1e..01f2a8d254c 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -45,6 +45,7 @@
#include <asm/pda.h>
#include <asm/proto.h>
#include <asm/nmi.h>
+#include <asm/stacktrace.h>
asmlinkage void divide_error(void);
asmlinkage void debug(void);
@@ -142,7 +143,7 @@ void printk_address(unsigned long address)
#endif
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
- unsigned *usedp, const char **idp)
+ unsigned *usedp, char **idp)
{
static char ids[][8] = {
[DEBUG_STACK - 1] = "#DB",
@@ -161,26 +162,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
* 'stack' is in one of them:
*/
for (k = 0; k < N_EXCEPTION_STACKS; k++) {
- unsigned long end;
-
- /*
- * set 'end' to the end of the exception stack.
- */
- switch (k + 1) {
- /*
- * TODO: this block is not needed i think, because
- * setup64.c:cpu_init() sets up t->ist[DEBUG_STACK]
- * properly too.
- */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
- case DEBUG_STACK:
- end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
- break;
-#endif
- default:
- end = per_cpu(orig_ist, cpu).ist[k];
- break;
- }
+ unsigned long end = per_cpu(orig_ist, cpu).ist[k];
/*
* Is 'stack' above this exception frame's end?
* If yes then skip to the next frame.
@@ -234,13 +216,19 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
return NULL;
}
-static int show_trace_unwind(struct unwind_frame_info *info, void *context)
+struct ops_and_data {
+ struct stacktrace_ops *ops;
+ void *data;
+};
+
+static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
{
+ struct ops_and_data *oad = (struct ops_and_data *)context;
int n = 0;
while (unwind(info) == 0 && UNW_PC(info)) {
n++;
- printk_address(UNW_PC(info));
+ oad->ops->address(oad->data, UNW_PC(info));
if (arch_unw_user_mode(info))
break;
}
@@ -254,45 +242,53 @@ static int show_trace_unwind(struct unwind_frame_info *info, void *context)
* severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
*/
-void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack,
+ struct stacktrace_ops *ops, void *data)
{
- const unsigned cpu = safe_smp_processor_id();
+ const unsigned cpu = smp_processor_id();
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
unsigned used = 0;
- printk("\nCall Trace:\n");
-
if (!tsk)
tsk = current;
if (call_trace >= 0) {
int unw_ret = 0;
struct unwind_frame_info info;
+ struct ops_and_data oad = { .ops = ops, .data = data };
if (regs) {
if (unwind_init_frame_info(&info, tsk, regs) == 0)
- unw_ret = show_trace_unwind(&info, NULL);
+ unw_ret = dump_trace_unwind(&info, &oad);
} else if (tsk == current)
- unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
+ unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
else {
if (unwind_init_blocked(&info, tsk) == 0)
- unw_ret = show_trace_unwind(&info, NULL);
+ unw_ret = dump_trace_unwind(&info, &oad);
}
if (unw_ret > 0) {
if (call_trace == 1 && !arch_unw_user_mode(&info)) {
- print_symbol("DWARF2 unwinder stuck at %s\n",
+ ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
UNW_PC(&info));
if ((long)UNW_SP(&info) < 0) {
- printk("Leftover inexact backtrace:\n");
+ ops->warning(data, "Leftover inexact backtrace:\n");
stack = (unsigned long *)UNW_SP(&info);
+ if (!stack)
+ return;
} else
- printk("Full inexact backtrace again:\n");
+ ops->warning(data, "Full inexact backtrace again:\n");
} else if (call_trace >= 1)
return;
else
- printk("Full inexact backtrace again:\n");
+ ops->warning(data, "Full inexact backtrace again:\n");
} else
- printk("Inexact backtrace:\n");
+ ops->warning(data, "Inexact backtrace:\n");
+ }
+ if (!stack) {
+ unsigned long dummy;
+ stack = &dummy;
+ if (tsk && tsk != current)
+ stack = (unsigned long *)tsk->thread.rsp;
}
/*
@@ -303,7 +299,9 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
#define HANDLE_STACK(cond) \
do while (cond) { \
unsigned long addr = *stack++; \
- if (kernel_text_address(addr)) { \
+ if (oops_in_progress ? \
+ __kernel_text_address(addr) : \
+ kernel_text_address(addr)) { \
/* \
* If the address is either in the text segment of the \
* kernel, or in the region which contains vmalloc'ed \
@@ -312,7 +310,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
* down the cause of the crash will be able to figure \
* out the call path that was taken. \
*/ \
- printk_address(addr); \
+ ops->address(data, addr); \
} \
} while (0)
@@ -321,16 +319,17 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
* current stack address. If the stacks consist of nested
* exceptions
*/
- for ( ; ; ) {
- const char *id;
+ for (;;) {
+ char *id;
unsigned long *estack_end;
estack_end = in_exception_stack(cpu, (unsigned long)stack,
&used, &id);
if (estack_end) {
- printk(" <%s>", id);
+ if (ops->stack(data, id) < 0)
+ break;
HANDLE_STACK (stack < estack_end);
- printk(" <EOE>");
+ ops->stack(data, "<EOE>");
/*
* We link to the next stack via the
* second-to-last pointer (index -2 to end) in the
@@ -345,7 +344,8 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
(IRQSTACKSIZE - 64) / sizeof(*irqstack);
if (stack >= irqstack && stack < irqstack_end) {
- printk(" <IRQ>");
+ if (ops->stack(data, "IRQ") < 0)
+ break;
HANDLE_STACK (stack < irqstack_end);
/*
* We link to the next stack (which would be
@@ -354,7 +354,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
*/
stack = (unsigned long *) (irqstack_end[-1]);
irqstack_end = NULL;
- printk(" <EOI>");
+ ops->stack(data, "EOI");
continue;
}
}
@@ -362,19 +362,57 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
}
/*
- * This prints the process stack:
+ * This handles the process stack:
*/
HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
#undef HANDLE_STACK
+}
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+ print_symbol(msg, symbol);
+ printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+ printk("%s\n", msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+ printk(" <%s> ", name);
+ return 0;
+}
+
+static void print_trace_address(void *data, unsigned long addr)
+{
+ printk_address(addr);
+}
+
+static struct stacktrace_ops print_trace_ops = {
+ .warning = print_trace_warning,
+ .warning_symbol = print_trace_warning_symbol,
+ .stack = print_trace_stack,
+ .address = print_trace_address,
+};
+void
+show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack)
+{
+ printk("\nCall Trace:\n");
+ dump_trace(tsk, regs, stack, &print_trace_ops, NULL);
printk("\n");
}
-static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
+static void
+_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *rsp)
{
unsigned long *stack;
int i;
- const int cpu = safe_smp_processor_id();
+ const int cpu = smp_processor_id();
unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
@@ -428,7 +466,7 @@ void show_registers(struct pt_regs *regs)
int i;
int in_kernel = !user_mode(regs);
unsigned long rsp;
- const int cpu = safe_smp_processor_id();
+ const int cpu = smp_processor_id();
struct task_struct *cur = cpu_pda(cpu)->pcurrent;
rsp = regs->rsp;
@@ -503,9 +541,11 @@ static unsigned int die_nest_count;
unsigned __kprobes long oops_begin(void)
{
- int cpu = safe_smp_processor_id();
+ int cpu = smp_processor_id();
unsigned long flags;
+ oops_enter();
+
/* racy, but better than risking deadlock. */
local_irq_save(flags);
if (!spin_trylock(&die_lock)) {
@@ -534,6 +574,7 @@ void __kprobes oops_end(unsigned long flags)
spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
panic("Fatal exception");
+ oops_exit();
}
void __kprobes __die(const char * str, struct pt_regs * regs, long err)
@@ -570,7 +611,7 @@ void die(const char * str, struct pt_regs * regs, long err)
do_exit(SIGSEGV);
}
-void __kprobes die_nmi(char *str, struct pt_regs *regs)
+void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
{
unsigned long flags = oops_begin();
@@ -578,13 +619,12 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
* We are in trouble anyway, lets at least try
* to get a message out.
*/
- printk(str, safe_smp_processor_id());
+ printk(str, smp_processor_id());
show_registers(regs);
if (kexec_should_crash(current))
crash_kexec(regs);
- if (panic_on_timeout || panic_on_oops)
- panic("nmi watchdog");
- printk("console shuts up ...\n");
+ if (do_panic || panic_on_oops)
+ panic("Non maskable interrupt");
oops_end(flags);
nmi_exit();
local_irq_enable();
@@ -730,8 +770,15 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
static __kprobes void
mem_parity_error(unsigned char reason, struct pt_regs * regs)
{
- printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
- printk("You probably have a hardware problem with your RAM chips\n");
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ reason);
+ printk(KERN_EMERG "You probably have a hardware problem with your "
+ "RAM chips\n");
+
+ if (panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
/* Clear and disable the memory parity error line. */
reason = (reason & 0xf) | 4;
@@ -754,9 +801,15 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
static __kprobes void
unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
-{ printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
- printk("Dazed and confused, but trying to continue\n");
- printk("Do you have a strange power saving mode enabled?\n");
+{
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ reason);
+ printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+
+ if (panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
}
/* Runs on IST stack. This code must keep interrupts off all the time.
@@ -776,17 +829,15 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
== NOTIFY_STOP)
return;
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* Ok, so this is none of the documented NMI sources,
* so it must be the NMI watchdog.
*/
- if (nmi_watchdog > 0) {
- nmi_watchdog_tick(regs,reason);
+ if (nmi_watchdog_tick(regs,reason))
return;
- }
-#endif
- unknown_nmi_error(reason, regs);
+ if (!do_nmi_callback(regs,cpu))
+ unknown_nmi_error(reason, regs);
+
return;
}
if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
@@ -1071,6 +1122,7 @@ asmlinkage void math_state_restore(void)
init_fpu(me);
restore_fpu_checking(&me->thread.i387.fxsave);
task_thread_info(me)->status |= TS_USEDFPU;
+ me->fpu_counter++;
}
void __init trap_init(void)
@@ -1109,24 +1161,30 @@ void __init trap_init(void)
}
-/* Actual parsing is done early in setup.c. */
-static int __init oops_dummy(char *s)
+static int __init oops_setup(char *s)
{
- panic_on_oops = 1;
- return 1;
+ if (!s)
+ return -EINVAL;
+ if (!strcmp(s, "panic"))
+ panic_on_oops = 1;
+ return 0;
}
-__setup("oops=", oops_dummy);
+early_param("oops", oops_setup);
static int __init kstack_setup(char *s)
{
+ if (!s)
+ return -EINVAL;
kstack_depth_to_print = simple_strtoul(s,NULL,0);
- return 1;
+ return 0;
}
-__setup("kstack=", kstack_setup);
+early_param("kstack", kstack_setup);
#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
+ if (!s)
+ return -EINVAL;
if (strcmp(s, "old") == 0)
call_trace = -1;
else if (strcmp(s, "both") == 0)
@@ -1135,7 +1193,7 @@ static int __init call_trace_setup(char *s)
call_trace = 1;
else if (strcmp(s, "new") == 0)
call_trace = 2;
- return 1;
+ return 0;
}
-__setup("call_trace=", call_trace_setup);
+early_param("call_trace", call_trace_setup);
#endif
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 7c4de31471d..d0564f1bcb0 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
jiffies_64 = jiffies;
+PHDRS {
+ text PT_LOAD FLAGS(5); /* R_E */
+ data PT_LOAD FLAGS(7); /* RWE */
+ user PT_LOAD FLAGS(7); /* RWE */
+ note PT_NOTE FLAGS(4); /* R__ */
+}
SECTIONS
{
. = __START_KERNEL;
@@ -31,7 +37,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x9090
+ } :text = 0x9090
/* out-of-line lock text */
.text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
@@ -57,7 +63,7 @@ SECTIONS
.data : AT(ADDR(.data) - LOAD_OFFSET) {
*(.data)
CONSTRUCTORS
- }
+ } :data
_edata = .; /* End of data section */
@@ -89,7 +95,7 @@ SECTIONS
#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
. = VSYSCALL_ADDR;
- .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
+ .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
__vsyscall_0 = VSYSCALL_VIRT_ADDR;
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
@@ -99,6 +105,9 @@ SECTIONS
.vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
vxtime = VVIRT(.vxtime);
+ .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
+ vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
.wall_jiffies : AT(VLOAD(.wall_jiffies)) { *(.wall_jiffies) }
wall_jiffies = VVIRT(.wall_jiffies);
@@ -132,7 +141,7 @@ SECTIONS
. = ALIGN(8192); /* init_task */
.data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
*(.data.init_task)
- }
+ } :data
. = ALIGN(4096);
.data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
@@ -207,14 +216,12 @@ SECTIONS
__initramfs_start = .;
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
__initramfs_end = .;
- /* temporary here to work around NR_CPUS. If you see this comment in 2.6.17+
- complain */
- . = ALIGN(4096);
- __init_end = .;
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
__per_cpu_start = .;
.data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
__per_cpu_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
. = ALIGN(4096);
__nosave_begin = .;
diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c
index 92f70c74965..044e852bd25 100644
--- a/arch/x86_64/kernel/vsmp.c
+++ b/arch/x86_64/kernel/vsmp.c
@@ -20,6 +20,9 @@ static int __init vsmp_init(void)
void *address;
unsigned int cap, ctl;
+ if (!early_pci_allowed())
+ return 0;
+
/* Check if we are running on a ScaleMP vSMP box */
if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) ||
(read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index f603037df16..ac48c3857dd 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -26,6 +26,7 @@
#include <linux/seqlock.h>
#include <linux/jiffies.h>
#include <linux/sysctl.h>
+#include <linux/getcpu.h>
#include <asm/vsyscall.h>
#include <asm/pgtable.h>
@@ -33,11 +34,15 @@
#include <asm/fixmap.h>
#include <asm/errno.h>
#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/desc.h>
+#include <asm/topology.h>
#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
+int __vgetcpu_mode __section_vgetcpu_mode;
#include <asm/unistd.h>
@@ -72,7 +77,8 @@ static __always_inline void do_vgettimeofday(struct timeval * tv)
__vxtime.tsc_quot) >> 32;
/* See comment in x86_64 do_gettimeofday. */
} else {
- usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) -
+ usec += ((readl((void __iomem *)
+ fix_to_virt(VSYSCALL_HPET) + 0xf0) -
__vxtime.last) * __vxtime.quot) >> 32;
}
} while (read_seqretry(&__xtime_lock, sequence));
@@ -127,9 +133,46 @@ time_t __vsyscall(1) vtime(time_t *t)
return __xtime.tv_sec;
}
-long __vsyscall(2) venosys_0(void)
+/* Fast way to get current CPU and node.
+ This helps to do per node and per CPU caches in user space.
+ The result is not guaranteed without CPU affinity, but usually
+ works out because the scheduler tries to keep a thread on the same
+ CPU.
+
+ tcache must point to a two element sized long array.
+ All arguments can be NULL. */
+long __vsyscall(2)
+vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
{
- return -ENOSYS;
+ unsigned int dummy, p;
+ unsigned long j = 0;
+
+ /* Fast cache - only recompute value once per jiffies and avoid
+ relatively costly rdtscp/cpuid otherwise.
+ This works because the scheduler usually keeps the process
+ on the same CPU and this syscall doesn't guarantee its
+ results anyways.
+ We do this here because otherwise user space would do it on
+ its own in a likely inferior way (no access to jiffies).
+ If you don't like it pass NULL. */
+ if (tcache && tcache->t0 == (j = __jiffies)) {
+ p = tcache->t1;
+ } else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+ /* Load per CPU data from RDTSCP */
+ rdtscp(dummy, dummy, p);
+ } else {
+ /* Load per CPU data from GDT */
+ asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+ }
+ if (tcache) {
+ tcache->t0 = j;
+ tcache->t1 = p;
+ }
+ if (cpu)
+ *cpu = p & 0xfff;
+ if (node)
+ *node = p >> 12;
+ return 0;
}
long __vsyscall(3) venosys_1(void)
@@ -149,7 +192,8 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
extern u16 vsysc1, vsysc2;
- u16 *map1, *map2;
+ u16 __iomem *map1;
+ u16 __iomem *map2;
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (!write)
return ret;
@@ -164,11 +208,11 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
goto out;
}
if (!sysctl_vsyscall) {
- *map1 = SYSCALL;
- *map2 = SYSCALL;
+ writew(SYSCALL, map1);
+ writew(SYSCALL, map2);
} else {
- *map1 = NOP2;
- *map2 = NOP2;
+ writew(NOP2, map1);
+ writew(NOP2, map2);
}
iounmap(map2);
out:
@@ -200,6 +244,43 @@ static ctl_table kernel_root_table2[] = {
#endif
+static void __cpuinit write_rdtscp_cb(void *info)
+{
+ write_rdtscp_aux((unsigned long)info);
+}
+
+void __cpuinit vsyscall_set_cpu(int cpu)
+{
+ unsigned long *d;
+ unsigned long node = 0;
+#ifdef CONFIG_NUMA
+ node = cpu_to_node[cpu];
+#endif
+ if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) {
+ void *info = (void *)((node << 12) | cpu);
+ /* Can happen on preemptive kernel */
+ if (get_cpu() == cpu)
+ write_rdtscp_cb(info);
+#ifdef CONFIG_SMP
+ else {
+ /* the notifier is unfortunately not executed on the
+ target CPU */
+ smp_call_function_single(cpu,write_rdtscp_cb,info,0,1);
+ }
+#endif
+ put_cpu();
+ }
+
+ /* Store cpu number in limit so that it can be loaded quickly
+ in user space in vgetcpu.
+ 12 bits for the CPU and 8 bits for the node. */
+ d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+ *d = 0x0f40000000000ULL;
+ *d |= cpu;
+ *d |= (node & 0xf) << 12;
+ *d |= (node >> 4) << 48;
+}
+
static void __init map_vsyscall(void)
{
extern char __vsyscall_0;
@@ -214,6 +295,7 @@ static int __init vsyscall_init(void)
VSYSCALL_ADDR(__NR_vgettimeofday)));
BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
+ BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
map_vsyscall();
#ifdef CONFIG_SYSCTL
register_sysctl_table(kernel_root_table2, 0);
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 370952c4ff2..c3454af5e3a 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -29,6 +29,7 @@ EXPORT_SYMBOL(__put_user_8);
EXPORT_SYMBOL(copy_user_generic);
EXPORT_SYMBOL(copy_from_user);
EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(__copy_from_user_inatomic);
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(clear_page);
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index ccef6ae747a..b78d4170fce 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -9,4 +9,4 @@ obj-y := io.o iomap_copy.o
lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
usercopy.o getuser.o putuser.o \
thunk.o clear_page.o copy_page.o bitstr.o bitops.o
-lib-y += memcpy.o memmove.o memset.o copy_user.o
+lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o
diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S
index 1f81b79b796..9a10a78bb4a 100644
--- a/arch/x86_64/lib/clear_page.S
+++ b/arch/x86_64/lib/clear_page.S
@@ -1,10 +1,22 @@
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
/*
* Zero a page.
* rdi page
*/
- .globl clear_page
- .p2align 4
-clear_page:
+ ALIGN
+clear_page_c:
+ CFI_STARTPROC
+ movl $4096/8,%ecx
+ xorl %eax,%eax
+ rep stosq
+ ret
+ CFI_ENDPROC
+ENDPROC(clear_page)
+
+ENTRY(clear_page)
+ CFI_STARTPROC
xorl %eax,%eax
movl $4096/64,%ecx
.p2align 4
@@ -23,28 +35,25 @@ clear_page:
jnz .Lloop
nop
ret
-clear_page_end:
+ CFI_ENDPROC
+.Lclear_page_end:
+ENDPROC(clear_page)
/* Some CPUs run faster using the string instructions.
It is also a lot simpler. Use this when possible */
#include <asm/cpufeature.h>
+ .section .altinstr_replacement,"ax"
+1: .byte 0xeb /* jmp <disp8> */
+ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */
+2:
+ .previous
.section .altinstructions,"a"
.align 8
- .quad clear_page
- .quad clear_page_c
- .byte X86_FEATURE_REP_GOOD
- .byte clear_page_end-clear_page
- .byte clear_page_c_end-clear_page_c
- .previous
-
- .section .altinstr_replacement,"ax"
-clear_page_c:
- movl $4096/8,%ecx
- xorl %eax,%eax
- rep
- stosq
- ret
-clear_page_c_end:
+ .quad clear_page
+ .quad 1b
+ .byte X86_FEATURE_REP_GOOD
+ .byte .Lclear_page_end - clear_page
+ .byte 2b - 1b
.previous
diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S
index 8fa19d96a7e..0ebb03b60e7 100644
--- a/arch/x86_64/lib/copy_page.S
+++ b/arch/x86_64/lib/copy_page.S
@@ -1,17 +1,33 @@
/* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+ ALIGN
+copy_page_c:
+ CFI_STARTPROC
+ movl $4096/8,%ecx
+ rep movsq
+ ret
+ CFI_ENDPROC
+ENDPROC(copy_page_c)
+
/* Don't use streaming store because it's better when the target
ends up in cache. */
/* Could vary the prefetch distance based on SMP/UP */
- .globl copy_page
- .p2align 4
-copy_page:
+ENTRY(copy_page)
+ CFI_STARTPROC
subq $3*8,%rsp
+ CFI_ADJUST_CFA_OFFSET 3*8
movq %rbx,(%rsp)
+ CFI_REL_OFFSET rbx, 0
movq %r12,1*8(%rsp)
+ CFI_REL_OFFSET r12, 1*8
movq %r13,2*8(%rsp)
+ CFI_REL_OFFSET r13, 2*8
movl $(4096/64)-5,%ecx
.p2align 4
@@ -72,30 +88,33 @@ copy_page:
jnz .Loop2
movq (%rsp),%rbx
+ CFI_RESTORE rbx
movq 1*8(%rsp),%r12
+ CFI_RESTORE r12
movq 2*8(%rsp),%r13
+ CFI_RESTORE r13
addq $3*8,%rsp
+ CFI_ADJUST_CFA_OFFSET -3*8
ret
+.Lcopy_page_end:
+ CFI_ENDPROC
+ENDPROC(copy_page)
/* Some CPUs run faster using the string copy instructions.
It is also a lot simpler. Use this when possible */
#include <asm/cpufeature.h>
+ .section .altinstr_replacement,"ax"
+1: .byte 0xeb /* jmp <disp8> */
+ .byte (copy_page_c - copy_page) - (2f - 1b) /* offset */
+2:
+ .previous
.section .altinstructions,"a"
.align 8
- .quad copy_page
- .quad copy_page_c
- .byte X86_FEATURE_REP_GOOD
- .byte copy_page_c_end-copy_page_c
- .byte copy_page_c_end-copy_page_c
- .previous
-
- .section .altinstr_replacement,"ax"
-copy_page_c:
- movl $4096/8,%ecx
- rep
- movsq
- ret
-copy_page_c_end:
+ .quad copy_page
+ .quad 1b
+ .byte X86_FEATURE_REP_GOOD
+ .byte .Lcopy_page_end - copy_page
+ .byte 2b - 1b
.previous
diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
index f64569b83b5..70bebd31040 100644
--- a/arch/x86_64/lib/copy_user.S
+++ b/arch/x86_64/lib/copy_user.S
@@ -4,56 +4,78 @@
* Functions to copy from and to user space.
*/
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
#define FIX_ALIGNMENT 1
- #include <asm/current.h>
- #include <asm/asm-offsets.h>
- #include <asm/thread_info.h>
- #include <asm/cpufeature.h>
+#include <asm/current.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpufeature.h>
-/* Standard copy_to_user with segment limit checking */
- .globl copy_to_user
- .p2align 4
-copy_to_user:
- GET_THREAD_INFO(%rax)
- movq %rdi,%rcx
- addq %rdx,%rcx
- jc bad_to_user
- cmpq threadinfo_addr_limit(%rax),%rcx
- jae bad_to_user
-2:
+ .macro ALTERNATIVE_JUMP feature,orig,alt
+0:
.byte 0xe9 /* 32bit jump */
- .long .Lcug-1f
+ .long \orig-1f /* by default jump to orig */
1:
-
.section .altinstr_replacement,"ax"
-3: .byte 0xe9 /* replacement jmp with 8 bit immediate */
- .long copy_user_generic_c-1b /* offset */
+2: .byte 0xe9 /* near jump with 32bit immediate */
+ .long \alt-1b /* offset */ /* or alternatively to alt */
.previous
.section .altinstructions,"a"
.align 8
+ .quad 0b
.quad 2b
- .quad 3b
- .byte X86_FEATURE_REP_GOOD
+ .byte \feature /* when feature is set */
.byte 5
.byte 5
.previous
+ .endm
+
+/* Standard copy_to_user with segment limit checking */
+ENTRY(copy_to_user)
+ CFI_STARTPROC
+ GET_THREAD_INFO(%rax)
+ movq %rdi,%rcx
+ addq %rdx,%rcx
+ jc bad_to_user
+ cmpq threadinfo_addr_limit(%rax),%rcx
+ jae bad_to_user
+ xorl %eax,%eax /* clear zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+
+ENTRY(copy_user_generic)
+ CFI_STARTPROC
+ movl $1,%ecx /* set zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+
+ENTRY(__copy_from_user_inatomic)
+ CFI_STARTPROC
+ xorl %ecx,%ecx /* clear zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
/* Standard copy_from_user with segment limit checking */
- .globl copy_from_user
- .p2align 4
-copy_from_user:
+ENTRY(copy_from_user)
+ CFI_STARTPROC
GET_THREAD_INFO(%rax)
movq %rsi,%rcx
addq %rdx,%rcx
jc bad_from_user
cmpq threadinfo_addr_limit(%rax),%rcx
jae bad_from_user
- /* FALL THROUGH to copy_user_generic */
+ movl $1,%ecx /* set zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ENDPROC(copy_from_user)
.section .fixup,"ax"
/* must zero dest */
bad_from_user:
+ CFI_STARTPROC
movl %edx,%ecx
xorl %eax,%eax
rep
@@ -61,40 +83,32 @@ bad_from_user:
bad_to_user:
movl %edx,%eax
ret
+ CFI_ENDPROC
+END(bad_from_user)
.previous
/*
- * copy_user_generic - memory copy with exception handling.
+ * copy_user_generic_unrolled - memory copy with exception handling.
+ * This version is for CPUs like P4 that don't have efficient micro code for rep movsq
*
* Input:
* rdi destination
* rsi source
* rdx count
+ * ecx zero flag -- if true zero destination on error
*
* Output:
* eax uncopied bytes or 0 if successful.
*/
- .globl copy_user_generic
- .p2align 4
-copy_user_generic:
- .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */
- .byte 0x66,0x90
-1:
- .section .altinstr_replacement,"ax"
-2: .byte 0xe9 /* near jump with 32bit immediate */
- .long copy_user_generic_c-1b /* offset */
- .previous
- .section .altinstructions,"a"
- .align 8
- .quad copy_user_generic
- .quad 2b
- .byte X86_FEATURE_REP_GOOD
- .byte 5
- .byte 5
- .previous
-.Lcug:
+ENTRY(copy_user_generic_unrolled)
+ CFI_STARTPROC
pushq %rbx
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbx, 0
+ pushq %rcx
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rcx, 0
xorl %eax,%eax /*zero for the exception handler */
#ifdef FIX_ALIGNMENT
@@ -168,9 +182,16 @@ copy_user_generic:
decl %ecx
jnz .Lloop_1
+ CFI_REMEMBER_STATE
.Lende:
+ popq %rcx
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_RESTORE rcx
popq %rbx
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_RESTORE rbx
ret
+ CFI_RESTORE_STATE
#ifdef FIX_ALIGNMENT
/* align destination */
@@ -252,6 +273,8 @@ copy_user_generic:
addl %ecx,%edx
/* edx: bytes to zero, rdi: dest, eax:zero */
.Lzero_rest:
+ cmpl $0,(%rsp)
+ jz .Le_zero
movq %rdx,%rcx
.Le_byte:
xorl %eax,%eax
@@ -261,6 +284,9 @@ copy_user_generic:
.Le_zero:
movq %rdx,%rax
jmp .Lende
+ CFI_ENDPROC
+ENDPROC(copy_user_generic)
+
/* Some CPUs run faster using the string copy instructions.
This is also a lot simpler. Use them when possible.
@@ -270,6 +296,7 @@ copy_user_generic:
/* rdi destination
* rsi source
* rdx count
+ * ecx zero flag
*
* Output:
* eax uncopied bytes or 0 if successfull.
@@ -280,22 +307,48 @@ copy_user_generic:
* And more would be dangerous because both Intel and AMD have
* errata with rep movsq > 4GB. If someone feels the need to fix
* this please consider this.
- */
-copy_user_generic_c:
+ */
+ENTRY(copy_user_generic_string)
+ CFI_STARTPROC
+ movl %ecx,%r8d /* save zero flag */
movl %edx,%ecx
shrl $3,%ecx
andl $7,%edx
+ jz 10f
1: rep
movsq
movl %edx,%ecx
2: rep
movsb
-4: movl %ecx,%eax
+9: movl %ecx,%eax
ret
-3: lea (%rdx,%rcx,8),%rax
+
+ /* multiple of 8 byte */
+10: rep
+ movsq
+ xor %eax,%eax
ret
+ /* exception handling */
+3: lea (%rdx,%rcx,8),%rax /* exception on quad loop */
+ jmp 6f
+5: movl %ecx,%eax /* exception on byte loop */
+ /* eax: left over bytes */
+6: testl %r8d,%r8d /* zero flag set? */
+ jz 7f
+ movl %eax,%ecx /* initialize x86 loop counter */
+ push %rax
+ xorl %eax,%eax
+8: rep
+ stosb /* zero the rest */
+11: pop %rax
+7: ret
+ CFI_ENDPROC
+END(copy_user_generic_c)
+
.section __ex_table,"a"
.quad 1b,3b
- .quad 2b,4b
+ .quad 2b,5b
+ .quad 8b,11b
+ .quad 10b,3b
.previous
diff --git a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S
index 72fd55ee896..f0dba36578e 100644
--- a/arch/x86_64/lib/csum-copy.S
+++ b/arch/x86_64/lib/csum-copy.S
@@ -5,8 +5,9 @@
* License. See the file COPYING in the main directory of this archive
* for more details. No warranty for anything given at all.
*/
- #include <linux/linkage.h>
- #include <asm/errno.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/errno.h>
/*
* Checksum copy with exception handling.
@@ -53,19 +54,24 @@
.endm
- .globl csum_partial_copy_generic
- .p2align 4
-csum_partial_copy_generic:
+ENTRY(csum_partial_copy_generic)
+ CFI_STARTPROC
cmpl $3*64,%edx
jle .Lignore
.Lignore:
subq $7*8,%rsp
+ CFI_ADJUST_CFA_OFFSET 7*8
movq %rbx,2*8(%rsp)
+ CFI_REL_OFFSET rbx, 2*8
movq %r12,3*8(%rsp)
+ CFI_REL_OFFSET r12, 3*8
movq %r14,4*8(%rsp)
+ CFI_REL_OFFSET r14, 4*8
movq %r13,5*8(%rsp)
+ CFI_REL_OFFSET r13, 5*8
movq %rbp,6*8(%rsp)
+ CFI_REL_OFFSET rbp, 6*8
movq %r8,(%rsp)
movq %r9,1*8(%rsp)
@@ -208,14 +214,22 @@ csum_partial_copy_generic:
addl %ebx,%eax
adcl %r9d,%eax /* carry */
+ CFI_REMEMBER_STATE
.Lende:
movq 2*8(%rsp),%rbx
+ CFI_RESTORE rbx
movq 3*8(%rsp),%r12
+ CFI_RESTORE r12
movq 4*8(%rsp),%r14
+ CFI_RESTORE r14
movq 5*8(%rsp),%r13
+ CFI_RESTORE r13
movq 6*8(%rsp),%rbp
+ CFI_RESTORE rbp
addq $7*8,%rsp
+ CFI_ADJUST_CFA_OFFSET -7*8
ret
+ CFI_RESTORE_STATE
/* Exception handlers. Very simple, zeroing is done in the wrappers */
.Lbad_source:
@@ -231,3 +245,5 @@ csum_partial_copy_generic:
jz .Lende
movl $-EFAULT,(%rax)
jmp .Lende
+ CFI_ENDPROC
+ENDPROC(csum_partial_copy_generic)
diff --git a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
index 3844d5e885a..5448876261f 100644
--- a/arch/x86_64/lib/getuser.S
+++ b/arch/x86_64/lib/getuser.S
@@ -27,25 +27,26 @@
*/
#include <linux/linkage.h>
+#include <asm/dwarf2.h>
#include <asm/page.h>
#include <asm/errno.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
.text
- .p2align 4
-.globl __get_user_1
-__get_user_1:
+ENTRY(__get_user_1)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
cmpq threadinfo_addr_limit(%r8),%rcx
jae bad_get_user
1: movzb (%rcx),%edx
xorl %eax,%eax
ret
+ CFI_ENDPROC
+ENDPROC(__get_user_1)
- .p2align 4
-.globl __get_user_2
-__get_user_2:
+ENTRY(__get_user_2)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $1,%rcx
jc 20f
@@ -57,10 +58,11 @@ __get_user_2:
ret
20: decq %rcx
jmp bad_get_user
+ CFI_ENDPROC
+ENDPROC(__get_user_2)
- .p2align 4
-.globl __get_user_4
-__get_user_4:
+ENTRY(__get_user_4)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $3,%rcx
jc 30f
@@ -72,10 +74,11 @@ __get_user_4:
ret
30: subq $3,%rcx
jmp bad_get_user
+ CFI_ENDPROC
+ENDPROC(__get_user_4)
- .p2align 4
-.globl __get_user_8
-__get_user_8:
+ENTRY(__get_user_8)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $7,%rcx
jc 40f
@@ -87,11 +90,16 @@ __get_user_8:
ret
40: subq $7,%rcx
jmp bad_get_user
+ CFI_ENDPROC
+ENDPROC(__get_user_8)
bad_get_user:
+ CFI_STARTPROC
xorl %edx,%edx
movq $(-EFAULT),%rax
ret
+ CFI_ENDPROC
+END(bad_get_user)
.section __ex_table,"a"
.quad 1b,bad_get_user
diff --git a/arch/x86_64/lib/iomap_copy.S b/arch/x86_64/lib/iomap_copy.S
index 8bbade5fea0..05a95e713da 100644
--- a/arch/x86_64/lib/iomap_copy.S
+++ b/arch/x86_64/lib/iomap_copy.S
@@ -15,12 +15,16 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
/*
* override generic version in lib/iomap_copy.c
*/
- .globl __iowrite32_copy
- .p2align 4
-__iowrite32_copy:
+ENTRY(__iowrite32_copy)
+ CFI_STARTPROC
movl %edx,%ecx
rep movsd
ret
+ CFI_ENDPROC
+ENDPROC(__iowrite32_copy)
diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S
index 5554948b555..967b22fa7d0 100644
--- a/arch/x86_64/lib/memcpy.S
+++ b/arch/x86_64/lib/memcpy.S
@@ -1,6 +1,10 @@
/* Copyright 2002 Andi Kleen */
- #include <asm/cpufeature.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
+
/*
* memcpy - Copy a memory block.
*
@@ -13,12 +17,26 @@
* rax original destination
*/
- .globl __memcpy
- .globl memcpy
- .p2align 4
-__memcpy:
-memcpy:
+ ALIGN
+memcpy_c:
+ CFI_STARTPROC
+ movq %rdi,%rax
+ movl %edx,%ecx
+ shrl $3,%ecx
+ andl $7,%edx
+ rep movsq
+ movl %edx,%ecx
+ rep movsb
+ ret
+ CFI_ENDPROC
+ENDPROC(memcpy_c)
+
+ENTRY(__memcpy)
+ENTRY(memcpy)
+ CFI_STARTPROC
pushq %rbx
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbx, 0
movq %rdi,%rax
movl %edx,%ecx
@@ -86,36 +104,27 @@ memcpy:
.Lende:
popq %rbx
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_RESTORE rbx
ret
.Lfinal:
+ CFI_ENDPROC
+ENDPROC(memcpy)
+ENDPROC(__memcpy)
/* Some CPUs run faster using the string copy instructions.
It is also a lot simpler. Use this when possible */
+ .section .altinstr_replacement,"ax"
+1: .byte 0xeb /* jmp <disp8> */
+ .byte (memcpy_c - memcpy) - (2f - 1b) /* offset */
+2:
+ .previous
.section .altinstructions,"a"
.align 8
- .quad memcpy
- .quad memcpy_c
- .byte X86_FEATURE_REP_GOOD
- .byte .Lfinal-memcpy
- .byte memcpy_c_end-memcpy_c
- .previous
-
- .section .altinstr_replacement,"ax"
- /* rdi destination
- * rsi source
- * rdx count
- */
-memcpy_c:
- movq %rdi,%rax
- movl %edx,%ecx
- shrl $3,%ecx
- andl $7,%edx
- rep
- movsq
- movl %edx,%ecx
- rep
- movsb
- ret
-memcpy_c_end:
+ .quad memcpy
+ .quad 1b
+ .byte X86_FEATURE_REP_GOOD
+ .byte .Lfinal - memcpy
+ .byte 2b - 1b
.previous
diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S
index ad397f2c7de..09ed1f6b0ea 100644
--- a/arch/x86_64/lib/memset.S
+++ b/arch/x86_64/lib/memset.S
@@ -1,4 +1,9 @@
/* Copyright 2002 Andi Kleen, SuSE Labs */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
/*
* ISO C memset - set a memory block to a byte value.
*
@@ -8,11 +13,29 @@
*
* rax original destination
*/
- .globl __memset
- .globl memset
- .p2align 4
-memset:
-__memset:
+ ALIGN
+memset_c:
+ CFI_STARTPROC
+ movq %rdi,%r9
+ movl %edx,%r8d
+ andl $7,%r8d
+ movl %edx,%ecx
+ shrl $3,%ecx
+ /* expand byte value */
+ movzbl %sil,%esi
+ movabs $0x0101010101010101,%rax
+ mulq %rsi /* with rax, clobbers rdx */
+ rep stosq
+ movl %r8d,%ecx
+ rep stosb
+ movq %r9,%rax
+ ret
+ CFI_ENDPROC
+ENDPROC(memset_c)
+
+ENTRY(memset)
+ENTRY(__memset)
+ CFI_STARTPROC
movq %rdi,%r10
movq %rdx,%r11
@@ -25,6 +48,7 @@ __memset:
movl %edi,%r9d
andl $7,%r9d
jnz .Lbad_alignment
+ CFI_REMEMBER_STATE
.Lafter_bad_alignment:
movl %r11d,%ecx
@@ -75,6 +99,7 @@ __memset:
movq %r10,%rax
ret
+ CFI_RESTORE_STATE
.Lbad_alignment:
cmpq $7,%r11
jbe .Lhandle_7
@@ -84,42 +109,26 @@ __memset:
addq %r8,%rdi
subq %r8,%r11
jmp .Lafter_bad_alignment
+.Lfinal:
+ CFI_ENDPROC
+ENDPROC(memset)
+ENDPROC(__memset)
/* Some CPUs run faster using the string instructions.
It is also a lot simpler. Use this when possible */
#include <asm/cpufeature.h>
+ .section .altinstr_replacement,"ax"
+1: .byte 0xeb /* jmp <disp8> */
+ .byte (memset_c - memset) - (2f - 1b) /* offset */
+2:
+ .previous
.section .altinstructions,"a"
.align 8
- .quad memset
- .quad memset_c
- .byte X86_FEATURE_REP_GOOD
- .byte memset_c_end-memset_c
- .byte memset_c_end-memset_c
- .previous
-
- .section .altinstr_replacement,"ax"
- /* rdi destination
- * rsi value
- * rdx count
- */
-memset_c:
- movq %rdi,%r9
- movl %edx,%r8d
- andl $7,%r8d
- movl %edx,%ecx
- shrl $3,%ecx
- /* expand byte value */
- movzbl %sil,%esi
- movabs $0x0101010101010101,%rax
- mulq %rsi /* with rax, clobbers rdx */
- rep
- stosq
- movl %r8d,%ecx
- rep
- stosb
- movq %r9,%rax
- ret
-memset_c_end:
+ .quad memset
+ .quad 1b
+ .byte X86_FEATURE_REP_GOOD
+ .byte .Lfinal - memset
+ .byte 2b - 1b
.previous
diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S
index 7f5593974e2..4989f5a8fa9 100644
--- a/arch/x86_64/lib/putuser.S
+++ b/arch/x86_64/lib/putuser.S
@@ -25,25 +25,26 @@
*/
#include <linux/linkage.h>
+#include <asm/dwarf2.h>
#include <asm/page.h>
#include <asm/errno.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
.text
- .p2align 4
-.globl __put_user_1
-__put_user_1:
+ENTRY(__put_user_1)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
cmpq threadinfo_addr_limit(%r8),%rcx
jae bad_put_user
1: movb %dl,(%rcx)
xorl %eax,%eax
ret
+ CFI_ENDPROC
+ENDPROC(__put_user_1)
- .p2align 4
-.globl __put_user_2
-__put_user_2:
+ENTRY(__put_user_2)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $1,%rcx
jc 20f
@@ -55,10 +56,11 @@ __put_user_2:
ret
20: decq %rcx
jmp bad_put_user
+ CFI_ENDPROC
+ENDPROC(__put_user_2)
- .p2align 4
-.globl __put_user_4
-__put_user_4:
+ENTRY(__put_user_4)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $3,%rcx
jc 30f
@@ -70,10 +72,11 @@ __put_user_4:
ret
30: subq $3,%rcx
jmp bad_put_user
+ CFI_ENDPROC
+ENDPROC(__put_user_4)
- .p2align 4
-.globl __put_user_8
-__put_user_8:
+ENTRY(__put_user_8)
+ CFI_STARTPROC
GET_THREAD_INFO(%r8)
addq $7,%rcx
jc 40f
@@ -85,10 +88,15 @@ __put_user_8:
ret
40: subq $7,%rcx
jmp bad_put_user
+ CFI_ENDPROC
+ENDPROC(__put_user_8)
bad_put_user:
+ CFI_STARTPROC
movq $(-EFAULT),%rax
ret
+ CFI_ENDPROC
+END(bad_put_user)
.section __ex_table,"a"
.quad 1b,bad_put_user
diff --git a/arch/x86_64/lib/rwlock.S b/arch/x86_64/lib/rwlock.S
new file mode 100644
index 00000000000..0cde1f80731
--- /dev/null
+++ b/arch/x86_64/lib/rwlock.S
@@ -0,0 +1,38 @@
+/* Slow paths of read/write spinlocks. */
+
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.i>
+#include <asm/dwarf2.h>
+
+/* rdi: pointer to rwlock_t */
+ENTRY(__write_lock_failed)
+ CFI_STARTPROC
+ LOCK_PREFIX
+ addl $RW_LOCK_BIAS,(%rdi)
+1: rep
+ nop
+ cmpl $RW_LOCK_BIAS,(%rdi)
+ jne 1b
+ LOCK_PREFIX
+ subl $RW_LOCK_BIAS,(%rdi)
+ jnz __write_lock_failed
+ ret
+ CFI_ENDPROC
+END(__write_lock_failed)
+
+/* rdi: pointer to rwlock_t */
+ENTRY(__read_lock_failed)
+ CFI_STARTPROC
+ LOCK_PREFIX
+ incl (%rdi)
+1: rep
+ nop
+ cmpl $1,(%rdi)
+ js 1b
+ LOCK_PREFIX
+ decl (%rdi)
+ js __read_lock_failed
+ ret
+ CFI_ENDPROC
+END(__read_lock_failed)
diff --git a/arch/x86_64/lib/thunk.S b/arch/x86_64/lib/thunk.S
index 332ea5dff91..0025535cac8 100644
--- a/arch/x86_64/lib/thunk.S
+++ b/arch/x86_64/lib/thunk.S
@@ -1,10 +1,9 @@
- /*
- * Save registers before calling assembly functions. This avoids
- * disturbance of register allocation in some inline assembly constructs.
- * Copyright 2001,2002 by Andi Kleen, SuSE Labs.
- * Subject to the GNU public license, v.2. No warranty of any kind.
- * $Id: thunk.S,v 1.2 2002/03/13 20:06:58 ak Exp $
- */
+/*
+ * Save registers before calling assembly functions. This avoids
+ * disturbance of register allocation in some inline assembly constructs.
+ * Copyright 2001,2002 by Andi Kleen, SuSE Labs.
+ * Subject to the GNU public license, v.2. No warranty of any kind.
+ */
#include <linux/config.h>
#include <linux/linkage.h>
@@ -67,33 +66,3 @@ restore_norax:
RESTORE_ARGS 1
ret
CFI_ENDPROC
-
-#ifdef CONFIG_SMP
-/* Support for read/write spinlocks. */
- .text
-/* rax: pointer to rwlock_t */
-ENTRY(__write_lock_failed)
- lock
- addl $RW_LOCK_BIAS,(%rax)
-1: rep
- nop
- cmpl $RW_LOCK_BIAS,(%rax)
- jne 1b
- lock
- subl $RW_LOCK_BIAS,(%rax)
- jnz __write_lock_failed
- ret
-
-/* rax: pointer to rwlock_t */
-ENTRY(__read_lock_failed)
- lock
- incl (%rax)
-1: rep
- nop
- cmpl $1,(%rax)
- js 1b
- lock
- decl (%rax)
- js __read_lock_failed
- ret
-#endif
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index ac8ea66ccb9..1a17b0733ab 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -40,8 +40,7 @@
#define PF_RSVD (1<<3)
#define PF_INSTR (1<<4)
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
/* Hook to register for page fault notifications */
int register_page_fault_notifier(struct notifier_block *nb)
@@ -49,11 +48,13 @@ int register_page_fault_notifier(struct notifier_block *nb)
vmalloc_sync_all();
return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}
+EXPORT_SYMBOL_GPL(register_page_fault_notifier);
int unregister_page_fault_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
}
+EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
static inline int notify_page_fault(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
@@ -67,13 +68,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
};
return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
}
-#else
-static inline int notify_page_fault(enum die_val val, const char *str,
- struct pt_regs *regs, long err, int trap, int sig)
-{
- return NOTIFY_DONE;
-}
-#endif
void bust_spinlocks(int yes)
{
@@ -102,7 +96,7 @@ void bust_spinlocks(int yes)
static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
unsigned long error_code)
{
- unsigned char *instr;
+ unsigned char __user *instr;
int scan_more = 1;
int prefetch = 0;
unsigned char *max_instr;
@@ -111,7 +105,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
if (error_code & PF_INSTR)
return 0;
- instr = (unsigned char *)convert_rip_to_linear(current, regs);
+ instr = (unsigned char __user *)convert_rip_to_linear(current, regs);
max_instr = instr + 15;
if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
@@ -122,7 +116,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
unsigned char instr_hi;
unsigned char instr_lo;
- if (__get_user(opcode, instr))
+ if (__get_user(opcode, (char __user *)instr))
break;
instr_hi = opcode & 0xf0;
@@ -160,7 +154,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
case 0x00:
/* Prefetch instruction is 0x0F0D or 0x0F18 */
scan_more = 0;
- if (__get_user(opcode, instr))
+ if (__get_user(opcode, (char __user *)instr))
break;
prefetch = (instr_lo == 0xF) &&
(opcode == 0x0D || opcode == 0x18);
@@ -176,7 +170,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
static int bad_address(void *p)
{
unsigned long dummy;
- return __get_user(dummy, (unsigned long *)p);
+ return __get_user(dummy, (unsigned long __user *)p);
}
void dump_pagetable(unsigned long address)
@@ -299,7 +293,7 @@ static int vmalloc_fault(unsigned long address)
if (pgd_none(*pgd))
set_pgd(pgd, *pgd_ref);
else
- BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
+ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
/* Below here mismatches are bugs because these lower tables
are shared */
@@ -308,7 +302,7 @@ static int vmalloc_fault(unsigned long address)
pud_ref = pud_offset(pgd_ref, address);
if (pud_none(*pud_ref))
return -1;
- if (pud_none(*pud) || pud_page(*pud) != pud_page(*pud_ref))
+ if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
BUG();
pmd = pmd_offset(pud, address);
pmd_ref = pmd_offset(pud_ref, address);
@@ -641,7 +635,7 @@ void vmalloc_sync_all(void)
if (pgd_none(*pgd))
set_pgd(pgd, *pgd_ref);
else
- BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
+ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
}
spin_unlock(&pgd_lock);
set_bit(pgd_index(address), insync);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index d14fb2dfbfc..3e16fe08150 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -229,7 +229,6 @@ __init void *early_ioremap(unsigned long addr, unsigned long size)
/* actually usually some more */
if (size >= LARGE_PAGE_SIZE) {
- printk("SMBIOS area too long %lu\n", size);
return NULL;
}
set_pmd(temp_mappings[0].pmd, __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
@@ -250,12 +249,13 @@ __init void early_iounmap(void *addr, unsigned long size)
}
static void __meminit
-phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
+phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
{
- int i;
+ int i = pmd_index(address);
- for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
+ for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
unsigned long entry;
+ pmd_t *pmd = pmd_page + pmd_index(address);
if (address >= end) {
if (!after_bootmem)
@@ -263,6 +263,10 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
set_pmd(pmd, __pmd(0));
break;
}
+
+ if (pmd_val(*pmd))
+ continue;
+
entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
entry &= __supported_pte_mask;
set_pmd(pmd, __pmd(entry));
@@ -272,45 +276,41 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
static void __meminit
phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
{
- pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
-
- if (pmd_none(*pmd)) {
- spin_lock(&init_mm.page_table_lock);
- phys_pmd_init(pmd, address, end);
- spin_unlock(&init_mm.page_table_lock);
- __flush_tlb_all();
- }
+ pmd_t *pmd = pmd_offset(pud,0);
+ spin_lock(&init_mm.page_table_lock);
+ phys_pmd_init(pmd, address, end);
+ spin_unlock(&init_mm.page_table_lock);
+ __flush_tlb_all();
}
-static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
{
- long i = pud_index(address);
+ int i = pud_index(addr);
- pud = pud + i;
- if (after_bootmem && pud_val(*pud)) {
- phys_pmd_update(pud, address, end);
- return;
- }
-
- for (; i < PTRS_PER_PUD; pud++, i++) {
+ for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE ) {
int map;
- unsigned long paddr, pmd_phys;
+ unsigned long pmd_phys;
+ pud_t *pud = pud_page + pud_index(addr);
pmd_t *pmd;
- paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
- if (paddr >= end)
+ if (addr >= end)
break;
- if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) {
+ if (!after_bootmem && !e820_any_mapped(addr,addr+PUD_SIZE,0)) {
set_pud(pud, __pud(0));
continue;
}
+ if (pud_val(*pud)) {
+ phys_pmd_update(pud, addr, end);
+ continue;
+ }
+
pmd = alloc_low_page(&map, &pmd_phys);
spin_lock(&init_mm.page_table_lock);
set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
- phys_pmd_init(pmd, paddr, end);
+ phys_pmd_init(pmd, addr, end);
spin_unlock(&init_mm.page_table_lock);
unmap_low_page(map);
}
@@ -403,69 +403,15 @@ void __cpuinit zap_low_mappings(int cpu)
__flush_tlb_all();
}
-/* Compute zone sizes for the DMA and DMA32 zones in a node. */
-__init void
-size_zones(unsigned long *z, unsigned long *h,
- unsigned long start_pfn, unsigned long end_pfn)
-{
- int i;
- unsigned long w;
-
- for (i = 0; i < MAX_NR_ZONES; i++)
- z[i] = 0;
-
- if (start_pfn < MAX_DMA_PFN)
- z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
- if (start_pfn < MAX_DMA32_PFN) {
- unsigned long dma32_pfn = MAX_DMA32_PFN;
- if (dma32_pfn > end_pfn)
- dma32_pfn = end_pfn;
- z[ZONE_DMA32] = dma32_pfn - start_pfn;
- }
- z[ZONE_NORMAL] = end_pfn - start_pfn;
-
- /* Remove lower zones from higher ones. */
- w = 0;
- for (i = 0; i < MAX_NR_ZONES; i++) {
- if (z[i])
- z[i] -= w;
- w += z[i];
- }
-
- /* Compute holes */
- w = start_pfn;
- for (i = 0; i < MAX_NR_ZONES; i++) {
- unsigned long s = w;
- w += z[i];
- h[i] = e820_hole_size(s, w);
- }
-
- /* Add the space pace needed for mem_map to the holes too. */
- for (i = 0; i < MAX_NR_ZONES; i++)
- h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
-
- /* The 16MB DMA zone has the kernel and other misc mappings.
- Account them too */
- if (h[ZONE_DMA]) {
- h[ZONE_DMA] += dma_reserve;
- if (h[ZONE_DMA] >= z[ZONE_DMA]) {
- printk(KERN_WARNING
- "Kernel too large and filling up ZONE_DMA?\n");
- h[ZONE_DMA] = z[ZONE_DMA];
- }
- }
-}
-
#ifndef CONFIG_NUMA
void __init paging_init(void)
{
- unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
-
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = {MAX_DMA_PFN,
+ MAX_DMA32_PFN,
+ end_pfn};
memory_present(0, 0, end_pfn);
sparse_init();
- size_zones(zones, holes, 0, end_pfn);
- free_area_init_node(0, NODE_DATA(0), zones,
- __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
+ free_area_init_nodes(max_zone_pfns);
}
#endif
@@ -536,7 +482,7 @@ int memory_add_physaddr_to_nid(u64 start)
int arch_add_memory(int nid, u64 start, u64 size)
{
struct pglist_data *pgdat = NODE_DATA(nid);
- struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
+ struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
int ret;
@@ -597,12 +543,6 @@ void __init mem_init(void)
pci_iommu_alloc();
- /* How many end-of-memory variables you have, grandma! */
- max_low_pfn = end_pfn;
- max_pfn = end_pfn;
- num_physpages = end_pfn;
- high_memory = (void *) __va(end_pfn * PAGE_SIZE);
-
/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);
@@ -614,7 +554,8 @@ void __init mem_init(void)
#else
totalram_pages = free_all_bootmem();
#endif
- reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
+ reservedpages = end_pfn - totalram_pages -
+ absent_pages_in_range(0, end_pfn);
after_bootmem = 1;
@@ -714,8 +655,10 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
#else
reserve_bootmem(phys, len);
#endif
- if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
+ if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
dma_reserve += len / PAGE_SIZE;
+ set_dma_reserve(dma_reserve);
+ }
}
int kern_addr_valid(unsigned long addr)
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index 7c45c2d2b8b..b5b8dba28b4 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -54,6 +54,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes_clear(nodes_parsed);
+ if (!early_pci_allowed())
+ return -1;
+
nb = find_northbridge();
if (nb < 0)
return nb;
@@ -146,6 +149,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes[nodeid].start = base;
nodes[nodeid].end = limit;
+ e820_register_active_regions(nodeid,
+ nodes[nodeid].start >> PAGE_SHIFT,
+ nodes[nodeid].end >> PAGE_SHIFT);
prevbase = base;
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index b2fac14baac..829a008bd39 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -161,7 +161,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
bootmap_start >> PAGE_SHIFT,
start_pfn, end_pfn);
- e820_bootmem_free(NODE_DATA(nodeid), start, end);
+ free_bootmem_with_active_regions(nodeid, end);
reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size);
reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
@@ -175,13 +175,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
void __init setup_node_zones(int nodeid)
{
unsigned long start_pfn, end_pfn, memmapsize, limit;
- unsigned long zones[MAX_NR_ZONES];
- unsigned long holes[MAX_NR_ZONES];
start_pfn = node_start_pfn(nodeid);
end_pfn = node_end_pfn(nodeid);
- Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
+ Dprintk(KERN_INFO "Setting up memmap for node %d %lx-%lx\n",
nodeid, start_pfn, end_pfn);
/* Try to allocate mem_map at end to not fill up precious <4GB
@@ -195,10 +193,6 @@ void __init setup_node_zones(int nodeid)
round_down(limit - memmapsize, PAGE_SIZE),
limit);
#endif
-
- size_zones(zones, holes, start_pfn, end_pfn);
- free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
- start_pfn, holes);
}
void __init numa_init_array(void)
@@ -225,7 +219,7 @@ void __init numa_init_array(void)
int numa_fake __initdata = 0;
/* Numa emulation */
-static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
{
int i;
struct bootnode nodes[MAX_NUMNODES];
@@ -259,8 +253,11 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
return -1;
}
- for_each_online_node(i)
+ for_each_online_node(i) {
+ e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+ nodes[i].end >> PAGE_SHIFT);
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ }
numa_init_array();
return 0;
}
@@ -299,6 +296,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
for (i = 0; i < NR_CPUS; i++)
numa_set_node(i, 0);
node_to_cpumask[0] = cpumask_of_cpu(0);
+ e820_register_active_regions(0, start_pfn, end_pfn);
setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
}
@@ -340,17 +338,23 @@ static void __init arch_sparse_init(void)
void __init paging_init(void)
{
int i;
+ unsigned long max_zone_pfns[MAX_NR_ZONES] = { MAX_DMA_PFN,
+ MAX_DMA32_PFN,
+ end_pfn};
arch_sparse_init();
for_each_online_node(i) {
setup_node_zones(i);
}
+
+ free_area_init_nodes(max_zone_pfns);
}
-/* [numa=off] */
-__init int numa_setup(char *opt)
+static __init int numa_setup(char *opt)
{
+ if (!opt)
+ return -EINVAL;
if (!strncmp(opt,"off",3))
numa_off = 1;
#ifdef CONFIG_NUMA_EMU
@@ -366,9 +370,11 @@ __init int numa_setup(char *opt)
if (!strncmp(opt,"hotadd=", 7))
hotadd_percent = simple_strtoul(opt+7, NULL, 10);
#endif
- return 1;
+ return 0;
}
+early_param("numa", numa_setup);
+
/*
* Setup early cpu_to_node.
*
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index 2685b1f3671..3e231d762aa 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -108,8 +108,8 @@ static void revert_page(unsigned long address, pgprot_t ref_prot)
BUG_ON(pud_none(*pud));
pmd = pmd_offset(pud, address);
BUG_ON(pmd_val(*pmd) & _PAGE_PSE);
- pgprot_val(ref_prot) |= _PAGE_PSE;
large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
+ large_pte = pte_mkhuge(large_pte);
set_pte((pte_t *)pmd, large_pte);
}
@@ -119,32 +119,28 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
{
pte_t *kpte;
struct page *kpte_page;
- unsigned kpte_flags;
pgprot_t ref_prot2;
kpte = lookup_address(address);
if (!kpte) return 0;
kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
- kpte_flags = pte_val(*kpte);
if (pgprot_val(prot) != pgprot_val(ref_prot)) {
- if ((kpte_flags & _PAGE_PSE) == 0) {
+ if (!pte_huge(*kpte)) {
set_pte(kpte, pfn_pte(pfn, prot));
} else {
/*
* split_large_page will take the reference for this
* change_page_attr on the split page.
*/
-
struct page *split;
- ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE));
-
+ ref_prot2 = pte_pgprot(pte_clrhuge(*kpte));
split = split_large_page(address, prot, ref_prot2);
if (!split)
return -ENOMEM;
- set_pte(kpte,mk_pte(split, ref_prot2));
+ set_pte(kpte, mk_pte(split, ref_prot2));
kpte_page = split;
- }
+ }
page_private(kpte_page)++;
- } else if ((kpte_flags & _PAGE_PSE) == 0) {
+ } else if (!pte_huge(*kpte)) {
set_pte(kpte, pfn_pte(pfn, ref_prot));
BUG_ON(page_private(kpte_page) == 0);
page_private(kpte_page)--;
@@ -190,10 +186,12 @@ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
* lowmem */
if (__pa(address) < KERNEL_TEXT_SIZE) {
unsigned long addr2;
- pgprot_t prot2 = prot;
+ pgprot_t prot2;
addr2 = __START_KERNEL_map + __pa(address);
- pgprot_val(prot2) &= ~_PAGE_NX;
- err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC);
+ /* Make sure the kernel mappings stay executable */
+ prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
+ err = __change_page_attr(addr2, pfn, prot2,
+ PAGE_KERNEL_EXEC);
}
}
up_write(&init_mm.mmap_sem);
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 502fce65e96..f8c04d6935c 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -21,6 +21,8 @@
#include <asm/numa.h>
#include <asm/e820.h>
+int acpi_numa __initdata;
+
#if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
&& !defined(CONFIG_MEMORY_HOTPLUG)
@@ -91,6 +93,7 @@ static __init void bad_srat(void)
apicid_to_node[i] = NUMA_NO_NODE;
for (i = 0; i < MAX_NUMNODES; i++)
nodes_add[i].start = nodes[i].end = 0;
+ remove_all_active_ranges();
}
static __init inline int srat_disabled(void)
@@ -173,7 +176,7 @@ static int hotadd_enough_memory(struct bootnode *nd)
if (mem < 0)
return 0;
- allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+ allowed = (end_pfn - absent_pages_in_range(0, end_pfn)) * PAGE_SIZE;
allowed = (allowed / 100) * hotadd_percent;
if (allocated + mem > allowed) {
unsigned long range;
@@ -223,8 +226,10 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end)
}
/* This check might be a bit too strict, but I'm keeping it for now. */
- if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
- printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+ if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
+ printk(KERN_ERR
+ "SRAT: Hotplug area %lu -> %lu has existing memory\n",
+ s_pfn, e_pfn);
return -1;
}
@@ -317,6 +322,10 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
nd->start, nd->end);
+ e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
+ nd->end >> PAGE_SHIFT);
+ push_node_boundaries(node, nd->start >> PAGE_SHIFT,
+ nd->end >> PAGE_SHIFT);
#ifdef RESERVE_HOTADD
if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
@@ -341,13 +350,13 @@ static int nodes_cover_memory(void)
unsigned long s = nodes[i].start >> PAGE_SHIFT;
unsigned long e = nodes[i].end >> PAGE_SHIFT;
pxmram += e - s;
- pxmram -= e820_hole_size(s, e);
+ pxmram -= absent_pages_in_range(s, e);
pxmram -= nodes_add[i].end - nodes_add[i].start;
if ((long)pxmram < 0)
pxmram = 0;
}
- e820ram = end_pfn - e820_hole_size(0, end_pfn);
+ e820ram = end_pfn - absent_pages_in_range(0, end_pfn);
/* We seem to lose 3 pages somewhere. Allow a bit of slack. */
if ((long)(e820ram - pxmram) >= 1*1024*1024) {
printk(KERN_ERR
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index a3f6ad57017..1eb18f421ed 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -9,7 +9,7 @@ obj-y := i386.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o
obj-y += fixup.o init.o
obj-$(CONFIG_ACPI) += acpi.o
-obj-y += legacy.o irq.o common.o
+obj-y += legacy.o irq.o common.o early.o
# mmconfig has a 64bit special
obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
@@ -23,3 +23,4 @@ common-y += ../../i386/pci/common.o
fixup-y += ../../i386/pci/fixup.o
i386-y += ../../i386/pci/i386.o
init-y += ../../i386/pci/init.o
+early-y += ../../i386/pci/early.o
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 3c55c76c6fd..7732f4254d2 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -156,15 +156,45 @@ static __init void unreachable_devices(void)
addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
if (addr == NULL|| readl(addr) != val1) {
set_bit(i + 32*k, fallback_slots);
- printk(KERN_NOTICE
- "PCI: No mmconfig possible on device %x:%x\n",
- k, i);
+ printk(KERN_NOTICE "PCI: No mmconfig possible"
+ " on device %02x:%02x\n", k, i);
}
}
}
}
-void __init pci_mmcfg_init(void)
+static __init void pci_mmcfg_insert_resources(void)
+{
+#define PCI_MMCFG_RESOURCE_NAME_LEN 19
+ int i;
+ struct resource *res;
+ char *names;
+ unsigned num_buses;
+
+ res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
+ pci_mmcfg_config_num, GFP_KERNEL);
+
+ if (!res) {
+ printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
+ return;
+ }
+
+ names = (void *)&res[pci_mmcfg_config_num];
+ for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
+ num_buses = pci_mmcfg_config[i].end_bus_number -
+ pci_mmcfg_config[i].start_bus_number + 1;
+ res->name = names;
+ snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+ pci_mmcfg_config[i].pci_segment_group_number);
+ res->start = pci_mmcfg_config[i].base_address;
+ res->end = res->start + (num_buses << 20) - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ insert_resource(&iomem_resource, res);
+ names += PCI_MMCFG_RESOURCE_NAME_LEN;
+ }
+}
+
+void __init pci_mmcfg_init(int type)
{
int i;
@@ -177,7 +207,9 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ /* Only do this check when type 1 works. If it doesn't work
+ assume we run on a Mac and always use MCFG */
+ if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address,
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
E820_RESERVED)) {
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
@@ -186,7 +218,6 @@ void __init pci_mmcfg_init(void)
return;
}
- /* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
printk("PCI: Can not allocate memory for mmconfig structures\n");
@@ -205,6 +236,7 @@ void __init pci_mmcfg_init(void)
}
unreachable_devices();
+ pci_mmcfg_insert_resources();
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;