From aa7f905df59269b8e2d42c47c51c3ecf0435a3ad Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 22 Mar 2011 13:39:27 +1000 Subject: [PATCH] --- yaml --- r: 242498 b: refs/heads/master c: 66d857b08b8c3ed5c72c361f863cce77d2a978d7 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/ABI/testing/sysfs-fs-ext4 | 13 +- trunk/Documentation/filesystems/ext4.txt | 207 +-- trunk/MAINTAINERS | 5 - trunk/arch/m68k/Kconfig | 456 +------ trunk/arch/m68k/Kconfig.debug | 34 + trunk/arch/m68k/Kconfig.mmu | 417 ++++++ .../{m68knommu/Kconfig => m68k/Kconfig.nommu} | 94 -- trunk/arch/m68k/Makefile | 122 +- trunk/arch/m68k/Makefile_mm | 121 ++ .../{m68knommu/Makefile => m68k/Makefile_no} | 16 +- .../configs/m5208evb_defconfig | 2 + .../configs/m5249evb_defconfig | 2 + .../configs/m5272c3_defconfig | 2 + .../configs/m5275evb_defconfig | 2 + .../configs/m5307c3_defconfig | 2 + .../configs/m5407c3_defconfig | 2 + trunk/arch/m68k/kernel/Makefile | 18 +- trunk/arch/m68k/kernel/Makefile_mm | 17 + .../Makefile => m68k/kernel/Makefile_no} | 0 trunk/arch/m68k/kernel/asm-offsets.c | 101 +- trunk/arch/m68k/kernel/asm-offsets_mm.c | 100 ++ .../kernel/asm-offsets_no.c} | 0 trunk/arch/m68k/kernel/dma.c | 135 +- trunk/arch/m68k/kernel/dma_mm.c | 130 ++ .../kernel/dma.c => m68k/kernel/dma_no.c} | 0 trunk/arch/m68k/kernel/entry.S | 756 +---------- trunk/arch/m68k/kernel/entry_mm.S | 753 ++++++++++ .../kernel/entry.S => m68k/kernel/entry_no.S} | 0 .../{m68knommu => m68k}/kernel/init_task.c | 0 trunk/arch/{m68knommu => m68k}/kernel/irq.c | 0 trunk/arch/m68k/kernel/m68k_ksyms.c | 21 +- trunk/arch/m68k/kernel/m68k_ksyms_mm.c | 16 + .../kernel/m68k_ksyms_no.c} | 0 trunk/arch/m68k/kernel/module.c | 156 +-- trunk/arch/m68k/kernel/module_mm.c | 155 +++ .../module.c => m68k/kernel/module_no.c} | 0 trunk/arch/m68k/kernel/process.c | 355 +---- trunk/arch/m68k/kernel/process_mm.c | 354 +++++ .../process.c => m68k/kernel/process_no.c} | 0 trunk/arch/m68k/kernel/ptrace.c | 282 +--- trunk/arch/m68k/kernel/ptrace_mm.c | 277 ++++ .../ptrace.c => m68k/kernel/ptrace_no.c} | 0 trunk/arch/m68k/kernel/setup.c | 534 +------- trunk/arch/m68k/kernel/setup_mm.c | 533 ++++++++ .../kernel/setup.c => m68k/kernel/setup_no.c} | 0 trunk/arch/m68k/kernel/signal.c | 1018 +------------- trunk/arch/m68k/kernel/signal_mm.c | 1017 ++++++++++++++ .../signal.c => m68k/kernel/signal_no.c} | 0 trunk/arch/m68k/kernel/sys_m68k.c | 551 +------- trunk/arch/m68k/kernel/sys_m68k_mm.c | 546 ++++++++ .../sys_m68k.c => m68k/kernel/sys_m68k_no.c} | 0 .../{m68knommu => m68k}/kernel/syscalltable.S | 0 trunk/arch/m68k/kernel/time.c | 119 +- trunk/arch/m68k/kernel/time_mm.c | 114 ++ .../kernel/time.c => m68k/kernel/time_no.c} | 0 trunk/arch/m68k/kernel/traps.c | 1208 +---------------- trunk/arch/m68k/kernel/traps_mm.c | 1207 ++++++++++++++++ .../kernel/traps.c => m68k/kernel/traps_no.c} | 0 trunk/arch/m68k/kernel/vmlinux.lds.S | 11 +- trunk/arch/m68k/kernel/vmlinux.lds_mm.S | 10 + .../kernel/vmlinux.lds_no.S} | 0 trunk/arch/m68k/lib/Makefile | 11 +- trunk/arch/m68k/lib/Makefile_mm | 6 + .../lib/Makefile => m68k/lib/Makefile_no} | 0 trunk/arch/m68k/lib/checksum.c | 430 +----- trunk/arch/m68k/lib/checksum_mm.c | 425 ++++++ .../lib/checksum.c => m68k/lib/checksum_no.c} | 0 trunk/arch/{m68knommu => m68k}/lib/delay.c | 0 trunk/arch/{m68knommu => m68k}/lib/divsi3.S | 0 trunk/arch/{m68knommu => m68k}/lib/memcpy.c | 0 trunk/arch/{m68knommu => m68k}/lib/memmove.c | 0 trunk/arch/{m68knommu => m68k}/lib/memset.c | 0 trunk/arch/{m68knommu => m68k}/lib/modsi3.S | 0 trunk/arch/m68k/lib/muldi3.c | 68 +- .../lib/ashrdi3.c => m68k/lib/muldi3_mm.c} | 48 +- .../lib/muldi3.c => m68k/lib/muldi3_no.c} | 0 trunk/arch/{m68knommu => m68k}/lib/mulsi3.S | 0 trunk/arch/{m68knommu => m68k}/lib/udivsi3.S | 0 trunk/arch/{m68knommu => m68k}/lib/umodsi3.S | 0 trunk/arch/m68k/mm/Makefile | 13 +- trunk/arch/m68k/mm/Makefile_mm | 8 + .../mm/Makefile => m68k/mm/Makefile_no} | 0 trunk/arch/m68k/mm/init.c | 153 +-- trunk/arch/m68k/mm/init_mm.c | 150 ++ .../mm/init.c => m68k/mm/init_no.c} | 0 trunk/arch/m68k/mm/kmap.c | 368 +---- trunk/arch/m68k/mm/kmap_mm.c | 367 +++++ .../mm/kmap.c => m68k/mm/kmap_no.c} | 0 .../platform/5206/Makefile | 0 .../platform/5206/config.c | 0 .../{m68knommu => m68k}/platform/5206/gpio.c | 0 .../platform/5206e/Makefile | 0 .../platform/5206e/config.c | 0 .../{m68knommu => m68k}/platform/5206e/gpio.c | 0 .../platform/520x/Makefile | 0 .../platform/520x/config.c | 0 .../{m68knommu => m68k}/platform/520x/gpio.c | 0 .../platform/523x/Makefile | 0 .../platform/523x/config.c | 0 .../{m68knommu => m68k}/platform/523x/gpio.c | 0 .../platform/5249/Makefile | 0 .../platform/5249/config.c | 0 .../{m68knommu => m68k}/platform/5249/gpio.c | 0 .../{m68knommu => m68k}/platform/5249/intc2.c | 0 .../platform/5272/Makefile | 0 .../platform/5272/config.c | 0 .../{m68knommu => m68k}/platform/5272/gpio.c | 0 .../{m68knommu => m68k}/platform/5272/intc.c | 0 .../platform/527x/Makefile | 0 .../platform/527x/config.c | 0 .../{m68knommu => m68k}/platform/527x/gpio.c | 0 .../platform/528x/Makefile | 0 .../platform/528x/config.c | 0 .../{m68knommu => m68k}/platform/528x/gpio.c | 0 .../platform/5307/Makefile | 0 .../platform/5307/config.c | 0 .../{m68knommu => m68k}/platform/5307/gpio.c | 0 .../platform/5307/nettel.c | 0 .../platform/532x/Makefile | 0 .../platform/532x/config.c | 0 .../{m68knommu => m68k}/platform/532x/gpio.c | 0 .../platform/5407/Makefile | 0 .../platform/5407/config.c | 0 .../{m68knommu => m68k}/platform/5407/gpio.c | 0 .../platform/54xx/Makefile | 0 .../platform/54xx/config.c | 0 .../platform/54xx/firebee.c | 0 .../platform/68328/Makefile | 0 .../platform/68328/bootlogo.h | 0 .../platform/68328/bootlogo.pl | 0 .../platform/68328/config.c | 0 .../platform/68328/entry.S | 0 .../platform/68328/head-de2.S | 0 .../platform/68328/head-pilot.S | 0 .../platform/68328/head-ram.S | 0 .../platform/68328/head-rom.S | 0 .../{m68knommu => m68k}/platform/68328/ints.c | 0 .../platform/68328/romvec.S | 0 .../platform/68328/timers.c | 0 .../platform/68360/Makefile | 0 .../platform/68360/commproc.c | 0 .../platform/68360/config.c | 0 .../platform/68360/entry.S | 0 .../platform/68360/head-ram.S | 0 .../platform/68360/head-rom.S | 0 .../{m68knommu => m68k}/platform/68360/ints.c | 0 .../platform/68EZ328/Makefile | 0 .../platform/68EZ328/bootlogo.h | 0 .../platform/68EZ328/config.c | 0 .../platform/68VZ328/Makefile | 0 .../platform/68VZ328/config.c | 0 .../{m68knommu => m68k}/platform/Makefile | 0 .../platform/coldfire/Makefile | 0 .../platform/coldfire/cache.c | 0 .../platform/coldfire/clk.c | 0 .../platform/coldfire/dma.c | 0 .../platform/coldfire/dma_timer.c | 0 .../platform/coldfire/entry.S | 0 .../platform/coldfire/gpio.c | 0 .../platform/coldfire/head.S | 0 .../platform/coldfire/intc-2.c | 0 .../platform/coldfire/intc-simr.c | 0 .../platform/coldfire/intc.c | 0 .../platform/coldfire/pinmux.c | 0 .../platform/coldfire/pit.c | 0 .../platform/coldfire/sltimers.c | 0 .../platform/coldfire/timers.c | 0 .../platform/coldfire/vectors.c | 0 trunk/arch/m68knommu/Kconfig.debug | 35 - trunk/arch/m68knommu/defconfig | 74 - trunk/arch/m68knommu/kernel/.gitignore | 1 - trunk/arch/m68knommu/lib/ashldi3.c | 62 - trunk/arch/m68knommu/lib/lshrdi3.c | 62 - trunk/arch/mips/Kconfig | 4 - trunk/arch/mips/alchemy/common/irq.c | 98 +- trunk/arch/mips/alchemy/devboards/bcsr.c | 18 +- trunk/arch/mips/ar7/irq.c | 42 +- trunk/arch/mips/ath79/irq.c | 24 +- trunk/arch/mips/bcm63xx/irq.c | 77 +- trunk/arch/mips/dec/ioasic-irq.c | 60 +- trunk/arch/mips/dec/kn02-irq.c | 23 +- trunk/arch/mips/emma/markeins/irq.c | 67 +- trunk/arch/mips/include/asm/irq.h | 64 +- .../msp71xx/cpu-feature-overrides.h | 21 - .../asm/pmc-sierra/msp71xx/msp_gpio_macros.h | 343 ----- .../include/asm/pmc-sierra/msp71xx/msp_regs.h | 17 +- .../include/asm/pmc-sierra/msp71xx/msp_usb.h | 144 -- trunk/arch/mips/include/asm/spinlock.h | 22 +- trunk/arch/mips/include/asm/unistd.h | 24 +- trunk/arch/mips/jazz/irq.c | 14 +- trunk/arch/mips/jz4740/board-qi_lb60.c | 32 +- trunk/arch/mips/jz4740/gpio.c | 111 +- trunk/arch/mips/jz4740/irq.c | 32 +- trunk/arch/mips/kernel/i8259.c | 37 +- trunk/arch/mips/kernel/irq-gic.c | 43 +- trunk/arch/mips/kernel/irq-gt641xx.c | 26 +- trunk/arch/mips/kernel/irq-msc01.c | 51 +- trunk/arch/mips/kernel/irq-rm7000.c | 18 +- trunk/arch/mips/kernel/irq-rm9000.c | 49 +- trunk/arch/mips/kernel/irq.c | 49 +- trunk/arch/mips/kernel/irq_cpu.c | 46 +- trunk/arch/mips/kernel/irq_txx9.c | 28 +- trunk/arch/mips/kernel/scall32-o32.S | 4 - trunk/arch/mips/kernel/scall64-64.S | 4 - trunk/arch/mips/kernel/scall64-n32.S | 4 - trunk/arch/mips/kernel/scall64-o32.S | 4 - trunk/arch/mips/kernel/smtc.c | 13 +- trunk/arch/mips/lasat/interrupt.c | 16 +- trunk/arch/mips/loongson/common/bonito-irq.c | 16 +- trunk/arch/mips/mipssim/sim_smtc.c | 3 +- trunk/arch/mips/mti-malta/malta-smtc.c | 10 +- trunk/arch/mips/pmc-sierra/Kconfig | 15 - trunk/arch/mips/pmc-sierra/msp71xx/Makefile | 8 +- trunk/arch/mips/pmc-sierra/msp71xx/msp_eth.c | 187 --- trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c | 56 +- .../mips/pmc-sierra/msp71xx/msp_irq_cic.c | 239 ++-- .../mips/pmc-sierra/msp71xx/msp_irq_per.c | 135 -- .../mips/pmc-sierra/msp71xx/msp_irq_slp.c | 18 +- .../arch/mips/pmc-sierra/msp71xx/msp_setup.c | 10 - trunk/arch/mips/pmc-sierra/msp71xx/msp_smp.c | 77 -- trunk/arch/mips/pmc-sierra/msp71xx/msp_smtc.c | 105 -- trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c | 16 +- trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c | 239 +--- trunk/arch/mips/pnx833x/common/interrupts.c | 98 +- trunk/arch/mips/pnx8550/common/int.c | 18 +- trunk/arch/mips/powertv/asic/irq_asic.c | 13 +- trunk/arch/mips/rb532/irq.c | 32 +- trunk/arch/mips/sgi-ip22/ip22-int.c | 60 +- trunk/arch/mips/sgi-ip27/ip27-irq.c | 38 +- trunk/arch/mips/sgi-ip27/ip27-timer.c | 11 +- trunk/arch/mips/sgi-ip32/ip32-irq.c | 134 +- trunk/arch/mips/sibyte/bcm1480/irq.c | 55 +- trunk/arch/mips/sibyte/sb1250/irq.c | 53 +- trunk/arch/mips/sni/a20r.c | 23 +- trunk/arch/mips/sni/pcimt.c | 21 +- trunk/arch/mips/sni/pcit.c | 21 +- trunk/arch/mips/sni/rm200.c | 42 +- trunk/arch/mips/txx9/generic/irq_tx4939.c | 28 +- trunk/arch/mips/txx9/jmr3927/irq.c | 14 +- trunk/arch/mips/txx9/rbtx4927/irq.c | 58 +- trunk/arch/mips/txx9/rbtx4938/irq.c | 54 +- trunk/arch/mips/txx9/rbtx4939/irq.c | 14 +- trunk/arch/mips/vr41xx/common/icu.c | 72 +- trunk/arch/mips/vr41xx/common/irq.c | 19 +- trunk/arch/s390/include/asm/ccwdev.h | 4 + trunk/arch/s390/include/asm/ccwgroup.h | 4 + trunk/arch/s390/include/asm/cmpxchg.h | 225 --- trunk/arch/s390/include/asm/system.h | 196 ++- trunk/arch/s390/include/asm/unistd.h | 6 +- trunk/arch/s390/kernel/compat_wrapper.S | 27 - trunk/arch/s390/kernel/early.c | 22 +- trunk/arch/s390/kernel/setup.c | 88 +- trunk/arch/s390/kernel/syscalls.S | 4 - trunk/arch/s390/oprofile/Makefile | 3 +- trunk/arch/s390/oprofile/init.c | 15 +- trunk/arch/sparc/kernel/time_32.c | 4 - trunk/block/blk-core.c | 7 +- trunk/drivers/memstick/host/Kconfig | 12 - trunk/drivers/memstick/host/Makefile | 1 - trunk/drivers/memstick/host/r592.c | 908 ------------- trunk/drivers/memstick/host/r592.h | 175 --- trunk/drivers/s390/block/dasd_eckd.c | 6 +- trunk/drivers/s390/block/dasd_fba.c | 6 +- trunk/drivers/s390/char/con3215.c | 6 +- trunk/drivers/s390/char/raw3270.c | 6 +- trunk/drivers/s390/char/tape_34xx.c | 6 +- trunk/drivers/s390/char/tape_3590.c | 6 +- trunk/drivers/s390/char/vmur.c | 6 +- trunk/drivers/s390/cio/ccwgroup.c | 6 +- trunk/drivers/s390/cio/device.c | 11 +- trunk/drivers/s390/cio/device.h | 1 + trunk/drivers/s390/cio/qdio_main.c | 3 +- trunk/drivers/s390/net/claw.c | 12 +- trunk/drivers/s390/net/ctcm_main.c | 12 +- trunk/drivers/s390/net/lcs.c | 12 +- trunk/drivers/s390/net/qeth_core_main.c | 10 +- trunk/drivers/s390/scsi/zfcp_ccw.c | 6 +- trunk/fs/coda/sysctl.c | 9 - trunk/fs/ext4/balloc.c | 3 - trunk/fs/ext4/ext4_jbd2.h | 7 + trunk/fs/ext4/extents.c | 213 +-- trunk/fs/ext4/fsync.c | 14 +- trunk/fs/ext4/ialloc.c | 8 +- trunk/fs/ext4/inode.c | 410 +++--- trunk/fs/ext4/ioctl.c | 7 - trunk/fs/ext4/mballoc.c | 34 +- trunk/fs/ext4/mballoc.h | 2 +- trunk/fs/ext4/migrate.c | 10 +- trunk/fs/ext4/namei.c | 13 +- trunk/fs/ext4/page-io.c | 13 +- trunk/fs/ext4/resize.c | 12 +- trunk/fs/ext4/super.c | 48 +- trunk/fs/ext4/xattr.c | 4 +- trunk/fs/nfs/dir.c | 89 +- trunk/fs/nfs/file.c | 3 - trunk/fs/nfs/getroot.c | 4 - trunk/fs/nfs/inode.c | 10 +- trunk/fs/nfs/internal.h | 27 +- trunk/fs/nfs/namespace.c | 115 +- trunk/fs/nfs/nfs3proc.c | 2 +- trunk/fs/nfs/nfs4_fs.h | 5 +- trunk/fs/nfs/nfs4filelayout.c | 352 +---- trunk/fs/nfs/nfs4filelayout.h | 2 - trunk/fs/nfs/nfs4filelayoutdev.c | 178 +-- trunk/fs/nfs/nfs4proc.c | 302 +---- trunk/fs/nfs/nfs4xdr.c | 313 +---- trunk/fs/nfs/pagelist.c | 8 +- trunk/fs/nfs/pnfs.c | 142 -- trunk/fs/nfs/pnfs.h | 83 +- trunk/fs/nfs/proc.c | 2 +- trunk/fs/nfs/write.c | 214 +-- trunk/fs/nfs_common/nfsacl.c | 1 + trunk/include/linux/jbd2.h | 28 +- trunk/include/linux/journal-head.h | 7 - trunk/include/linux/nfs4.h | 2 - trunk/include/linux/nfs_fs.h | 10 - trunk/include/linux/nfs_page.h | 7 +- trunk/include/linux/nfs_xdr.h | 70 +- trunk/include/linux/sunrpc/gss_api.h | 3 - trunk/include/trace/events/ext4.h | 775 +++-------- trunk/include/trace/events/jbd2.h | 78 +- trunk/ipc/namespace.c | 2 +- trunk/net/sunrpc/auth_gss/gss_mech_switch.c | 38 - trunk/net/sunrpc/xprtsock.c | 2 - 325 files changed, 9406 insertions(+), 14006 deletions(-) create mode 100644 trunk/arch/m68k/Kconfig.mmu rename trunk/arch/{m68knommu/Kconfig => m68k/Kconfig.nommu} (93%) create mode 100644 trunk/arch/m68k/Makefile_mm rename trunk/arch/{m68knommu/Makefile => m68k/Makefile_no} (92%) rename trunk/arch/{m68knommu => m68k}/configs/m5208evb_defconfig (97%) rename trunk/arch/{m68knommu => m68k}/configs/m5249evb_defconfig (97%) rename trunk/arch/{m68knommu => m68k}/configs/m5272c3_defconfig (96%) rename trunk/arch/{m68knommu => m68k}/configs/m5275evb_defconfig (97%) rename trunk/arch/{m68knommu => m68k}/configs/m5307c3_defconfig (97%) rename trunk/arch/{m68knommu => m68k}/configs/m5407c3_defconfig (97%) create mode 100644 trunk/arch/m68k/kernel/Makefile_mm rename trunk/arch/{m68knommu/kernel/Makefile => m68k/kernel/Makefile_no} (100%) create mode 100644 trunk/arch/m68k/kernel/asm-offsets_mm.c rename trunk/arch/{m68knommu/kernel/asm-offsets.c => m68k/kernel/asm-offsets_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/dma_mm.c rename trunk/arch/{m68knommu/kernel/dma.c => m68k/kernel/dma_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/entry_mm.S rename trunk/arch/{m68knommu/kernel/entry.S => m68k/kernel/entry_no.S} (100%) rename trunk/arch/{m68knommu => m68k}/kernel/init_task.c (100%) rename trunk/arch/{m68knommu => m68k}/kernel/irq.c (100%) create mode 100644 trunk/arch/m68k/kernel/m68k_ksyms_mm.c rename trunk/arch/{m68knommu/kernel/m68k_ksyms.c => m68k/kernel/m68k_ksyms_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/module_mm.c rename trunk/arch/{m68knommu/kernel/module.c => m68k/kernel/module_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/process_mm.c rename trunk/arch/{m68knommu/kernel/process.c => m68k/kernel/process_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/ptrace_mm.c rename trunk/arch/{m68knommu/kernel/ptrace.c => m68k/kernel/ptrace_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/setup_mm.c rename trunk/arch/{m68knommu/kernel/setup.c => m68k/kernel/setup_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/signal_mm.c rename trunk/arch/{m68knommu/kernel/signal.c => m68k/kernel/signal_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/sys_m68k_mm.c rename trunk/arch/{m68knommu/kernel/sys_m68k.c => m68k/kernel/sys_m68k_no.c} (100%) rename trunk/arch/{m68knommu => m68k}/kernel/syscalltable.S (100%) create mode 100644 trunk/arch/m68k/kernel/time_mm.c rename trunk/arch/{m68knommu/kernel/time.c => m68k/kernel/time_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/traps_mm.c rename trunk/arch/{m68knommu/kernel/traps.c => m68k/kernel/traps_no.c} (100%) create mode 100644 trunk/arch/m68k/kernel/vmlinux.lds_mm.S rename trunk/arch/{m68knommu/kernel/vmlinux.lds.S => m68k/kernel/vmlinux.lds_no.S} (100%) create mode 100644 trunk/arch/m68k/lib/Makefile_mm rename trunk/arch/{m68knommu/lib/Makefile => m68k/lib/Makefile_no} (100%) create mode 100644 trunk/arch/m68k/lib/checksum_mm.c rename trunk/arch/{m68knommu/lib/checksum.c => m68k/lib/checksum_no.c} (100%) rename trunk/arch/{m68knommu => m68k}/lib/delay.c (100%) rename trunk/arch/{m68knommu => m68k}/lib/divsi3.S (100%) rename trunk/arch/{m68knommu => m68k}/lib/memcpy.c (100%) rename trunk/arch/{m68knommu => m68k}/lib/memmove.c (100%) rename trunk/arch/{m68knommu => m68k}/lib/memset.c (100%) rename trunk/arch/{m68knommu => m68k}/lib/modsi3.S (100%) rename trunk/arch/{m68knommu/lib/ashrdi3.c => m68k/lib/muldi3_mm.c} (60%) rename trunk/arch/{m68knommu/lib/muldi3.c => m68k/lib/muldi3_no.c} (100%) rename trunk/arch/{m68knommu => m68k}/lib/mulsi3.S (100%) rename trunk/arch/{m68knommu => m68k}/lib/udivsi3.S (100%) rename trunk/arch/{m68knommu => m68k}/lib/umodsi3.S (100%) create mode 100644 trunk/arch/m68k/mm/Makefile_mm rename trunk/arch/{m68knommu/mm/Makefile => m68k/mm/Makefile_no} (100%) create mode 100644 trunk/arch/m68k/mm/init_mm.c rename trunk/arch/{m68knommu/mm/init.c => m68k/mm/init_no.c} (100%) create mode 100644 trunk/arch/m68k/mm/kmap_mm.c rename trunk/arch/{m68knommu/mm/kmap.c => m68k/mm/kmap_no.c} (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206e/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206e/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5206e/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/520x/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/520x/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/520x/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/523x/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/523x/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/523x/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5249/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5249/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5249/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5249/intc2.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5272/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5272/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5272/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5272/intc.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/527x/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/527x/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/527x/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/528x/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/528x/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/528x/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5307/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5307/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5307/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5307/nettel.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/532x/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/532x/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/532x/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5407/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/5407/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/5407/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/54xx/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/54xx/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/54xx/firebee.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/bootlogo.h (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/bootlogo.pl (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/entry.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/head-de2.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/head-pilot.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/head-ram.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/head-rom.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/ints.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/romvec.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68328/timers.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/commproc.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/entry.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/head-ram.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/head-rom.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/68360/ints.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68EZ328/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/68EZ328/bootlogo.h (100%) rename trunk/arch/{m68knommu => m68k}/platform/68EZ328/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/68VZ328/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/68VZ328/config.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/Makefile (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/cache.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/clk.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/dma.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/dma_timer.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/entry.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/gpio.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/head.S (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/intc-2.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/intc-simr.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/intc.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/pinmux.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/pit.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/sltimers.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/timers.c (100%) rename trunk/arch/{m68knommu => m68k}/platform/coldfire/vectors.c (100%) delete mode 100644 trunk/arch/m68knommu/Kconfig.debug delete mode 100644 trunk/arch/m68knommu/defconfig delete mode 100644 trunk/arch/m68knommu/kernel/.gitignore delete mode 100644 trunk/arch/m68knommu/lib/ashldi3.c delete mode 100644 trunk/arch/m68knommu/lib/lshrdi3.c delete mode 100644 trunk/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h delete mode 100644 trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h delete mode 100644 trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_eth.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_smp.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_smtc.c delete mode 100644 trunk/arch/s390/include/asm/cmpxchg.h delete mode 100644 trunk/drivers/memstick/host/r592.c delete mode 100644 trunk/drivers/memstick/host/r592.h diff --git a/[refs] b/[refs] index c77b3b5002d1..1658b8203252 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 73939bb56acef1c9e776a10f0aeea0456d6815f6 +refs/heads/master: 66d857b08b8c3ed5c72c361f863cce77d2a978d7 diff --git a/trunk/Documentation/ABI/testing/sysfs-fs-ext4 b/trunk/Documentation/ABI/testing/sysfs-fs-ext4 index f22ac0872ae8..5fb709997d96 100644 --- a/trunk/Documentation/ABI/testing/sysfs-fs-ext4 +++ b/trunk/Documentation/ABI/testing/sysfs-fs-ext4 @@ -48,7 +48,7 @@ Description: will have its blocks allocated out of its own unique preallocation pool. -What: /sys/fs/ext4//inode_readahead_blks +What: /sys/fs/ext4//inode_readahead Date: March 2008 Contact: "Theodore Ts'o" Description: @@ -85,14 +85,7 @@ Date: June 2008 Contact: "Theodore Ts'o" Description: Tuning parameter which (if non-zero) controls the goal - inode used by the inode allocator in preference to - all other allocation heuristics. This is intended for + inode used by the inode allocator in p0reference to + all other allocation hueristics. This is intended for debugging use only, and should be 0 on production systems. - -What: /sys/fs/ext4//max_writeback_mb_bump -Date: September 2009 -Contact: "Theodore Ts'o" -Description: - The maximum number of megabytes the writeback code will - try to write out before move on to another inode. diff --git a/trunk/Documentation/filesystems/ext4.txt b/trunk/Documentation/filesystems/ext4.txt index 6b050464a90d..6ab9442d7eeb 100644 --- a/trunk/Documentation/filesystems/ext4.txt +++ b/trunk/Documentation/filesystems/ext4.txt @@ -367,47 +367,12 @@ init_itable=n The lazy itable init code will wait n times the minimizes the impact on the systme performance while file system's inode table is being initialized. -discard Controls whether ext4 should issue discard/TRIM +discard Controls whether ext4 should issue discard/TRIM nodiscard(*) commands to the underlying block device when blocks are freed. This is useful for SSD devices and sparse/thinly-provisioned LUNs, but it is off by default until sufficient testing has been done. -nouid32 Disables 32-bit UIDs and GIDs. This is for - interoperability with older kernels which only - store and expect 16-bit values. - -resize Allows to resize filesystem to the end of the last - existing block group, further resize has to be done - with resize2fs either online, or offline. It can be - used only with conjunction with remount. - -block_validity This options allows to enables/disables the in-kernel -noblock_validity facility for tracking filesystem metadata blocks - within internal data structures. This allows multi- - block allocator and other routines to quickly locate - extents which might overlap with filesystem metadata - blocks. This option is intended for debugging - purposes and since it negatively affects the - performance, it is off by default. - -dioread_lock Controls whether or not ext4 should use the DIO read -dioread_nolock locking. If the dioread_nolock option is specified - ext4 will allocate uninitialized extent before buffer - write and convert the extent to initialized after IO - completes. This approach allows ext4 code to avoid - using inode mutex, which improves scalability on high - speed storages. However this does not work with nobh - option and the mount will fail. Nor does it work with - data journaling and dioread_nolock option will be - ignored with kernel warning. Note that dioread_nolock - code path is only used for extent-based files. - Because of the restrictions this options comprises - it is off by default (e.g. dioread_lock). - -i_version Enable 64-bit inode version support. This option is - off by default. - Data Mode ========= There are 3 different data modes: @@ -435,176 +400,6 @@ needs to be read from and written to disk at the same time where it outperforms all others modes. Currently ext4 does not have delayed allocation support if this data journalling mode is selected. -/proc entries -============= - -Information about mounted ext4 file systems can be found in -/proc/fs/ext4. Each mounted filesystem will have a directory in -/proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or -/proc/fs/ext4/dm-0). The files in each per-device directory are shown -in table below. - -Files in /proc/fs/ext4/ -.............................................................................. - File Content - mb_groups details of multiblock allocator buddy cache of free blocks -.............................................................................. - -/sys entries -============ - -Information about mounted ext4 file systems can be found in -/sys/fs/ext4. Each mounted filesystem will have a directory in -/sys/fs/ext4 based on its device name (i.e., /sys/fs/ext4/hdc or -/sys/fs/ext4/dm-0). The files in each per-device directory are shown -in table below. - -Files in /sys/fs/ext4/ -(see also Documentation/ABI/testing/sysfs-fs-ext4) -.............................................................................. - File Content - - delayed_allocation_blocks This file is read-only and shows the number of - blocks that are dirty in the page cache, but - which do not have their location in the - filesystem allocated yet. - - inode_goal Tuning parameter which (if non-zero) controls - the goal inode used by the inode allocator in - preference to all other allocation heuristics. - This is intended for debugging use only, and - should be 0 on production systems. - - inode_readahead_blks Tuning parameter which controls the maximum - number of inode table blocks that ext4's inode - table readahead algorithm will pre-read into - the buffer cache - - lifetime_write_kbytes This file is read-only and shows the number of - kilobytes of data that have been written to this - filesystem since it was created. - - max_writeback_mb_bump The maximum number of megabytes the writeback - code will try to write out before move on to - another inode. - - mb_group_prealloc The multiblock allocator will round up allocation - requests to a multiple of this tuning parameter if - the stripe size is not set in the ext4 superblock - - mb_max_to_scan The maximum number of extents the multiblock - allocator will search to find the best extent - - mb_min_to_scan The minimum number of extents the multiblock - allocator will search to find the best extent - - mb_order2_req Tuning parameter which controls the minimum size - for requests (as a power of 2) where the buddy - cache is used - - mb_stats Controls whether the multiblock allocator should - collect statistics, which are shown during the - unmount. 1 means to collect statistics, 0 means - not to collect statistics - - mb_stream_req Files which have fewer blocks than this tunable - parameter will have their blocks allocated out - of a block group specific preallocation pool, so - that small files are packed closely together. - Each large file will have its blocks allocated - out of its own unique preallocation pool. - - session_write_kbytes This file is read-only and shows the number of - kilobytes of data that have been written to this - filesystem since it was mounted. -.............................................................................. - -Ioctls -====== - -There is some Ext4 specific functionality which can be accessed by applications -through the system call interfaces. The list of all Ext4 specific ioctls are -shown in the table below. - -Table of Ext4 specific ioctls -.............................................................................. - Ioctl Description - EXT4_IOC_GETFLAGS Get additional attributes associated with inode. - The ioctl argument is an integer bitfield, with - bit values described in ext4.h. This ioctl is an - alias for FS_IOC_GETFLAGS. - - EXT4_IOC_SETFLAGS Set additional attributes associated with inode. - The ioctl argument is an integer bitfield, with - bit values described in ext4.h. This ioctl is an - alias for FS_IOC_SETFLAGS. - - EXT4_IOC_GETVERSION - EXT4_IOC_GETVERSION_OLD - Get the inode i_generation number stored for - each inode. The i_generation number is normally - changed only when new inode is created and it is - particularly useful for network filesystems. The - '_OLD' version of this ioctl is an alias for - FS_IOC_GETVERSION. - - EXT4_IOC_SETVERSION - EXT4_IOC_SETVERSION_OLD - Set the inode i_generation number stored for - each inode. The '_OLD' version of this ioctl - is an alias for FS_IOC_SETVERSION. - - EXT4_IOC_GROUP_EXTEND This ioctl has the same purpose as the resize - mount option. It allows to resize filesystem - to the end of the last existing block group, - further resize has to be done with resize2fs, - either online, or offline. The argument points - to the unsigned logn number representing the - filesystem new block count. - - EXT4_IOC_MOVE_EXT Move the block extents from orig_fd (the one - this ioctl is pointing to) to the donor_fd (the - one specified in move_extent structure passed - as an argument to this ioctl). Then, exchange - inode metadata between orig_fd and donor_fd. - This is especially useful for online - defragmentation, because the allocator has the - opportunity to allocate moved blocks better, - ideally into one contiguous extent. - - EXT4_IOC_GROUP_ADD Add a new group descriptor to an existing or - new group descriptor block. The new group - descriptor is described by ext4_new_group_input - structure, which is passed as an argument to - this ioctl. This is especially useful in - conjunction with EXT4_IOC_GROUP_EXTEND, - which allows online resize of the filesystem - to the end of the last existing block group. - Those two ioctls combined is used in userspace - online resize tool (e.g. resize2fs). - - EXT4_IOC_MIGRATE This ioctl operates on the filesystem itself. - It converts (migrates) ext3 indirect block mapped - inode to ext4 extent mapped inode by walking - through indirect block mapping of the original - inode and converting contiguous block ranges - into ext4 extents of the temporary inode. Then, - inodes are swapped. This ioctl might help, when - migrating from ext3 to ext4 filesystem, however - suggestion is to create fresh ext4 filesystem - and copy data from the backup. Note, that - filesystem has to support extents for this ioctl - to work. - - EXT4_IOC_ALLOC_DA_BLKS Force all of the delay allocated blocks to be - allocated to preserve application-expected ext3 - behaviour. Note that this will also start - triggering a write of the data blocks, but this - behaviour may change in the future as it is - not necessary and has been done this way only - for sake of simplicity. -.............................................................................. - References ========== diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 4fb9017b4413..749f9cd38089 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -5291,11 +5291,6 @@ S: Maintained F: drivers/mtd/nand/r852.c F: drivers/mtd/nand/r852.h -RICOH R5C592 MEMORYSTICK DRIVER -M: Maxim Levitsky -S: Maintained -F: drivers/memstick/host/r592.* - RISCOM8 DRIVER S: Orphan F: Documentation/serial/riscom8.txt diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 525174d41679..6e056d3c5d01 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -1,13 +1,11 @@ config M68K bool default y - select HAVE_AOUT select HAVE_IDE - select GENERIC_ATOMIC64 - -config MMU - bool - default y + select HAVE_AOUT if MMU + select GENERIC_ATOMIC64 if MMU + select HAVE_GENERIC_HARDIRQS if !MMU + select GENERIC_HARDIRQS_NO_DEPRECATED if !MMU config RWSEM_GENERIC_SPINLOCK bool @@ -34,457 +32,67 @@ config TIME_LOW_RES bool default y -config GENERIC_IOMAP - bool - default y - -config ARCH_MAY_HAVE_PC_FDC - bool - depends on BROKEN && (Q40 || SUN3X) - default y - config NO_IOPORT def_bool y config NO_DMA - def_bool SUN3 + def_bool (MMU && SUN3) || (!MMU && !COLDFIRE) +config ZONE_DMA + bool + default y config HZ int + default 1000 if CLEOPATRA default 100 -config ARCH_USES_GETTIMEOFFSET - def_bool y - source "init/Kconfig" source "kernel/Kconfig.freezer" -menu "Platform dependent setup" - -config EISA - bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config PCMCIA - tristate - ---help--- - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). Please also read the PCMCIA-HOWTO, available from - . - - To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. - -config AMIGA - bool "Amiga support" - select MMU_MOTOROLA if MMU - help - This option enables support for the Amiga series of computers. If - you plan to use this kernel on an Amiga, say Y here and browse the - material available in ; otherwise say N. - -config ATARI - bool "Atari support" - select MMU_MOTOROLA if MMU - help - This option enables support for the 68000-based Atari series of - computers (including the TT, Falcon and Medusa). If you plan to use - this kernel on an Atari, say Y here and browse the material - available in ; otherwise say N. - -config MAC - bool "Macintosh support" - select MMU_MOTOROLA if MMU - help - This option enables support for the Apple Macintosh series of - computers (yes, there is experimental support now, at least for part - of the series). - - Say N unless you're willing to code the remaining necessary support. - ;) - -config NUBUS - bool - depends on MAC - default y - -config M68K_L2_CACHE - bool - depends on MAC - default y - -config APOLLO - bool "Apollo support" - select MMU_MOTOROLA if MMU - help - Say Y here if you want to run Linux on an MC680x0-based Apollo - Domain workstation such as the DN3500. - -config VME - bool "VME (Motorola and BVM) support" - select MMU_MOTOROLA if MMU - help - Say Y here if you want to build a kernel for a 680x0 based VME - board. Boards currently supported include Motorola boards MVME147, - MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and - BVME6000 boards from BVM Ltd are also supported. - -config MVME147 - bool "MVME147 support" - depends on VME - help - Say Y to include support for early Motorola VME boards. This will - build a kernel which can run on MVME147 single-board computers. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -config MVME16x - bool "MVME162, 166 and 167 support" - depends on VME - help - Say Y to include support for Motorola VME boards. This will build a - kernel which can run on MVME162, MVME166, MVME167, MVME172, and - MVME177 boards. If you select this option you will have to select - the appropriate drivers for SCSI, Ethernet and serial ports later - on. - -config BVME6000 - bool "BVME4000 and BVME6000 support" - depends on VME - help - Say Y to include support for VME boards from BVM Ltd. This will - build a kernel which can run on BVME4000 and BVME6000 boards. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -config HP300 - bool "HP9000/300 and HP9000/400 support" - select MMU_MOTOROLA if MMU - help - This option enables support for the HP9000/300 and HP9000/400 series - of workstations. Support for these machines is still somewhat - experimental. If you plan to try to use the kernel on such a machine - say Y here. - Everybody else says N. - -config DIO - bool "DIO bus support" - depends on HP300 +config MMU + bool "MMU-based Paged Memory Management Support" default y help - Say Y here to enable support for the "DIO" expansion bus used in - HP300 machines. If you are using such a system you almost certainly - want this. - -config SUN3X - bool "Sun3x support" - select MMU_MOTOROLA if MMU - select M68030 - help - This option enables support for the Sun 3x series of workstations. - Be warned that this support is very experimental. - Note that Sun 3x kernels are not compatible with Sun 3 hardware. - General Linux information on the Sun 3x series (now discontinued) - is at . - - If you don't want to compile a kernel for a Sun 3x, say N. - -config Q40 - bool "Q40/Q60 support" - select MMU_MOTOROLA if MMU - help - The Q40 is a Motorola 68040-based successor to the Sinclair QL - manufactured in Germany. There is an official Q40 home page at - . This option enables support for the Q40 and - Q60. Select your CPU below. For 68LC060 don't forget to enable FPU - emulation. - -config SUN3 - bool "Sun3 support" - depends on !MMU_MOTOROLA - select MMU_SUN3 if MMU - select M68020 - help - This option enables support for the Sun 3 series of workstations - (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires - that all other hardware types must be disabled, as Sun 3 kernels - are incompatible with all other m68k targets (including Sun 3x!). - - If you don't want to compile a kernel exclusively for a Sun 3, say N. - -config NATFEAT - bool "ARAnyM emulator support" - depends on ATARI - help - This option enables support for ARAnyM native features, such as - access to a disk image as /dev/hda. - -config NFBLOCK - tristate "NatFeat block device support" - depends on BLOCK && NATFEAT - help - Say Y to include support for the ARAnyM NatFeat block device - which allows direct access to the hard drives without using - the hardware emulation. - -config NFCON - tristate "NatFeat console driver" - depends on NATFEAT - help - Say Y to include support for the ARAnyM NatFeat console driver - which allows the console output to be redirected to the stderr - output of ARAnyM. - -config NFETH - tristate "NatFeat Ethernet support" - depends on NET_ETHERNET && NATFEAT - help - Say Y to include support for the ARAnyM NatFeat network device - which will emulate a regular ethernet device while presenting an - ethertap device to the host system. - -comment "Processor type" - -config M68020 - bool "68020 support" - help - If you anticipate running this kernel on a computer with a MC68020 - processor, say Y. Otherwise, say N. Note that the 68020 requires a - 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the - Sun 3, which provides its own version. - -config M68030 - bool "68030 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68030 - processor, say Y. Otherwise, say N. Note that a MC68EC030 will not - work, as it does not include an MMU (Memory Management Unit). - -config M68040 - bool "68040 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68LC040 - or MC68040 processor, say Y. Otherwise, say N. Note that an - MC68EC040 will not work, as it does not include an MMU (Memory - Management Unit). - -config M68060 - bool "68060 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68060 - processor, say Y. Otherwise, say N. - -config MMU_MOTOROLA - bool - -config MMU_SUN3 - bool - depends on MMU && !MMU_MOTOROLA - -config M68KFPU_EMU - bool "Math emulation support (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - At some point in the future, this will cause floating-point math - instructions to be emulated by the kernel on machines that lack a - floating-point math coprocessor. Thrill-seekers and chronically - sleep-deprived psychotic hacker types can say Y now, everyone else - should probably wait a while. - -config M68KFPU_EMU_EXTRAPREC - bool "Math emulation extra precision" - depends on M68KFPU_EMU - help - The fpu uses normally a few bit more during calculations for - correct rounding, the emulator can (often) do the same but this - extra calculation can cost quite some time, so you can disable - it here. The emulator will then "only" calculate with a 64 bit - mantissa and round slightly incorrect, what is more than enough - for normal usage. - -config M68KFPU_EMU_ONLY - bool "Math emulation only kernel" - depends on M68KFPU_EMU - help - This option prevents any floating-point instructions from being - compiled into the kernel, thereby the kernel doesn't save any - floating point context anymore during task switches, so this - kernel will only be usable on machines without a floating-point - math coprocessor. This makes the kernel a bit faster as no tests - needs to be executed whether a floating-point instruction in the - kernel should be executed or not. - -config ADVANCED - bool "Advanced configuration options" - ---help--- - This gives you access to some advanced options for the CPU. The - defaults should be fine for most users, but these options may make - it possible for you to improve performance somewhat if you know what - you are doing. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these options. + Select if you want MMU-based virtualised addressing space + support by paged memory management. If unsure, say 'Y'. - Most users should say N to this question. - -config RMW_INSNS - bool "Use read-modify-write instructions" - depends on ADVANCED - ---help--- - This allows to use certain instructions that work with indivisible - read-modify-write bus cycles. While this is faster than the - workaround of disabling interrupts, it can conflict with DMA - ( = direct memory access) on many Amiga systems, and it is also said - to destabilize other machines. It is very likely that this will - cause serious problems on any Amiga or Atari Medusa if set. The only - configuration where it should work are 68030-based Ataris, where it - apparently improves performance. But you've been warned! Unless you - really know what you are doing, say N. Try Y only if you're quite - adventurous. - -config SINGLE_MEMORY_CHUNK - bool "Use one physical chunk of memory only" if ADVANCED && !SUN3 - default y if SUN3 - select NEED_MULTIPLE_NODES - help - Ignore all but the first contiguous chunk of physical memory for VM - purposes. This will save a few bytes kernel size and may speed up - some operations. Say N if not sure. +menu "Platform dependent setup" -config 060_WRITETHROUGH - bool "Use write-through caching for 68060 supervisor accesses" - depends on ADVANCED && M68060 - ---help--- - The 68060 generally uses copyback caching of recently accessed data. - Copyback caching means that memory writes will be held in an on-chip - cache and only written back to memory some time later. Saying Y - here will force supervisor (kernel) accesses to use writethrough - caching. Writethrough caching means that data is written to memory - straight away, so that cache and memory data always agree. - Writethrough caching is less efficient, but is needed for some - drivers on 68060 based systems where the 68060 bus snooping signal - is hardwired on. The 53c710 SCSI driver is known to suffer from - this problem. - -config ARCH_DISCONTIGMEM_ENABLE - def_bool !SINGLE_MEMORY_CHUNK - -config NODES_SHIFT - int - default "3" - depends on !SINGLE_MEMORY_CHUNK +if MMU +source arch/m68k/Kconfig.mmu +endif +if !MMU +source arch/m68k/Kconfig.nommu +endif source "mm/Kconfig" endmenu -menu "General setup" +menu "Executable file formats" source "fs/Kconfig.binfmt" -config ZORRO - bool "Amiga Zorro (AutoConfig) bus support" - depends on AMIGA - help - This enables support for the Zorro bus in the Amiga. If you have - expansion cards in your Amiga that conform to the Amiga - AutoConfig(tm) specification, say Y, otherwise N. Note that even - expansion cards that do not fit in the Zorro slots but fit in e.g. - the CPU slot may fall in this category, so you have to say Y to let - Linux use these. - -config AMIGA_PCMCIA - bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)" - depends on AMIGA && EXPERIMENTAL - help - Include support in the kernel for pcmcia on Amiga 1200 and Amiga - 600. If you intend to use pcmcia cards say Y; otherwise say N. - -config STRAM_PROC - bool "ST-RAM statistics in /proc" - depends on ATARI - help - Say Y here to report ST-RAM usage statistics in /proc/stram. - -config HEARTBEAT - bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 - default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 - help - Use the power-on LED on your machine as a load meter. The exact - behavior is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. - -# We have a dedicated heartbeat LED. :-) -config PROC_HARDWARE - bool "/proc/hardware support" - help - Say Y here to support the /proc/hardware file, which gives you - access to information about the machine you're running on, - including the model, CPU, MMU, clock speed, BogoMIPS rating, - and memory size. - -config ISA - bool - depends on Q40 || AMIGA_PCMCIA - default y - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config GENERIC_ISA_DMA - bool - depends on Q40 || AMIGA_PCMCIA - default y - -config ZONE_DMA - bool - default y +endmenu -source "drivers/pci/Kconfig" +if !MMU +menu "Power management options" -source "drivers/zorro/Kconfig" +config PM + bool "Power Management support" + help + Support processor power management modes endmenu +endif source "net/Kconfig" source "drivers/Kconfig" +if MMU + menu "Character devices" config ATARI_MFPSER @@ -627,6 +235,8 @@ config SERIAL_CONSOLE endmenu +endif + source "fs/Kconfig" source "arch/m68k/Kconfig.debug" diff --git a/trunk/arch/m68k/Kconfig.debug b/trunk/arch/m68k/Kconfig.debug index f53b6d5300e5..2bdb1b01115c 100644 --- a/trunk/arch/m68k/Kconfig.debug +++ b/trunk/arch/m68k/Kconfig.debug @@ -2,4 +2,38 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +if !MMU + +config FULLDEBUG + bool "Full Symbolic/Source Debugging support" + help + Enable debugging symbols on kernel build. + +config HIGHPROFILE + bool "Use fast second timer for profiling" + depends on COLDFIRE + help + Use a fast secondary clock to produce profiling information. + +config BOOTPARAM + bool 'Compiled-in Kernel Boot Parameter' + +config BOOTPARAM_STRING + string 'Kernel Boot Parameter' + default 'console=ttyS0,19200' + depends on BOOTPARAM + +config NO_KERNEL_MSG + bool "Suppress Kernel BUG Messages" + help + Do not output any debug BUG messages within the kernel. + +config BDM_DISABLE + bool "Disable BDM signals" + depends on (EXPERIMENTAL && COLDFIRE) + help + Disable the ColdFire CPU's BDM signals. + +endif + endmenu diff --git a/trunk/arch/m68k/Kconfig.mmu b/trunk/arch/m68k/Kconfig.mmu new file mode 100644 index 000000000000..16539b1d5d3a --- /dev/null +++ b/trunk/arch/m68k/Kconfig.mmu @@ -0,0 +1,417 @@ +config GENERIC_IOMAP + bool + default y + +config ARCH_MAY_HAVE_PC_FDC + bool + depends on BROKEN && (Q40 || SUN3X) + default y + +config ARCH_USES_GETTIMEOFFSET + def_bool y + +config EISA + bool + ---help--- + The Extended Industry Standard Architecture (EISA) bus was + developed as an open alternative to the IBM MicroChannel bus. + + The EISA bus provided some of the features of the IBM MicroChannel + bus while maintaining backward compatibility with cards made for + the older ISA bus. The EISA bus saw limited use between 1988 and + 1995 when it was made obsolete by the PCI bus. + + Say Y here if you are building a kernel for an EISA-based machine. + + Otherwise, say N. + +config MCA + bool + help + MicroChannel Architecture is found in some IBM PS/2 machines and + laptops. It is a bus system similar to PCI or ISA. See + (and especially the web page given + there) before attempting to build an MCA bus kernel. + +config PCMCIA + tristate + ---help--- + Say Y here if you want to attach PCMCIA- or PC-cards to your Linux + computer. These are credit-card size devices such as network cards, + modems or hard drives often used with laptops computers. There are + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. If you want to use CardBus + cards, you need to say Y here and also to "CardBus support" below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file + for location). Please also read the PCMCIA-HOWTO, available from + . + + To compile this driver as modules, choose M here: the + modules will be called pcmcia_core and ds. + +config AMIGA + bool "Amiga support" + select MMU_MOTOROLA if MMU + help + This option enables support for the Amiga series of computers. If + you plan to use this kernel on an Amiga, say Y here and browse the + material available in ; otherwise say N. + +config ATARI + bool "Atari support" + select MMU_MOTOROLA if MMU + help + This option enables support for the 68000-based Atari series of + computers (including the TT, Falcon and Medusa). If you plan to use + this kernel on an Atari, say Y here and browse the material + available in ; otherwise say N. + +config MAC + bool "Macintosh support" + select MMU_MOTOROLA if MMU + help + This option enables support for the Apple Macintosh series of + computers (yes, there is experimental support now, at least for part + of the series). + + Say N unless you're willing to code the remaining necessary support. + ;) + +config NUBUS + bool + depends on MAC + default y + +config M68K_L2_CACHE + bool + depends on MAC + default y + +config APOLLO + bool "Apollo support" + select MMU_MOTOROLA if MMU + help + Say Y here if you want to run Linux on an MC680x0-based Apollo + Domain workstation such as the DN3500. + +config VME + bool "VME (Motorola and BVM) support" + select MMU_MOTOROLA if MMU + help + Say Y here if you want to build a kernel for a 680x0 based VME + board. Boards currently supported include Motorola boards MVME147, + MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and + BVME6000 boards from BVM Ltd are also supported. + +config MVME147 + bool "MVME147 support" + depends on VME + help + Say Y to include support for early Motorola VME boards. This will + build a kernel which can run on MVME147 single-board computers. If + you select this option you will have to select the appropriate + drivers for SCSI, Ethernet and serial ports later on. + +config MVME16x + bool "MVME162, 166 and 167 support" + depends on VME + help + Say Y to include support for Motorola VME boards. This will build a + kernel which can run on MVME162, MVME166, MVME167, MVME172, and + MVME177 boards. If you select this option you will have to select + the appropriate drivers for SCSI, Ethernet and serial ports later + on. + +config BVME6000 + bool "BVME4000 and BVME6000 support" + depends on VME + help + Say Y to include support for VME boards from BVM Ltd. This will + build a kernel which can run on BVME4000 and BVME6000 boards. If + you select this option you will have to select the appropriate + drivers for SCSI, Ethernet and serial ports later on. + +config HP300 + bool "HP9000/300 and HP9000/400 support" + select MMU_MOTOROLA if MMU + help + This option enables support for the HP9000/300 and HP9000/400 series + of workstations. Support for these machines is still somewhat + experimental. If you plan to try to use the kernel on such a machine + say Y here. + Everybody else says N. + +config DIO + bool "DIO bus support" + depends on HP300 + default y + help + Say Y here to enable support for the "DIO" expansion bus used in + HP300 machines. If you are using such a system you almost certainly + want this. + +config SUN3X + bool "Sun3x support" + select MMU_MOTOROLA if MMU + select M68030 + help + This option enables support for the Sun 3x series of workstations. + Be warned that this support is very experimental. + Note that Sun 3x kernels are not compatible with Sun 3 hardware. + General Linux information on the Sun 3x series (now discontinued) + is at . + + If you don't want to compile a kernel for a Sun 3x, say N. + +config Q40 + bool "Q40/Q60 support" + select MMU_MOTOROLA if MMU + help + The Q40 is a Motorola 68040-based successor to the Sinclair QL + manufactured in Germany. There is an official Q40 home page at + . This option enables support for the Q40 and + Q60. Select your CPU below. For 68LC060 don't forget to enable FPU + emulation. + +config SUN3 + bool "Sun3 support" + depends on !MMU_MOTOROLA + select MMU_SUN3 if MMU + select M68020 + help + This option enables support for the Sun 3 series of workstations + (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires + that all other hardware types must be disabled, as Sun 3 kernels + are incompatible with all other m68k targets (including Sun 3x!). + + If you don't want to compile a kernel exclusively for a Sun 3, say N. + +config NATFEAT + bool "ARAnyM emulator support" + depends on ATARI + help + This option enables support for ARAnyM native features, such as + access to a disk image as /dev/hda. + +config NFBLOCK + tristate "NatFeat block device support" + depends on BLOCK && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat block device + which allows direct access to the hard drives without using + the hardware emulation. + +config NFCON + tristate "NatFeat console driver" + depends on NATFEAT + help + Say Y to include support for the ARAnyM NatFeat console driver + which allows the console output to be redirected to the stderr + output of ARAnyM. + +config NFETH + tristate "NatFeat Ethernet support" + depends on NET_ETHERNET && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat network device + which will emulate a regular ethernet device while presenting an + ethertap device to the host system. + +comment "Processor type" + +config M68020 + bool "68020 support" + help + If you anticipate running this kernel on a computer with a MC68020 + processor, say Y. Otherwise, say N. Note that the 68020 requires a + 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the + Sun 3, which provides its own version. + +config M68030 + bool "68030 support" + depends on !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68030 + processor, say Y. Otherwise, say N. Note that a MC68EC030 will not + work, as it does not include an MMU (Memory Management Unit). + +config M68040 + bool "68040 support" + depends on !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68LC040 + or MC68040 processor, say Y. Otherwise, say N. Note that an + MC68EC040 will not work, as it does not include an MMU (Memory + Management Unit). + +config M68060 + bool "68060 support" + depends on !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68060 + processor, say Y. Otherwise, say N. + +config MMU_MOTOROLA + bool + +config MMU_SUN3 + bool + depends on MMU && !MMU_MOTOROLA + +config M68KFPU_EMU + bool "Math emulation support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + At some point in the future, this will cause floating-point math + instructions to be emulated by the kernel on machines that lack a + floating-point math coprocessor. Thrill-seekers and chronically + sleep-deprived psychotic hacker types can say Y now, everyone else + should probably wait a while. + +config M68KFPU_EMU_EXTRAPREC + bool "Math emulation extra precision" + depends on M68KFPU_EMU + help + The fpu uses normally a few bit more during calculations for + correct rounding, the emulator can (often) do the same but this + extra calculation can cost quite some time, so you can disable + it here. The emulator will then "only" calculate with a 64 bit + mantissa and round slightly incorrect, what is more than enough + for normal usage. + +config M68KFPU_EMU_ONLY + bool "Math emulation only kernel" + depends on M68KFPU_EMU + help + This option prevents any floating-point instructions from being + compiled into the kernel, thereby the kernel doesn't save any + floating point context anymore during task switches, so this + kernel will only be usable on machines without a floating-point + math coprocessor. This makes the kernel a bit faster as no tests + needs to be executed whether a floating-point instruction in the + kernel should be executed or not. + +config ADVANCED + bool "Advanced configuration options" + ---help--- + This gives you access to some advanced options for the CPU. The + defaults should be fine for most users, but these options may make + it possible for you to improve performance somewhat if you know what + you are doing. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about these options. + + Most users should say N to this question. + +config RMW_INSNS + bool "Use read-modify-write instructions" + depends on ADVANCED + ---help--- + This allows to use certain instructions that work with indivisible + read-modify-write bus cycles. While this is faster than the + workaround of disabling interrupts, it can conflict with DMA + ( = direct memory access) on many Amiga systems, and it is also said + to destabilize other machines. It is very likely that this will + cause serious problems on any Amiga or Atari Medusa if set. The only + configuration where it should work are 68030-based Ataris, where it + apparently improves performance. But you've been warned! Unless you + really know what you are doing, say N. Try Y only if you're quite + adventurous. + +config SINGLE_MEMORY_CHUNK + bool "Use one physical chunk of memory only" if ADVANCED && !SUN3 + default y if SUN3 + select NEED_MULTIPLE_NODES + help + Ignore all but the first contiguous chunk of physical memory for VM + purposes. This will save a few bytes kernel size and may speed up + some operations. Say N if not sure. + +config 060_WRITETHROUGH + bool "Use write-through caching for 68060 supervisor accesses" + depends on ADVANCED && M68060 + ---help--- + The 68060 generally uses copyback caching of recently accessed data. + Copyback caching means that memory writes will be held in an on-chip + cache and only written back to memory some time later. Saying Y + here will force supervisor (kernel) accesses to use writethrough + caching. Writethrough caching means that data is written to memory + straight away, so that cache and memory data always agree. + Writethrough caching is less efficient, but is needed for some + drivers on 68060 based systems where the 68060 bus snooping signal + is hardwired on. The 53c710 SCSI driver is known to suffer from + this problem. + +config ARCH_DISCONTIGMEM_ENABLE + def_bool !SINGLE_MEMORY_CHUNK + +config NODES_SHIFT + int + default "3" + depends on !SINGLE_MEMORY_CHUNK + +config ZORRO + bool "Amiga Zorro (AutoConfig) bus support" + depends on AMIGA + help + This enables support for the Zorro bus in the Amiga. If you have + expansion cards in your Amiga that conform to the Amiga + AutoConfig(tm) specification, say Y, otherwise N. Note that even + expansion cards that do not fit in the Zorro slots but fit in e.g. + the CPU slot may fall in this category, so you have to say Y to let + Linux use these. + +config AMIGA_PCMCIA + bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)" + depends on AMIGA && EXPERIMENTAL + help + Include support in the kernel for pcmcia on Amiga 1200 and Amiga + 600. If you intend to use pcmcia cards say Y; otherwise say N. + +config STRAM_PROC + bool "ST-RAM statistics in /proc" + depends on ATARI + help + Say Y here to report ST-RAM usage statistics in /proc/stram. + +config HEARTBEAT + bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 + default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 + help + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. + +# We have a dedicated heartbeat LED. :-) +config PROC_HARDWARE + bool "/proc/hardware support" + help + Say Y here to support the /proc/hardware file, which gives you + access to information about the machine you're running on, + including the model, CPU, MMU, clock speed, BogoMIPS rating, + and memory size. + +config ISA + bool + depends on Q40 || AMIGA_PCMCIA + default y + help + Find out whether you have ISA slots on your motherboard. ISA is the + name of a bus system, i.e. the way the CPU talks to the other stuff + inside your box. Other bus systems are PCI, EISA, MicroChannel + (MCA) or VESA. ISA is an older system, now being displaced by PCI; + newer boards don't support it. If you have ISA, say Y, otherwise N. + +config GENERIC_ISA_DMA + bool + depends on Q40 || AMIGA_PCMCIA + default y + +source "drivers/pci/Kconfig" + +source "drivers/zorro/Kconfig" + diff --git a/trunk/arch/m68knommu/Kconfig b/trunk/arch/m68k/Kconfig.nommu similarity index 93% rename from trunk/arch/m68knommu/Kconfig rename to trunk/arch/m68k/Kconfig.nommu index b5424cf948e6..273bccab9517 100644 --- a/trunk/arch/m68knommu/Kconfig +++ b/trunk/arch/m68k/Kconfig.nommu @@ -1,43 +1,7 @@ -config M68K - bool - default y - select HAVE_IDE - select HAVE_GENERIC_HARDIRQS - select GENERIC_HARDIRQS_NO_DEPRECATED - -config MMU - bool - default n - -config NO_DMA - bool - depends on !COLDFIRE - default y - config FPU bool default n -config ZONE_DMA - bool - default y - -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - default n - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - config GENERIC_FIND_NEXT_BIT bool default y @@ -46,29 +10,14 @@ config GENERIC_GPIO bool default n -config GENERIC_HWEIGHT - bool - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - config GENERIC_CMOS_UPDATE bool default y -config TIME_LOW_RES - bool - default y - config GENERIC_CLOCKEVENTS bool default n -config NO_IOPORT - def_bool y - config COLDFIRE_SW_A7 bool default n @@ -85,12 +34,6 @@ config HAVE_MBAR config HAVE_IPSBAR bool -source "init/Kconfig" - -source "kernel/Kconfig.freezer" - -menu "Processor type and features" - choice prompt "CPU" default M68EZ328 @@ -630,11 +573,6 @@ config 4KSTACKS running more threads on a system and also reduces the pressure on the VM subsystem for higher order allocations. -config HZ - int - default 1000 if CLEOPATRA - default 100 - comment "RAM configuration" config RAMBASE @@ -803,10 +741,6 @@ endif source "kernel/time/Kconfig" -source "mm/Kconfig" - -endmenu - config ISA_DMA_API bool depends on !M5272 @@ -814,31 +748,3 @@ config ISA_DMA_API source "drivers/pcmcia/Kconfig" -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -endmenu - -menu "Power management options" - -config PM - bool "Power Management support" - help - Support processor power management modes - -endmenu - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "fs/Kconfig" - -source "arch/m68knommu/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/trunk/arch/m68k/Makefile b/trunk/arch/m68k/Makefile index b793163abc61..be46cadd4017 100644 --- a/trunk/arch/m68k/Makefile +++ b/trunk/arch/m68k/Makefile @@ -1,123 +1,7 @@ -# -# m68k/Makefile -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture -# -# 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) 1994 by Hamish Macdonald -# - KBUILD_DEFCONFIG := multi_defconfig -# override top level makefile -AS += -m68020 -LDFLAGS := -m m68kelf -KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds -ifneq ($(SUBARCH),$(ARCH)) - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, \ - m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-) - endif -endif - -ifdef CONFIG_SUN3 -LDFLAGS_vmlinux = -N -endif - -CHECKFLAGS += -D__mc68000__ - -# without -fno-strength-reduce the 53c7xx.c driver fails ;-( -KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 - -# enable processor switch if compiled only for a single cpu -ifndef CONFIG_M68020 -ifndef CONFIG_M68030 - -ifndef CONFIG_M68060 -KBUILD_CFLAGS += -m68040 -endif - -ifndef CONFIG_M68040 -KBUILD_CFLAGS += -m68060 -endif - -endif -endif - -ifdef CONFIG_KGDB -# If configured for kgdb support, include debugging infos and keep the -# frame pointer -KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g -endif - -ifndef CONFIG_SUN3 -head-y := arch/m68k/kernel/head.o +ifdef CONFIG_MMU +include $(srctree)/arch/m68k/Makefile_mm else -head-y := arch/m68k/kernel/sun3-head.o +include $(srctree)/arch/m68k/Makefile_no endif - -core-y += arch/m68k/kernel/ arch/m68k/mm/ -libs-y += arch/m68k/lib/ - -core-$(CONFIG_Q40) += arch/m68k/q40/ -core-$(CONFIG_AMIGA) += arch/m68k/amiga/ -core-$(CONFIG_ATARI) += arch/m68k/atari/ -core-$(CONFIG_MAC) += arch/m68k/mac/ -core-$(CONFIG_HP300) += arch/m68k/hp300/ -core-$(CONFIG_APOLLO) += arch/m68k/apollo/ -core-$(CONFIG_MVME147) += arch/m68k/mvme147/ -core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/ -core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ -core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ -core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ -core-$(CONFIG_NATFEAT) += arch/m68k/emu/ -core-$(CONFIG_M68040) += arch/m68k/fpsp040/ -core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ -core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ - -all: zImage - -lilo: vmlinux - if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi - if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi - cat vmlinux > $(INSTALL_PATH)/vmlinux - cp System.map $(INSTALL_PATH)/System.map - if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi - -zImage compressed: vmlinux.gz - -vmlinux.gz: vmlinux - -ifndef CONFIG_KGDB - cp vmlinux vmlinux.tmp - $(STRIP) vmlinux.tmp - gzip -9c vmlinux.tmp >vmlinux.gz - rm vmlinux.tmp -else - gzip -9c vmlinux >vmlinux.gz -endif - -bzImage: vmlinux.bz2 - -vmlinux.bz2: vmlinux - -ifndef CONFIG_KGDB - cp vmlinux vmlinux.tmp - $(STRIP) vmlinux.tmp - bzip2 -1c vmlinux.tmp >vmlinux.bz2 - rm vmlinux.tmp -else - bzip2 -1c vmlinux >vmlinux.bz2 -endif - -archclean: - rm -f vmlinux.gz vmlinux.bz2 - -install: - sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" diff --git a/trunk/arch/m68k/Makefile_mm b/trunk/arch/m68k/Makefile_mm new file mode 100644 index 000000000000..d449b6d5aecf --- /dev/null +++ b/trunk/arch/m68k/Makefile_mm @@ -0,0 +1,121 @@ +# +# m68k/Makefile +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# 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) 1994 by Hamish Macdonald +# + +# override top level makefile +AS += -m68020 +LDFLAGS := -m m68kelf +KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds +ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, \ + m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-) + endif +endif + +ifdef CONFIG_SUN3 +LDFLAGS_vmlinux = -N +endif + +CHECKFLAGS += -D__mc68000__ + +# without -fno-strength-reduce the 53c7xx.c driver fails ;-( +KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 + +# enable processor switch if compiled only for a single cpu +ifndef CONFIG_M68020 +ifndef CONFIG_M68030 + +ifndef CONFIG_M68060 +KBUILD_CFLAGS += -m68040 +endif + +ifndef CONFIG_M68040 +KBUILD_CFLAGS += -m68060 +endif + +endif +endif + +ifdef CONFIG_KGDB +# If configured for kgdb support, include debugging infos and keep the +# frame pointer +KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g +endif + +ifndef CONFIG_SUN3 +head-y := arch/m68k/kernel/head.o +else +head-y := arch/m68k/kernel/sun3-head.o +endif + +core-y += arch/m68k/kernel/ arch/m68k/mm/ +libs-y += arch/m68k/lib/ + +core-$(CONFIG_Q40) += arch/m68k/q40/ +core-$(CONFIG_AMIGA) += arch/m68k/amiga/ +core-$(CONFIG_ATARI) += arch/m68k/atari/ +core-$(CONFIG_MAC) += arch/m68k/mac/ +core-$(CONFIG_HP300) += arch/m68k/hp300/ +core-$(CONFIG_APOLLO) += arch/m68k/apollo/ +core-$(CONFIG_MVME147) += arch/m68k/mvme147/ +core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/ +core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ +core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ +core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ +core-$(CONFIG_NATFEAT) += arch/m68k/emu/ +core-$(CONFIG_M68040) += arch/m68k/fpsp040/ +core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ +core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ + +all: zImage + +lilo: vmlinux + if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi + if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi + cat vmlinux > $(INSTALL_PATH)/vmlinux + cp System.map $(INSTALL_PATH)/System.map + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + +zImage compressed: vmlinux.gz + +vmlinux.gz: vmlinux + +ifndef CONFIG_KGDB + cp vmlinux vmlinux.tmp + $(STRIP) vmlinux.tmp + gzip -9c vmlinux.tmp >vmlinux.gz + rm vmlinux.tmp +else + gzip -9c vmlinux >vmlinux.gz +endif + +bzImage: vmlinux.bz2 + +vmlinux.bz2: vmlinux + +ifndef CONFIG_KGDB + cp vmlinux vmlinux.tmp + $(STRIP) vmlinux.tmp + bzip2 -1c vmlinux.tmp >vmlinux.bz2 + rm vmlinux.tmp +else + bzip2 -1c vmlinux >vmlinux.bz2 +endif + +archclean: + rm -f vmlinux.gz vmlinux.bz2 + +install: + sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" diff --git a/trunk/arch/m68knommu/Makefile b/trunk/arch/m68k/Makefile_no similarity index 92% rename from trunk/arch/m68knommu/Makefile rename to trunk/arch/m68k/Makefile_no index 589613fed31d..81652ab893e1 100644 --- a/trunk/arch/m68knommu/Makefile +++ b/trunk/arch/m68k/Makefile_no @@ -1,5 +1,5 @@ # -# arch/m68knommu/Makefile +# arch/m68k/Makefile # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive @@ -8,8 +8,6 @@ # (C) Copyright 2002, Greg Ungerer # -KBUILD_DEFCONFIG := m5208evb_defconfig - platform-$(CONFIG_M68328) := 68328 platform-$(CONFIG_M68EZ328) := 68EZ328 platform-$(CONFIG_M68VZ328) := 68VZ328 @@ -82,7 +80,7 @@ cpuclass-$(CONFIG_M68360) := 68360 CPUCLASS := $(cpuclass-y) ifneq ($(CPUCLASS),$(PLATFORM)) -CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/ +CLASSDIR := arch/m68k/platform/$(cpuclass-y)/ endif export PLATFORM BOARD MODEL CPUCLASS @@ -114,13 +112,13 @@ KBUILD_CFLAGS += $(cflags-y) KBUILD_CFLAGS += -D__linux__ KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" -head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o +head-y := arch/m68k/platform/$(cpuclass-y)/head.o -core-y += arch/m68knommu/kernel/ \ - arch/m68knommu/mm/ \ +core-y += arch/m68k/kernel/ \ + arch/m68k/mm/ \ $(CLASSDIR) \ - arch/m68knommu/platform/$(PLATFORM)/ -libs-y += arch/m68knommu/lib/ + arch/m68k/platform/$(PLATFORM)/ +libs-y += arch/m68k/lib/ archclean: diff --git a/trunk/arch/m68knommu/configs/m5208evb_defconfig b/trunk/arch/m68k/configs/m5208evb_defconfig similarity index 97% rename from trunk/arch/m68knommu/configs/m5208evb_defconfig rename to trunk/arch/m68k/configs/m5208evb_defconfig index 2f5655c577af..c1616824e201 100644 --- a/trunk/arch/m68knommu/configs/m5208evb_defconfig +++ b/trunk/arch/m68k/configs/m5208evb_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -37,6 +38,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68knommu/configs/m5249evb_defconfig b/trunk/arch/m68k/configs/m5249evb_defconfig similarity index 97% rename from trunk/arch/m68knommu/configs/m5249evb_defconfig rename to trunk/arch/m68k/configs/m5249evb_defconfig index 16df72bfbd45..a6599e42facf 100644 --- a/trunk/arch/m68knommu/configs/m5249evb_defconfig +++ b/trunk/arch/m68k/configs/m5249evb_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -35,6 +36,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68knommu/configs/m5272c3_defconfig b/trunk/arch/m68k/configs/m5272c3_defconfig similarity index 96% rename from trunk/arch/m68knommu/configs/m5272c3_defconfig rename to trunk/arch/m68k/configs/m5272c3_defconfig index 4e6ea50c7f33..3fa60a57a0f9 100644 --- a/trunk/arch/m68knommu/configs/m5272c3_defconfig +++ b/trunk/arch/m68k/configs/m5272c3_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -33,6 +34,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68knommu/configs/m5275evb_defconfig b/trunk/arch/m68k/configs/m5275evb_defconfig similarity index 97% rename from trunk/arch/m68knommu/configs/m5275evb_defconfig rename to trunk/arch/m68k/configs/m5275evb_defconfig index f3dd74115a34..33c32aeca12b 100644 --- a/trunk/arch/m68knommu/configs/m5275evb_defconfig +++ b/trunk/arch/m68k/configs/m5275evb_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -36,6 +37,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68knommu/configs/m5307c3_defconfig b/trunk/arch/m68k/configs/m5307c3_defconfig similarity index 97% rename from trunk/arch/m68knommu/configs/m5307c3_defconfig rename to trunk/arch/m68k/configs/m5307c3_defconfig index bce0a20c3737..43795f41f7c7 100644 --- a/trunk/arch/m68knommu/configs/m5307c3_defconfig +++ b/trunk/arch/m68k/configs/m5307c3_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -35,6 +36,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68knommu/configs/m5407c3_defconfig b/trunk/arch/m68k/configs/m5407c3_defconfig similarity index 97% rename from trunk/arch/m68knommu/configs/m5407c3_defconfig rename to trunk/arch/m68k/configs/m5407c3_defconfig index 618cc32691f2..72746c57a571 100644 --- a/trunk/arch/m68knommu/configs/m5407c3_defconfig +++ b/trunk/arch/m68k/configs/m5407c3_defconfig @@ -1,3 +1,4 @@ +# CONFIG_MMU is not set CONFIG_EXPERIMENTAL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -35,6 +36,7 @@ CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +# CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/m68k/kernel/Makefile b/trunk/arch/m68k/kernel/Makefile index 55d5d6b680a2..c482ebc9dd54 100644 --- a/trunk/arch/m68k/kernel/Makefile +++ b/trunk/arch/m68k/kernel/Makefile @@ -1,17 +1,5 @@ -# -# Makefile for the linux kernel. -# - -ifndef CONFIG_SUN3 - extra-y := head.o +ifdef CONFIG_MMU +include arch/m68k/kernel/Makefile_mm else - extra-y := sun3-head.o +include arch/m68k/kernel/Makefile_no endif -extra-y += vmlinux.lds - -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ - sys_m68k.o time.o setup.o m68k_ksyms.o devres.o - -devres-y = ../../../kernel/irq/devres.o - -obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo diff --git a/trunk/arch/m68k/kernel/Makefile_mm b/trunk/arch/m68k/kernel/Makefile_mm new file mode 100644 index 000000000000..55d5d6b680a2 --- /dev/null +++ b/trunk/arch/m68k/kernel/Makefile_mm @@ -0,0 +1,17 @@ +# +# Makefile for the linux kernel. +# + +ifndef CONFIG_SUN3 + extra-y := head.o +else + extra-y := sun3-head.o +endif +extra-y += vmlinux.lds + +obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ + sys_m68k.o time.o setup.o m68k_ksyms.o devres.o + +devres-y = ../../../kernel/irq/devres.o + +obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo diff --git a/trunk/arch/m68knommu/kernel/Makefile b/trunk/arch/m68k/kernel/Makefile_no similarity index 100% rename from trunk/arch/m68knommu/kernel/Makefile rename to trunk/arch/m68k/kernel/Makefile_no diff --git a/trunk/arch/m68k/kernel/asm-offsets.c b/trunk/arch/m68k/kernel/asm-offsets.c index 78e59b82ebc3..59a69a5c62f2 100644 --- a/trunk/arch/m68k/kernel/asm-offsets.c +++ b/trunk/arch/m68k/kernel/asm-offsets.c @@ -1,100 +1,5 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#define ASM_OFFSETS_C - -#include -#include -#include -#include -#include -#include -#include -#include - -int main(void) -{ - /* offsets into the task struct */ - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); #ifdef CONFIG_MMU - DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); +#include "asm-offsets_mm.c" +#else +#include "asm-offsets_no.c" #endif - - /* offsets into the thread struct */ - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); - DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); - DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); - DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); - DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); - DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); - - /* offsets into the thread_info struct */ - DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); - - /* offsets into the pt_regs */ - DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); - DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); - DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); - DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); - DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); - DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); - DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); - /* bitfields are a bit difficult */ - DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); - - /* offsets into the bi_record struct */ - DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); - DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); - DEFINE(BIR_DATA, offsetof(struct bi_record, data)); - - /* offsets into font_desc (drivers/video/console/font.h) */ - DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); - DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); - DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); - DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); - DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); - DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); - - /* signal defines */ - DEFINE(LSIGSEGV, SIGSEGV); - DEFINE(LSEGV_MAPERR, SEGV_MAPERR); - DEFINE(LSIGTRAP, SIGTRAP); - DEFINE(LTRAP_TRACE, TRAP_TRACE); - - /* offsets into the custom struct */ - DEFINE(CUSTOMBASE, &amiga_custom); - DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); - DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); - DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); - DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); - DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); - DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); - DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); - DEFINE(CIAABASE, &ciaa); - DEFINE(CIABBASE, &ciab); - DEFINE(C_PRA, offsetof(struct CIA, pra)); - DEFINE(ZTWOBASE, zTwoBase); - - return 0; -} diff --git a/trunk/arch/m68k/kernel/asm-offsets_mm.c b/trunk/arch/m68k/kernel/asm-offsets_mm.c new file mode 100644 index 000000000000..78e59b82ebc3 --- /dev/null +++ b/trunk/arch/m68k/kernel/asm-offsets_mm.c @@ -0,0 +1,100 @@ +/* + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#define ASM_OFFSETS_C + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + /* offsets into the task struct */ + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); + DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); + DEFINE(TASK_MM, offsetof(struct task_struct, mm)); +#ifdef CONFIG_MMU + DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); +#endif + + /* offsets into the thread struct */ + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); + DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); + DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); + + /* offsets into the thread_info struct */ + DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); + + /* offsets into the pt_regs */ + DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); + DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); + /* bitfields are a bit difficult */ + DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); + + /* offsets into the irq_cpustat_t struct */ + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); + + /* offsets into the bi_record struct */ + DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); + DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); + DEFINE(BIR_DATA, offsetof(struct bi_record, data)); + + /* offsets into font_desc (drivers/video/console/font.h) */ + DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); + DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); + DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); + DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); + DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); + DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); + + /* signal defines */ + DEFINE(LSIGSEGV, SIGSEGV); + DEFINE(LSEGV_MAPERR, SEGV_MAPERR); + DEFINE(LSIGTRAP, SIGTRAP); + DEFINE(LTRAP_TRACE, TRAP_TRACE); + + /* offsets into the custom struct */ + DEFINE(CUSTOMBASE, &amiga_custom); + DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); + DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); + DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); + DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); + DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); + DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); + DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); + DEFINE(CIAABASE, &ciaa); + DEFINE(CIABBASE, &ciab); + DEFINE(C_PRA, offsetof(struct CIA, pra)); + DEFINE(ZTWOBASE, zTwoBase); + + return 0; +} diff --git a/trunk/arch/m68knommu/kernel/asm-offsets.c b/trunk/arch/m68k/kernel/asm-offsets_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/asm-offsets.c rename to trunk/arch/m68k/kernel/asm-offsets_no.c diff --git a/trunk/arch/m68k/kernel/dma.c b/trunk/arch/m68k/kernel/dma.c index 4bbb3c2a8880..90e8cb726c8c 100644 --- a/trunk/arch/m68k/kernel/dma.c +++ b/trunk/arch/m68k/kernel/dma.c @@ -1,130 +1,5 @@ -/* - * 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. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include - -#include - -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t flag) -{ - struct page *page, **map; - pgprot_t pgprot; - void *addr; - int i, order; - - pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); - - size = PAGE_ALIGN(size); - order = get_order(size); - - page = alloc_pages(flag, order); - if (!page) - return NULL; - - *handle = page_to_phys(page); - map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); - if (!map) { - __free_pages(page, order); - return NULL; - } - split_page(page, order); - - order = 1 << order; - size >>= PAGE_SHIFT; - map[0] = page; - for (i = 1; i < size; i++) - map[i] = page + i; - for (; i < order; i++) - __free_page(page + i); - pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); - if (CPU_IS_040_OR_060) - pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; - else - pgprot_val(pgprot) |= _PAGE_NOCACHE030; - addr = vmap(map, size, VM_MAP, pgprot); - kfree(map); - - return addr; -} -EXPORT_SYMBOL(dma_alloc_coherent); - -void dma_free_coherent(struct device *dev, size_t size, - void *addr, dma_addr_t handle) -{ - pr_debug("dma_free_coherent: %p, %x\n", addr, handle); - vfree(addr); -} -EXPORT_SYMBOL(dma_free_coherent); - -void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, - size_t size, enum dma_data_direction dir) -{ - switch (dir) { - case DMA_TO_DEVICE: - cache_push(handle, size); - break; - case DMA_FROM_DEVICE: - cache_clear(handle, size); - break; - default: - if (printk_ratelimit()) - printk("dma_sync_single_for_device: unsupported dir %u\n", dir); - break; - } -} -EXPORT_SYMBOL(dma_sync_single_for_device); - -void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; sg++, i++) - dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); -} -EXPORT_SYMBOL(dma_sync_sg_for_device); - -dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, - enum dma_data_direction dir) -{ - dma_addr_t handle = virt_to_bus(addr); - - dma_sync_single_for_device(dev, handle, size, dir); - return handle; -} -EXPORT_SYMBOL(dma_map_single); - -dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ - dma_addr_t handle = page_to_phys(page) + offset; - - dma_sync_single_for_device(dev, handle, size, dir); - return handle; -} -EXPORT_SYMBOL(dma_map_page); - -int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; sg++, i++) { - sg->dma_address = sg_phys(sg); - dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); - } - return nents; -} -EXPORT_SYMBOL(dma_map_sg); +#ifdef CONFIG_MMU +#include "dma_mm.c" +#else +#include "dma_no.c" +#endif diff --git a/trunk/arch/m68k/kernel/dma_mm.c b/trunk/arch/m68k/kernel/dma_mm.c new file mode 100644 index 000000000000..4bbb3c2a8880 --- /dev/null +++ b/trunk/arch/m68k/kernel/dma_mm.c @@ -0,0 +1,130 @@ +/* + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include + +#include + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *handle, gfp_t flag) +{ + struct page *page, **map; + pgprot_t pgprot; + void *addr; + int i, order; + + pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages(flag, order); + if (!page) + return NULL; + + *handle = page_to_phys(page); + map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); + if (!map) { + __free_pages(page, order); + return NULL; + } + split_page(page, order); + + order = 1 << order; + size >>= PAGE_SHIFT; + map[0] = page; + for (i = 1; i < size; i++) + map[i] = page + i; + for (; i < order; i++) + __free_page(page + i); + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + if (CPU_IS_040_OR_060) + pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; + else + pgprot_val(pgprot) |= _PAGE_NOCACHE030; + addr = vmap(map, size, VM_MAP, pgprot); + kfree(map); + + return addr; +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *addr, dma_addr_t handle) +{ + pr_debug("dma_free_coherent: %p, %x\n", addr, handle); + vfree(addr); +} +EXPORT_SYMBOL(dma_free_coherent); + +void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, + size_t size, enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_push(handle, size); + break; + case DMA_FROM_DEVICE: + cache_clear(handle, size); + break; + default: + if (printk_ratelimit()) + printk("dma_sync_single_for_device: unsupported dir %u\n", dir); + break; + } +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = virt_to_bus(addr); + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = page_to_phys(page) + offset; + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) { + sg->dma_address = sg_phys(sg); + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); + } + return nents; +} +EXPORT_SYMBOL(dma_map_sg); diff --git a/trunk/arch/m68knommu/kernel/dma.c b/trunk/arch/m68k/kernel/dma_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/dma.c rename to trunk/arch/m68k/kernel/dma_no.c diff --git a/trunk/arch/m68k/kernel/entry.S b/trunk/arch/m68k/kernel/entry.S index 1559dea36e55..081cf96f243b 100644 --- a/trunk/arch/m68k/kernel/entry.S +++ b/trunk/arch/m68k/kernel/entry.S @@ -1,753 +1,5 @@ -/* -*- mode: asm -*- - * - * linux/arch/m68k/kernel/entry.S - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file README.legal in the main directory of this archive - * for more details. - * - * Linux/m68k support by Hamish Macdonald - * - * 68060 fixes by Jesper Skov - * - */ - -/* - * entry.S contains the system-call and fault low-level handling routines. - * This also contains the timer-interrupt handler, as well as all interrupts - * and faults that can result in a task-switch. - * - * NOTE: This code handles signal-recognition, which happens every time - * after a timer-interrupt and after each system call. - * - */ - -/* - * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so - * all pointers that used to be 'current' are now entry - * number 0 in the 'current_set' list. - * - * 6/05/00 RZ: addedd writeback completion after return from sighandler - * for 68040 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -.globl system_call, buserr, trap, resume -.globl sys_call_table -.globl sys_fork, sys_clone, sys_vfork -.globl ret_from_interrupt, bad_interrupt -.globl auto_irqhandler_fixup -.globl user_irqvec_fixup, user_irqhandler_fixup - -.text -ENTRY(buserr) - SAVE_ALL_INT - GET_CURRENT(%d0) - movel %sp,%sp@- | stack frame pointer argument - bsrl buserr_c - addql #4,%sp - jra .Lret_from_exception - -ENTRY(trap) - SAVE_ALL_INT - GET_CURRENT(%d0) - movel %sp,%sp@- | stack frame pointer argument - bsrl trap_c - addql #4,%sp - jra .Lret_from_exception - - | After a fork we jump here directly from resume, - | so that %d1 contains the previous task - | schedule_tail now used regardless of CONFIG_SMP -ENTRY(ret_from_fork) - movel %d1,%sp@- - jsr schedule_tail - addql #4,%sp - jra .Lret_from_exception - -do_trace_entry: - movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace - subql #4,%sp - SAVE_SWITCH_STACK - jbsr syscall_trace - RESTORE_SWITCH_STACK - addql #4,%sp - movel %sp@(PT_OFF_ORIG_D0),%d0 - cmpl #NR_syscalls,%d0 - jcs syscall -badsys: - movel #-ENOSYS,%sp@(PT_OFF_D0) - jra ret_from_syscall - -do_trace_exit: - subql #4,%sp - SAVE_SWITCH_STACK - jbsr syscall_trace - RESTORE_SWITCH_STACK - addql #4,%sp - jra .Lret_from_exception - -ENTRY(ret_from_signal) - tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) - jge 1f - jbsr syscall_trace -1: RESTORE_SWITCH_STACK - addql #4,%sp -/* on 68040 complete pending writebacks if any */ -#ifdef CONFIG_M68040 - bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0 - subql #7,%d0 | bus error frame ? - jbne 1f - movel %sp,%sp@- - jbsr berr_040cleanup - addql #4,%sp -1: +#ifdef CONFIG_MMU +#include "entry_mm.S" +#else +#include "entry_no.S" #endif - jra .Lret_from_exception - -ENTRY(system_call) - SAVE_ALL_SYS - - GET_CURRENT(%d1) - | save top of frame - movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - - | syscall trace? - tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) - jmi do_trace_entry - cmpl #NR_syscalls,%d0 - jcc badsys -syscall: - jbsr @(sys_call_table,%d0:l:4)@(0) - movel %d0,%sp@(PT_OFF_D0) | save the return value -ret_from_syscall: - |oriw #0x0700,%sr - movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 - jne syscall_exit_work -1: RESTORE_ALL - -syscall_exit_work: - btst #5,%sp@(PT_OFF_SR) | check if returning to kernel - bnes 1b | if so, skip resched, signals - lslw #1,%d0 - jcs do_trace_exit - jmi do_delayed_trace - lslw #8,%d0 - jmi do_signal_return - pea resume_userspace - jra schedule - - -ENTRY(ret_from_exception) -.Lret_from_exception: - btst #5,%sp@(PT_OFF_SR) | check if returning to kernel - bnes 1f | if so, skip resched, signals - | only allow interrupts when we are really the last one on the - | kernel stack, otherwise stack overflow can occur during - | heavy interrupt load - andw #ALLOWINT,%sr - -resume_userspace: - moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 - jne exit_work -1: RESTORE_ALL - -exit_work: - | save top of frame - movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - lslb #1,%d0 - jmi do_signal_return - pea resume_userspace - jra schedule - - -do_signal_return: - |andw #ALLOWINT,%sr - subql #4,%sp | dummy return address - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) - bsrl do_signal - addql #4,%sp - RESTORE_SWITCH_STACK - addql #4,%sp - jbra resume_userspace - -do_delayed_trace: - bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR - pea 1 | send SIGTRAP - movel %curptr,%sp@- - pea LSIGTRAP - jbsr send_sig - addql #8,%sp - addql #4,%sp - jbra resume_userspace - - -/* This is the main interrupt handler for autovector interrupts */ - -ENTRY(auto_inthandler) - SAVE_ALL_INT - GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - | put exception # in d0 - bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 - subw #VEC_SPUR,%d0 - - movel %sp,%sp@- - movel %d0,%sp@- | put vector # on stack -auto_irqhandler_fixup = . + 2 - jsr __m68k_handle_int | process the IRQ - addql #8,%sp | pop parameters off stack - -ret_from_interrupt: - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - jeq ret_from_last_interrupt -2: RESTORE_ALL - - ALIGN -ret_from_last_interrupt: - moveq #(~ALLOWINT>>8)&0xff,%d0 - andb %sp@(PT_OFF_SR),%d0 - jne 2b - - /* check if we need to do software interrupts */ - tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING - jeq .Lret_from_exception - pea ret_from_exception - jra do_softirq - -/* Handler for user defined interrupt vectors */ - -ENTRY(user_inthandler) - SAVE_ALL_INT - GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - | put exception # in d0 - bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 -user_irqvec_fixup = . + 2 - subw #VEC_USER,%d0 - - movel %sp,%sp@- - movel %d0,%sp@- | put vector # on stack -user_irqhandler_fixup = . + 2 - jsr __m68k_handle_int | process the IRQ - addql #8,%sp | pop parameters off stack - - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - jeq ret_from_last_interrupt - RESTORE_ALL - -/* Handler for uninitialized and spurious interrupts */ - -ENTRY(bad_inthandler) - SAVE_ALL_INT - GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - - movel %sp,%sp@- - jsr handle_badint - addql #4,%sp - - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) - jeq ret_from_last_interrupt - RESTORE_ALL - - -ENTRY(sys_fork) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) - jbsr m68k_fork - addql #4,%sp - RESTORE_SWITCH_STACK - rts - -ENTRY(sys_clone) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) - jbsr m68k_clone - addql #4,%sp - RESTORE_SWITCH_STACK - rts - -ENTRY(sys_vfork) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) - jbsr m68k_vfork - addql #4,%sp - RESTORE_SWITCH_STACK - rts - -ENTRY(sys_sigreturn) - SAVE_SWITCH_STACK - jbsr do_sigreturn - RESTORE_SWITCH_STACK - rts - -ENTRY(sys_rt_sigreturn) - SAVE_SWITCH_STACK - jbsr do_rt_sigreturn - RESTORE_SWITCH_STACK - rts - -resume: - /* - * Beware - when entering resume, prev (the current task) is - * in a0, next (the new task) is in a1,so don't change these - * registers until their contents are no longer needed. - */ - - /* save sr */ - movew %sr,%a0@(TASK_THREAD+THREAD_SR) - - /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ - movec %sfc,%d0 - movew %d0,%a0@(TASK_THREAD+THREAD_FS) - - /* save usp */ - /* it is better to use a movel here instead of a movew 8*) */ - movec %usp,%d0 - movel %d0,%a0@(TASK_THREAD+THREAD_USP) - - /* save non-scratch registers on stack */ - SAVE_SWITCH_STACK - - /* save current kernel stack pointer */ - movel %sp,%a0@(TASK_THREAD+THREAD_KSP) - - /* save floating point context */ -#ifndef CONFIG_M68KFPU_EMU_ONLY -#ifdef CONFIG_M68KFPU_EMU - tstl m68k_fputype - jeq 3f -#endif - fsave %a0@(TASK_THREAD+THREAD_FPSTATE) - -#if defined(CONFIG_M68060) -#if !defined(CPU_M68060_ONLY) - btst #3,m68k_cputype+3 - beqs 1f -#endif - /* The 060 FPU keeps status in bits 15-8 of the first longword */ - tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) - jeq 3f -#if !defined(CPU_M68060_ONLY) - jra 2f -#endif -#endif /* CONFIG_M68060 */ -#if !defined(CPU_M68060_ONLY) -1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE) - jeq 3f -#endif -2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG) - fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL) -3: -#endif /* CONFIG_M68KFPU_EMU_ONLY */ - /* Return previous task in %d1 */ - movel %curptr,%d1 - - /* switch to new task (a1 contains new task) */ - movel %a1,%curptr - - /* restore floating point context */ -#ifndef CONFIG_M68KFPU_EMU_ONLY -#ifdef CONFIG_M68KFPU_EMU - tstl m68k_fputype - jeq 4f -#endif -#if defined(CONFIG_M68060) -#if !defined(CPU_M68060_ONLY) - btst #3,m68k_cputype+3 - beqs 1f -#endif - /* The 060 FPU keeps status in bits 15-8 of the first longword */ - tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2) - jeq 3f -#if !defined(CPU_M68060_ONLY) - jra 2f -#endif -#endif /* CONFIG_M68060 */ -#if !defined(CPU_M68060_ONLY) -1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE) - jeq 3f -#endif -2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7 - fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar -3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE) -4: -#endif /* CONFIG_M68KFPU_EMU_ONLY */ - - /* restore the kernel stack pointer */ - movel %a1@(TASK_THREAD+THREAD_KSP),%sp - - /* restore non-scratch registers */ - RESTORE_SWITCH_STACK - - /* restore user stack pointer */ - movel %a1@(TASK_THREAD+THREAD_USP),%a0 - movel %a0,%usp - - /* restore fs (sfc,%dfc) */ - movew %a1@(TASK_THREAD+THREAD_FS),%a0 - movec %a0,%sfc - movec %a0,%dfc - - /* restore status register */ - movew %a1@(TASK_THREAD+THREAD_SR),%sr - - rts - -.data -ALIGN -sys_call_table: - .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ - .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_chown16 - .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 - .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_old_select - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long sys_old_readdir - .long sys_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 for i386 */ - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall - .long sys_ni_syscall /* 110 */ /* iopl for i386 */ - .long sys_vhangup - .long sys_ni_syscall /* obsolete idle() syscall */ - .long sys_ni_syscall /* vm86old for i386 */ - .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_cacheflush /* modify_ldt for i386 */ - .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_getpagesize - .long sys_ni_syscall /* old sys_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_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_lchown16; - .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_chown - .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_lchown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_ni_syscall - .long sys_ni_syscall - .long sys_getdents64 /* 220 */ - .long sys_gettid - .long sys_tkill - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr /* 225 */ - .long sys_getxattr - .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr /* 230 */ - .long sys_flistxattr - .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_futex /* 235 */ - .long sys_sendfile64 - .long sys_mincore - .long sys_madvise - .long sys_fcntl64 - .long sys_readahead /* 240 */ - .long sys_io_setup - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel /* 245 */ - .long sys_fadvise64 - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 250 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 255 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 260 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 265 */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_mbind - .long sys_get_mempolicy - .long sys_set_mempolicy /* 270 */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive - .long sys_mq_notify /* 275 */ - .long sys_mq_getsetattr - .long sys_waitid - .long sys_ni_syscall /* for sys_vserver */ - .long sys_add_key - .long sys_request_key /* 280 */ - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init - .long sys_inotify_add_watch /* 285 */ - .long sys_inotify_rm_watch - .long sys_migrate_pages - .long sys_openat - .long sys_mkdirat - .long sys_mknodat /* 290 */ - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 - .long sys_unlinkat - .long sys_renameat /* 295 */ - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat - .long sys_fchmodat - .long sys_faccessat /* 300 */ - .long sys_ni_syscall /* Reserved for pselect6 */ - .long sys_ni_syscall /* Reserved for ppoll */ - .long sys_unshare - .long sys_set_robust_list - .long sys_get_robust_list /* 305 */ - .long sys_splice - .long sys_sync_file_range - .long sys_tee - .long sys_vmsplice - .long sys_move_pages /* 310 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_kexec_load - .long sys_getcpu - .long sys_epoll_pwait /* 315 */ - .long sys_utimensat - .long sys_signalfd - .long sys_timerfd_create - .long sys_eventfd - .long sys_fallocate /* 320 */ - .long sys_timerfd_settime - .long sys_timerfd_gettime - .long sys_signalfd4 - .long sys_eventfd2 - .long sys_epoll_create1 /* 325 */ - .long sys_dup3 - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev /* 330 */ - .long sys_rt_tgsigqueueinfo - .long sys_perf_event_open - .long sys_get_thread_area - .long sys_set_thread_area - .long sys_atomic_cmpxchg_32 /* 335 */ - .long sys_atomic_barrier - .long sys_fanotify_init - .long sys_fanotify_mark - .long sys_prlimit64 - diff --git a/trunk/arch/m68k/kernel/entry_mm.S b/trunk/arch/m68k/kernel/entry_mm.S new file mode 100644 index 000000000000..1559dea36e55 --- /dev/null +++ b/trunk/arch/m68k/kernel/entry_mm.S @@ -0,0 +1,753 @@ +/* -*- mode: asm -*- + * + * linux/arch/m68k/kernel/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + * Linux/m68k support by Hamish Macdonald + * + * 68060 fixes by Jesper Skov + * + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + */ + +/* + * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so + * all pointers that used to be 'current' are now entry + * number 0 in the 'current_set' list. + * + * 6/05/00 RZ: addedd writeback completion after return from sighandler + * for 68040 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +.globl system_call, buserr, trap, resume +.globl sys_call_table +.globl sys_fork, sys_clone, sys_vfork +.globl ret_from_interrupt, bad_interrupt +.globl auto_irqhandler_fixup +.globl user_irqvec_fixup, user_irqhandler_fixup + +.text +ENTRY(buserr) + SAVE_ALL_INT + GET_CURRENT(%d0) + movel %sp,%sp@- | stack frame pointer argument + bsrl buserr_c + addql #4,%sp + jra .Lret_from_exception + +ENTRY(trap) + SAVE_ALL_INT + GET_CURRENT(%d0) + movel %sp,%sp@- | stack frame pointer argument + bsrl trap_c + addql #4,%sp + jra .Lret_from_exception + + | After a fork we jump here directly from resume, + | so that %d1 contains the previous task + | schedule_tail now used regardless of CONFIG_SMP +ENTRY(ret_from_fork) + movel %d1,%sp@- + jsr schedule_tail + addql #4,%sp + jra .Lret_from_exception + +do_trace_entry: + movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace + subql #4,%sp + SAVE_SWITCH_STACK + jbsr syscall_trace + RESTORE_SWITCH_STACK + addql #4,%sp + movel %sp@(PT_OFF_ORIG_D0),%d0 + cmpl #NR_syscalls,%d0 + jcs syscall +badsys: + movel #-ENOSYS,%sp@(PT_OFF_D0) + jra ret_from_syscall + +do_trace_exit: + subql #4,%sp + SAVE_SWITCH_STACK + jbsr syscall_trace + RESTORE_SWITCH_STACK + addql #4,%sp + jra .Lret_from_exception + +ENTRY(ret_from_signal) + tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) + jge 1f + jbsr syscall_trace +1: RESTORE_SWITCH_STACK + addql #4,%sp +/* on 68040 complete pending writebacks if any */ +#ifdef CONFIG_M68040 + bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0 + subql #7,%d0 | bus error frame ? + jbne 1f + movel %sp,%sp@- + jbsr berr_040cleanup + addql #4,%sp +1: +#endif + jra .Lret_from_exception + +ENTRY(system_call) + SAVE_ALL_SYS + + GET_CURRENT(%d1) + | save top of frame + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) + + | syscall trace? + tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) + jmi do_trace_entry + cmpl #NR_syscalls,%d0 + jcc badsys +syscall: + jbsr @(sys_call_table,%d0:l:4)@(0) + movel %d0,%sp@(PT_OFF_D0) | save the return value +ret_from_syscall: + |oriw #0x0700,%sr + movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 + jne syscall_exit_work +1: RESTORE_ALL + +syscall_exit_work: + btst #5,%sp@(PT_OFF_SR) | check if returning to kernel + bnes 1b | if so, skip resched, signals + lslw #1,%d0 + jcs do_trace_exit + jmi do_delayed_trace + lslw #8,%d0 + jmi do_signal_return + pea resume_userspace + jra schedule + + +ENTRY(ret_from_exception) +.Lret_from_exception: + btst #5,%sp@(PT_OFF_SR) | check if returning to kernel + bnes 1f | if so, skip resched, signals + | only allow interrupts when we are really the last one on the + | kernel stack, otherwise stack overflow can occur during + | heavy interrupt load + andw #ALLOWINT,%sr + +resume_userspace: + moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 + jne exit_work +1: RESTORE_ALL + +exit_work: + | save top of frame + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) + lslb #1,%d0 + jmi do_signal_return + pea resume_userspace + jra schedule + + +do_signal_return: + |andw #ALLOWINT,%sr + subql #4,%sp | dummy return address + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + bsrl do_signal + addql #4,%sp + RESTORE_SWITCH_STACK + addql #4,%sp + jbra resume_userspace + +do_delayed_trace: + bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR + pea 1 | send SIGTRAP + movel %curptr,%sp@- + pea LSIGTRAP + jbsr send_sig + addql #8,%sp + addql #4,%sp + jbra resume_userspace + + +/* This is the main interrupt handler for autovector interrupts */ + +ENTRY(auto_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + | put exception # in d0 + bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 + subw #VEC_SPUR,%d0 + + movel %sp,%sp@- + movel %d0,%sp@- | put vector # on stack +auto_irqhandler_fixup = . + 2 + jsr __m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack + +ret_from_interrupt: + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt +2: RESTORE_ALL + + ALIGN +ret_from_last_interrupt: + moveq #(~ALLOWINT>>8)&0xff,%d0 + andb %sp@(PT_OFF_SR),%d0 + jne 2b + + /* check if we need to do software interrupts */ + tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING + jeq .Lret_from_exception + pea ret_from_exception + jra do_softirq + +/* Handler for user defined interrupt vectors */ + +ENTRY(user_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + | put exception # in d0 + bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 +user_irqvec_fixup = . + 2 + subw #VEC_USER,%d0 + + movel %sp,%sp@- + movel %d0,%sp@- | put vector # on stack +user_irqhandler_fixup = . + 2 + jsr __m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL + +/* Handler for uninitialized and spurious interrupts */ + +ENTRY(bad_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + + movel %sp,%sp@- + jsr handle_badint + addql #4,%sp + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL + + +ENTRY(sys_fork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_fork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_clone) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_clone + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_vfork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_vfork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigreturn) + SAVE_SWITCH_STACK + jbsr do_sigreturn + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigreturn) + SAVE_SWITCH_STACK + jbsr do_rt_sigreturn + RESTORE_SWITCH_STACK + rts + +resume: + /* + * Beware - when entering resume, prev (the current task) is + * in a0, next (the new task) is in a1,so don't change these + * registers until their contents are no longer needed. + */ + + /* save sr */ + movew %sr,%a0@(TASK_THREAD+THREAD_SR) + + /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ + movec %sfc,%d0 + movew %d0,%a0@(TASK_THREAD+THREAD_FS) + + /* save usp */ + /* it is better to use a movel here instead of a movew 8*) */ + movec %usp,%d0 + movel %d0,%a0@(TASK_THREAD+THREAD_USP) + + /* save non-scratch registers on stack */ + SAVE_SWITCH_STACK + + /* save current kernel stack pointer */ + movel %sp,%a0@(TASK_THREAD+THREAD_KSP) + + /* save floating point context */ +#ifndef CONFIG_M68KFPU_EMU_ONLY +#ifdef CONFIG_M68KFPU_EMU + tstl m68k_fputype + jeq 3f +#endif + fsave %a0@(TASK_THREAD+THREAD_FPSTATE) + +#if defined(CONFIG_M68060) +#if !defined(CPU_M68060_ONLY) + btst #3,m68k_cputype+3 + beqs 1f +#endif + /* The 060 FPU keeps status in bits 15-8 of the first longword */ + tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) + jeq 3f +#if !defined(CPU_M68060_ONLY) + jra 2f +#endif +#endif /* CONFIG_M68060 */ +#if !defined(CPU_M68060_ONLY) +1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE) + jeq 3f +#endif +2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG) + fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL) +3: +#endif /* CONFIG_M68KFPU_EMU_ONLY */ + /* Return previous task in %d1 */ + movel %curptr,%d1 + + /* switch to new task (a1 contains new task) */ + movel %a1,%curptr + + /* restore floating point context */ +#ifndef CONFIG_M68KFPU_EMU_ONLY +#ifdef CONFIG_M68KFPU_EMU + tstl m68k_fputype + jeq 4f +#endif +#if defined(CONFIG_M68060) +#if !defined(CPU_M68060_ONLY) + btst #3,m68k_cputype+3 + beqs 1f +#endif + /* The 060 FPU keeps status in bits 15-8 of the first longword */ + tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2) + jeq 3f +#if !defined(CPU_M68060_ONLY) + jra 2f +#endif +#endif /* CONFIG_M68060 */ +#if !defined(CPU_M68060_ONLY) +1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE) + jeq 3f +#endif +2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7 + fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar +3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE) +4: +#endif /* CONFIG_M68KFPU_EMU_ONLY */ + + /* restore the kernel stack pointer */ + movel %a1@(TASK_THREAD+THREAD_KSP),%sp + + /* restore non-scratch registers */ + RESTORE_SWITCH_STACK + + /* restore user stack pointer */ + movel %a1@(TASK_THREAD+THREAD_USP),%a0 + movel %a0,%usp + + /* restore fs (sfc,%dfc) */ + movew %a1@(TASK_THREAD+THREAD_FS),%a0 + movec %a0,%sfc + movec %a0,%dfc + + /* restore status register */ + movew %a1@(TASK_THREAD+THREAD_SR),%sr + + rts + +.data +ALIGN +sys_call_table: + .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ + .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_chown16 + .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 + .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_old_select + .long sys_symlink + .long sys_lstat + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_swapon + .long sys_reboot + .long sys_old_readdir + .long sys_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 for i386 */ + .long sys_socketcall + .long sys_syslog + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_ni_syscall + .long sys_ni_syscall /* 110 */ /* iopl for i386 */ + .long sys_vhangup + .long sys_ni_syscall /* obsolete idle() syscall */ + .long sys_ni_syscall /* vm86old for i386 */ + .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_cacheflush /* modify_ldt for i386 */ + .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_getpagesize + .long sys_ni_syscall /* old sys_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_pread64 /* 180 */ + .long sys_pwrite64 + .long sys_lchown16; + .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_chown + .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_lchown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_ni_syscall + .long sys_ni_syscall + .long sys_getdents64 /* 220 */ + .long sys_gettid + .long sys_tkill + .long sys_setxattr + .long sys_lsetxattr + .long sys_fsetxattr /* 225 */ + .long sys_getxattr + .long sys_lgetxattr + .long sys_fgetxattr + .long sys_listxattr + .long sys_llistxattr /* 230 */ + .long sys_flistxattr + .long sys_removexattr + .long sys_lremovexattr + .long sys_fremovexattr + .long sys_futex /* 235 */ + .long sys_sendfile64 + .long sys_mincore + .long sys_madvise + .long sys_fcntl64 + .long sys_readahead /* 240 */ + .long sys_io_setup + .long sys_io_destroy + .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel /* 245 */ + .long sys_fadvise64 + .long sys_exit_group + .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl /* 250 */ + .long sys_epoll_wait + .long sys_remap_file_pages + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime /* 255 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 260 */ + .long sys_clock_getres + .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 265 */ + .long sys_utimes + .long sys_fadvise64_64 + .long sys_mbind + .long sys_get_mempolicy + .long sys_set_mempolicy /* 270 */ + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive + .long sys_mq_notify /* 275 */ + .long sys_mq_getsetattr + .long sys_waitid + .long sys_ni_syscall /* for sys_vserver */ + .long sys_add_key + .long sys_request_key /* 280 */ + .long sys_keyctl + .long sys_ioprio_set + .long sys_ioprio_get + .long sys_inotify_init + .long sys_inotify_add_watch /* 285 */ + .long sys_inotify_rm_watch + .long sys_migrate_pages + .long sys_openat + .long sys_mkdirat + .long sys_mknodat /* 290 */ + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 + .long sys_unlinkat + .long sys_renameat /* 295 */ + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat + .long sys_fchmodat + .long sys_faccessat /* 300 */ + .long sys_ni_syscall /* Reserved for pselect6 */ + .long sys_ni_syscall /* Reserved for ppoll */ + .long sys_unshare + .long sys_set_robust_list + .long sys_get_robust_list /* 305 */ + .long sys_splice + .long sys_sync_file_range + .long sys_tee + .long sys_vmsplice + .long sys_move_pages /* 310 */ + .long sys_sched_setaffinity + .long sys_sched_getaffinity + .long sys_kexec_load + .long sys_getcpu + .long sys_epoll_pwait /* 315 */ + .long sys_utimensat + .long sys_signalfd + .long sys_timerfd_create + .long sys_eventfd + .long sys_fallocate /* 320 */ + .long sys_timerfd_settime + .long sys_timerfd_gettime + .long sys_signalfd4 + .long sys_eventfd2 + .long sys_epoll_create1 /* 325 */ + .long sys_dup3 + .long sys_pipe2 + .long sys_inotify_init1 + .long sys_preadv + .long sys_pwritev /* 330 */ + .long sys_rt_tgsigqueueinfo + .long sys_perf_event_open + .long sys_get_thread_area + .long sys_set_thread_area + .long sys_atomic_cmpxchg_32 /* 335 */ + .long sys_atomic_barrier + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 + diff --git a/trunk/arch/m68knommu/kernel/entry.S b/trunk/arch/m68k/kernel/entry_no.S similarity index 100% rename from trunk/arch/m68knommu/kernel/entry.S rename to trunk/arch/m68k/kernel/entry_no.S diff --git a/trunk/arch/m68knommu/kernel/init_task.c b/trunk/arch/m68k/kernel/init_task.c similarity index 100% rename from trunk/arch/m68knommu/kernel/init_task.c rename to trunk/arch/m68k/kernel/init_task.c diff --git a/trunk/arch/m68knommu/kernel/irq.c b/trunk/arch/m68k/kernel/irq.c similarity index 100% rename from trunk/arch/m68knommu/kernel/irq.c rename to trunk/arch/m68k/kernel/irq.c diff --git a/trunk/arch/m68k/kernel/m68k_ksyms.c b/trunk/arch/m68k/kernel/m68k_ksyms.c index d900e77e5363..4752c28ce0ac 100644 --- a/trunk/arch/m68k/kernel/m68k_ksyms.c +++ b/trunk/arch/m68k/kernel/m68k_ksyms.c @@ -1,16 +1,5 @@ -#include - -asmlinkage long long __ashldi3 (long long, int); -asmlinkage long long __ashrdi3 (long long, int); -asmlinkage long long __lshrdi3 (long long, int); -asmlinkage long long __muldi3 (long long, long long); - -/* The following are special because they're not called - explicitly (the C compiler generates them). Fortunately, - their interface isn't gonna change any time soon now, so - it's OK to leave it out of version control. */ -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__muldi3); - +#ifdef CONFIG_MMU +#include "m68k_ksyms_mm.c" +#else +#include "m68k_ksyms_no.c" +#endif diff --git a/trunk/arch/m68k/kernel/m68k_ksyms_mm.c b/trunk/arch/m68k/kernel/m68k_ksyms_mm.c new file mode 100644 index 000000000000..d900e77e5363 --- /dev/null +++ b/trunk/arch/m68k/kernel/m68k_ksyms_mm.c @@ -0,0 +1,16 @@ +#include + +asmlinkage long long __ashldi3 (long long, int); +asmlinkage long long __ashrdi3 (long long, int); +asmlinkage long long __lshrdi3 (long long, int); +asmlinkage long long __muldi3 (long long, long long); + +/* The following are special because they're not called + explicitly (the C compiler generates them). Fortunately, + their interface isn't gonna change any time soon now, so + it's OK to leave it out of version control. */ +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__muldi3); + diff --git a/trunk/arch/m68knommu/kernel/m68k_ksyms.c b/trunk/arch/m68k/kernel/m68k_ksyms_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/m68k_ksyms.c rename to trunk/arch/m68k/kernel/m68k_ksyms_no.c diff --git a/trunk/arch/m68k/kernel/module.c b/trunk/arch/m68k/kernel/module.c index cd6bcb1c957e..7ea203ce6b1a 100644 --- a/trunk/arch/m68k/kernel/module.c +++ b/trunk/arch/m68k/kernel/module.c @@ -1,155 +1,5 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk +#ifdef CONFIG_MMU +#include "module_mm.c" #else -#define DEBUGP(fmt...) +#include "module_no.c" #endif - -#ifdef CONFIG_MODULES - -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - return 0; -} - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location += sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location += sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate_add section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location = rel[i].r_addend + sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location = rel[i].r_addend + sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *mod) -{ - module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); - - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} - -#endif /* CONFIG_MODULES */ - -void module_fixup(struct module *mod, struct m68k_fixup_info *start, - struct m68k_fixup_info *end) -{ - struct m68k_fixup_info *fixup; - - for (fixup = start; fixup < end; fixup++) { - switch (fixup->type) { - case m68k_fixup_memoffset: - *(u32 *)fixup->addr = m68k_memoffset; - break; - case m68k_fixup_vnode_shift: - *(u16 *)fixup->addr += m68k_virt_to_node_shift; - break; - } - } -} diff --git a/trunk/arch/m68k/kernel/module_mm.c b/trunk/arch/m68k/kernel/module_mm.c new file mode 100644 index 000000000000..cd6bcb1c957e --- /dev/null +++ b/trunk/arch/m68k/kernel/module_mm.c @@ -0,0 +1,155 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt...) +#endif + +#ifdef CONFIG_MODULES + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); +} + +/* We don't need anything special. */ +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate_add section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *mod) +{ + module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); + + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} + +#endif /* CONFIG_MODULES */ + +void module_fixup(struct module *mod, struct m68k_fixup_info *start, + struct m68k_fixup_info *end) +{ + struct m68k_fixup_info *fixup; + + for (fixup = start; fixup < end; fixup++) { + switch (fixup->type) { + case m68k_fixup_memoffset: + *(u32 *)fixup->addr = m68k_memoffset; + break; + case m68k_fixup_vnode_shift: + *(u16 *)fixup->addr += m68k_virt_to_node_shift; + break; + } + } +} diff --git a/trunk/arch/m68knommu/kernel/module.c b/trunk/arch/m68k/kernel/module_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/module.c rename to trunk/arch/m68k/kernel/module_no.c diff --git a/trunk/arch/m68k/kernel/process.c b/trunk/arch/m68k/kernel/process.c index c2a1fc23dd75..6cf4bd6e34f8 100644 --- a/trunk/arch/m68k/kernel/process.c +++ b/trunk/arch/m68k/kernel/process.c @@ -1,354 +1,5 @@ -/* - * linux/arch/m68k/kernel/process.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * 68060 fixes by Jesper Skov - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * Initial task/thread structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -union thread_union init_thread_union __init_task_data - __attribute__((aligned(THREAD_SIZE))) = - { INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); - -asmlinkage void ret_from_fork(void); - - -/* - * Return saved PC from a blocked thread - */ -unsigned long thread_saved_pc(struct task_struct *tsk) -{ - struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; - /* Check whether the thread is blocked in resume() */ - if (in_sched_functions(sw->retpc)) - return ((unsigned long *)sw->a6)[1]; - else - return sw->retpc; -} - -/* - * The idle loop on an m68k.. - */ -static void default_idle(void) -{ - if (!need_resched()) -#if defined(MACH_ATARI_ONLY) - /* block out HSYNC on the atari (falcon) */ - __asm__("stop #0x2200" : : : "cc"); +#ifdef CONFIG_MMU +#include "process_mm.c" #else - __asm__("stop #0x2000" : : : "cc"); +#include "process_no.c" #endif -} - -void (*idle)(void) = default_idle; - -/* - * The idle thread. There's no useful work to be - * done, so just try to conserve power and have a - * low exit latency (ie sit in a loop waiting for - * somebody to say that they'd like to reschedule) - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - while (1) { - while (!need_resched()) - idle(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } -} - -void machine_restart(char * __unused) -{ - if (mach_reset) - mach_reset(); - for (;;); -} - -void machine_halt(void) -{ - if (mach_halt) - mach_halt(); - for (;;); -} - -void machine_power_off(void) -{ - if (mach_power_off) - mach_power_off(); - for (;;); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - -void show_regs(struct pt_regs * regs) -{ - printk("\n"); - printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", - regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); - printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", - regs->orig_d0, regs->d0, regs->a2, regs->a1); - printk("A0: %08lx D5: %08lx D4: %08lx\n", - regs->a0, regs->d5, regs->d4); - printk("D3: %08lx D2: %08lx D1: %08lx\n", - regs->d3, regs->d2, regs->d1); - if (!(regs->sr & PS_S)) - printk("USP: %08lx\n", rdusp()); -} - -/* - * Create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - int pid; - mm_segment_t fs; - - fs = get_fs(); - set_fs (KERNEL_DS); - - { - register long retval __asm__ ("d0"); - register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; - - retval = __NR_clone; - __asm__ __volatile__ - ("clrl %%d2\n\t" - "trap #0\n\t" /* Linux/m68k system call */ - "tstl %0\n\t" /* child or parent */ - "jne 1f\n\t" /* parent - jump */ - "lea %%sp@(%c7),%6\n\t" /* reload current */ - "movel %6@,%6\n\t" - "movel %3,%%sp@-\n\t" /* push argument */ - "jsr %4@\n\t" /* call fn */ - "movel %0,%%d1\n\t" /* pass exit value */ - "movel %2,%%d0\n\t" /* exit */ - "trap #0\n" - "1:" - : "+d" (retval) - : "i" (__NR_clone), "i" (__NR_exit), - "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), - "i" (-THREAD_SIZE) - : "d2"); - - pid = retval; - } - - set_fs (fs); - return pid; -} -EXPORT_SYMBOL(kernel_thread); - -void flush_thread(void) -{ - unsigned long zero = 0; - set_fs(USER_DS); - current->thread.fs = __USER_DS; - if (!FPU_IS_EMU) - asm volatile (".chip 68k/68881\n\t" - "frestore %0@\n\t" - ".chip 68k" : : "a" (&zero)); -} - -/* - * "m68k_fork()".. By the time we get here, the - * non-volatile registers have also been saved on the - * stack. We do some ugly pointer stuff here.. (see - * also copy_thread) - */ - -asmlinkage int m68k_fork(struct pt_regs *regs) -{ - return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); -} - -asmlinkage int m68k_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, - NULL, NULL); -} - -asmlinkage int m68k_clone(struct pt_regs *regs) -{ - unsigned long clone_flags; - unsigned long newsp; - int __user *parent_tidptr, *child_tidptr; - - /* syscall2 puts clone_flags in d1 and usp in d2 */ - clone_flags = regs->d1; - newsp = regs->d2; - parent_tidptr = (int __user *)regs->d3; - child_tidptr = (int __user *)regs->d4; - if (!newsp) - newsp = rdusp(); - return do_fork(clone_flags, newsp, regs, 0, - parent_tidptr, child_tidptr); -} - -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) -{ - struct pt_regs * childregs; - struct switch_stack * childstack, *stack; - unsigned long *retp; - - childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; - - *childregs = *regs; - childregs->d0 = 0; - - retp = ((unsigned long *) regs); - stack = ((struct switch_stack *) retp) - 1; - - childstack = ((struct switch_stack *) childregs) - 1; - *childstack = *stack; - childstack->retpc = (unsigned long)ret_from_fork; - - p->thread.usp = usp; - p->thread.ksp = (unsigned long)childstack; - - if (clone_flags & CLONE_SETTLS) - task_thread_info(p)->tp_value = regs->d5; - - /* - * Must save the current SFC/DFC value, NOT the value when - * the parent was last descheduled - RGH 10-08-96 - */ - p->thread.fs = get_fs().seg; - - if (!FPU_IS_EMU) { - /* Copy the current fpu state */ - asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); - - if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) - asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" - "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" - : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) - : "memory"); - /* Restore the state in case the fpu was busy */ - asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); - } - - return 0; -} - -/* Fill in the fpu structure for a core dump. */ - -int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) -{ - char fpustate[216]; - - if (FPU_IS_EMU) { - int i; - - memcpy(fpu->fpcntl, current->thread.fpcntl, 12); - memcpy(fpu->fpregs, current->thread.fp, 96); - /* Convert internal fpu reg representation - * into long double format - */ - for (i = 0; i < 24; i += 3) - fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | - ((fpu->fpregs[i] & 0x0000ffff) << 16); - return 1; - } - - /* First dump the fpu context to avoid protocol violation. */ - asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); - if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) - return 0; - - asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" - :: "m" (fpu->fpcntl[0]) - : "memory"); - asm volatile ("fmovemx %/fp0-%/fp7,%0" - :: "m" (fpu->fpregs[0]) - : "memory"); - return 1; -} -EXPORT_SYMBOL(dump_fpu); - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *name, - const char __user *const __user *argv, - const char __user *const __user *envp) -{ - int error; - char * filename; - struct pt_regs *regs = (struct pt_regs *) &name; - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - error = do_execve(filename, argv, envp, regs); - putname(filename); - return error; -} - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long fp, pc; - unsigned long stack_page; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - stack_page = (unsigned long)task_stack_page(p); - fp = ((struct switch_stack *)p->thread.ksp)->a6; - do { - if (fp < stack_page+sizeof(struct thread_info) || - fp >= 8184+stack_page) - return 0; - pc = ((unsigned long *)fp)[1]; - if (!in_sched_functions(pc)) - return pc; - fp = *(unsigned long *) fp; - } while (count++ < 16); - return 0; -} diff --git a/trunk/arch/m68k/kernel/process_mm.c b/trunk/arch/m68k/kernel/process_mm.c new file mode 100644 index 000000000000..c2a1fc23dd75 --- /dev/null +++ b/trunk/arch/m68k/kernel/process_mm.c @@ -0,0 +1,354 @@ +/* + * linux/arch/m68k/kernel/process.c + * + * Copyright (C) 1995 Hamish Macdonald + * + * 68060 fixes by Jesper Skov + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Initial task/thread structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); +union thread_union init_thread_union __init_task_data + __attribute__((aligned(THREAD_SIZE))) = + { INIT_THREAD_INFO(init_task) }; + +/* initial task structure */ +struct task_struct init_task = INIT_TASK(init_task); + +EXPORT_SYMBOL(init_task); + +asmlinkage void ret_from_fork(void); + + +/* + * Return saved PC from a blocked thread + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; + /* Check whether the thread is blocked in resume() */ + if (in_sched_functions(sw->retpc)) + return ((unsigned long *)sw->a6)[1]; + else + return sw->retpc; +} + +/* + * The idle loop on an m68k.. + */ +static void default_idle(void) +{ + if (!need_resched()) +#if defined(MACH_ATARI_ONLY) + /* block out HSYNC on the atari (falcon) */ + __asm__("stop #0x2200" : : : "cc"); +#else + __asm__("stop #0x2000" : : : "cc"); +#endif +} + +void (*idle)(void) = default_idle; + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) +{ + /* endless idle loop with no priority at all */ + while (1) { + while (!need_resched()) + idle(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } +} + +void machine_restart(char * __unused) +{ + if (mach_reset) + mach_reset(); + for (;;); +} + +void machine_halt(void) +{ + if (mach_halt) + mach_halt(); + for (;;); +} + +void machine_power_off(void) +{ + if (mach_power_off) + mach_power_off(); + for (;;); +} + +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); + +void show_regs(struct pt_regs * regs) +{ + printk("\n"); + printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", + regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); + printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", + regs->orig_d0, regs->d0, regs->a2, regs->a1); + printk("A0: %08lx D5: %08lx D4: %08lx\n", + regs->a0, regs->d5, regs->d4); + printk("D3: %08lx D2: %08lx D1: %08lx\n", + regs->d3, regs->d2, regs->d1); + if (!(regs->sr & PS_S)) + printk("USP: %08lx\n", rdusp()); +} + +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + int pid; + mm_segment_t fs; + + fs = get_fs(); + set_fs (KERNEL_DS); + + { + register long retval __asm__ ("d0"); + register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; + + retval = __NR_clone; + __asm__ __volatile__ + ("clrl %%d2\n\t" + "trap #0\n\t" /* Linux/m68k system call */ + "tstl %0\n\t" /* child or parent */ + "jne 1f\n\t" /* parent - jump */ + "lea %%sp@(%c7),%6\n\t" /* reload current */ + "movel %6@,%6\n\t" + "movel %3,%%sp@-\n\t" /* push argument */ + "jsr %4@\n\t" /* call fn */ + "movel %0,%%d1\n\t" /* pass exit value */ + "movel %2,%%d0\n\t" /* exit */ + "trap #0\n" + "1:" + : "+d" (retval) + : "i" (__NR_clone), "i" (__NR_exit), + "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), + "i" (-THREAD_SIZE) + : "d2"); + + pid = retval; + } + + set_fs (fs); + return pid; +} +EXPORT_SYMBOL(kernel_thread); + +void flush_thread(void) +{ + unsigned long zero = 0; + set_fs(USER_DS); + current->thread.fs = __USER_DS; + if (!FPU_IS_EMU) + asm volatile (".chip 68k/68881\n\t" + "frestore %0@\n\t" + ".chip 68k" : : "a" (&zero)); +} + +/* + * "m68k_fork()".. By the time we get here, the + * non-volatile registers have also been saved on the + * stack. We do some ugly pointer stuff here.. (see + * also copy_thread) + */ + +asmlinkage int m68k_fork(struct pt_regs *regs) +{ + return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); +} + +asmlinkage int m68k_vfork(struct pt_regs *regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, + NULL, NULL); +} + +asmlinkage int m68k_clone(struct pt_regs *regs) +{ + unsigned long clone_flags; + unsigned long newsp; + int __user *parent_tidptr, *child_tidptr; + + /* syscall2 puts clone_flags in d1 and usp in d2 */ + clone_flags = regs->d1; + newsp = regs->d2; + parent_tidptr = (int __user *)regs->d3; + child_tidptr = (int __user *)regs->d4; + if (!newsp) + newsp = rdusp(); + return do_fork(clone_flags, newsp, regs, 0, + parent_tidptr, child_tidptr); +} + +int copy_thread(unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct * p, struct pt_regs * regs) +{ + struct pt_regs * childregs; + struct switch_stack * childstack, *stack; + unsigned long *retp; + + childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; + + *childregs = *regs; + childregs->d0 = 0; + + retp = ((unsigned long *) regs); + stack = ((struct switch_stack *) retp) - 1; + + childstack = ((struct switch_stack *) childregs) - 1; + *childstack = *stack; + childstack->retpc = (unsigned long)ret_from_fork; + + p->thread.usp = usp; + p->thread.ksp = (unsigned long)childstack; + + if (clone_flags & CLONE_SETTLS) + task_thread_info(p)->tp_value = regs->d5; + + /* + * Must save the current SFC/DFC value, NOT the value when + * the parent was last descheduled - RGH 10-08-96 + */ + p->thread.fs = get_fs().seg; + + if (!FPU_IS_EMU) { + /* Copy the current fpu state */ + asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); + + if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) + asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" + "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" + : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) + : "memory"); + /* Restore the state in case the fpu was busy */ + asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); + } + + return 0; +} + +/* Fill in the fpu structure for a core dump. */ + +int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) +{ + char fpustate[216]; + + if (FPU_IS_EMU) { + int i; + + memcpy(fpu->fpcntl, current->thread.fpcntl, 12); + memcpy(fpu->fpregs, current->thread.fp, 96); + /* Convert internal fpu reg representation + * into long double format + */ + for (i = 0; i < 24; i += 3) + fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | + ((fpu->fpregs[i] & 0x0000ffff) << 16); + return 1; + } + + /* First dump the fpu context to avoid protocol violation. */ + asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); + if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) + return 0; + + asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" + :: "m" (fpu->fpcntl[0]) + : "memory"); + asm volatile ("fmovemx %/fp0-%/fp7,%0" + :: "m" (fpu->fpregs[0]) + : "memory"); + return 1; +} +EXPORT_SYMBOL(dump_fpu); + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(const char __user *name, + const char __user *const __user *argv, + const char __user *const __user *envp) +{ + int error; + char * filename; + struct pt_regs *regs = (struct pt_regs *) &name; + + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + return error; + error = do_execve(filename, argv, envp, regs); + putname(filename); + return error; +} + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = (unsigned long)task_stack_page(p); + fp = ((struct switch_stack *)p->thread.ksp)->a6; + do { + if (fp < stack_page+sizeof(struct thread_info) || + fp >= 8184+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + if (!in_sched_functions(pc)) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); + return 0; +} diff --git a/trunk/arch/m68knommu/kernel/process.c b/trunk/arch/m68k/kernel/process_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/process.c rename to trunk/arch/m68k/kernel/process_no.c diff --git a/trunk/arch/m68k/kernel/ptrace.c b/trunk/arch/m68k/kernel/ptrace.c index 0b252683cefb..07a417550e94 100644 --- a/trunk/arch/m68k/kernel/ptrace.c +++ b/trunk/arch/m68k/kernel/ptrace.c @@ -1,277 +1,5 @@ -/* - * linux/arch/m68k/kernel/ptrace.c - * - * Copyright (C) 1994 by Hamish Macdonald - * Taken from linux/kernel/ptrace.c and modified for M680x0. - * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* determines which bits in the SR the user has access to. */ -/* 1 = access 0 = no access */ -#define SR_MASK 0x001f - -/* sets the trace bits. */ -#define TRACE_BITS 0xC000 -#define T1_BIT 0x8000 -#define T0_BIT 0x4000 - -/* Find the stack offset for a register, relative to thread.esp0. */ -#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) -#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ - - sizeof(struct switch_stack)) -/* Mapping from PT_xxx to the stack offset at which the register is - saved. Notice that usp has no stack-slot and needs to be treated - specially (see get_reg/put_reg below). */ -static const int regoff[] = { - [0] = PT_REG(d1), - [1] = PT_REG(d2), - [2] = PT_REG(d3), - [3] = PT_REG(d4), - [4] = PT_REG(d5), - [5] = SW_REG(d6), - [6] = SW_REG(d7), - [7] = PT_REG(a0), - [8] = PT_REG(a1), - [9] = PT_REG(a2), - [10] = SW_REG(a3), - [11] = SW_REG(a4), - [12] = SW_REG(a5), - [13] = SW_REG(a6), - [14] = PT_REG(d0), - [15] = -1, - [16] = PT_REG(orig_d0), - [17] = PT_REG(sr), - [18] = PT_REG(pc), -}; - -/* - * Get contents of register REGNO in task TASK. - */ -static inline long get_reg(struct task_struct *task, int regno) -{ - unsigned long *addr; - - if (regno == PT_USP) - addr = &task->thread.usp; - else if (regno < ARRAY_SIZE(regoff)) - addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); - else - return 0; - /* Need to take stkadj into account. */ - if (regno == PT_SR || regno == PT_PC) { - long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); - addr = (unsigned long *) ((unsigned long)addr + stkadj); - /* The sr is actually a 16 bit register. */ - if (regno == PT_SR) - return *(unsigned short *)addr; - } - return *addr; -} - -/* - * Write contents of register REGNO in task TASK. - */ -static inline int put_reg(struct task_struct *task, int regno, - unsigned long data) -{ - unsigned long *addr; - - if (regno == PT_USP) - addr = &task->thread.usp; - else if (regno < ARRAY_SIZE(regoff)) - addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); - else - return -1; - /* Need to take stkadj into account. */ - if (regno == PT_SR || regno == PT_PC) { - long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); - addr = (unsigned long *) ((unsigned long)addr + stkadj); - /* The sr is actually a 16 bit register. */ - if (regno == PT_SR) { - *(unsigned short *)addr = data; - return 0; - } - } - *addr = data; - return 0; -} - -/* - * Make sure the single step bit is not set. - */ -static inline void singlestep_disable(struct task_struct *child) -{ - unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; - put_reg(child, PT_SR, tmp); - clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); -} - -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - singlestep_disable(child); -} - -void user_enable_single_step(struct task_struct *child) -{ - unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; - put_reg(child, PT_SR, tmp | T1_BIT); - set_tsk_thread_flag(child, TIF_DELAYED_TRACE); -} - -void user_enable_block_step(struct task_struct *child) -{ - unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; - put_reg(child, PT_SR, tmp | T0_BIT); -} - -void user_disable_single_step(struct task_struct *child) -{ - singlestep_disable(child); -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - unsigned long tmp; - int i, ret = 0; - int regno = addr >> 2; /* temporary hack. */ - unsigned long __user *datap = (unsigned long __user *) data; - - switch (request) { - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: - if (addr & 3) - goto out_eio; - - if (regno >= 0 && regno < 19) { - tmp = get_reg(child, regno); - } else if (regno >= 21 && regno < 49) { - tmp = child->thread.fp[regno - 21]; - /* Convert internal fpu reg representation - * into long double format - */ - if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) - tmp = ((tmp & 0xffff0000) << 15) | - ((tmp & 0x0000ffff) << 16); - } else - goto out_eio; - ret = put_user(tmp, datap); - break; - - case PTRACE_POKEUSR: - /* write the word at location addr in the USER area */ - if (addr & 3) - goto out_eio; - - if (regno == PT_SR) { - data &= SR_MASK; - data |= get_reg(child, PT_SR) & ~SR_MASK; - } - if (regno >= 0 && regno < 19) { - if (put_reg(child, regno, data)) - goto out_eio; - } else if (regno >= 21 && regno < 48) { - /* Convert long double format - * into internal fpu reg representation - */ - if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) { - data <<= 15; - data = (data & 0xffff0000) | - ((data & 0x0000ffff) >> 1); - } - child->thread.fp[regno - 21] = data; - } else - goto out_eio; - break; - - case PTRACE_GETREGS: /* Get all gp regs from the child. */ - for (i = 0; i < 19; i++) { - tmp = get_reg(child, i); - ret = put_user(tmp, datap); - if (ret) - break; - datap++; - } - break; - - case PTRACE_SETREGS: /* Set all gp regs in the child. */ - for (i = 0; i < 19; i++) { - ret = get_user(tmp, datap); - if (ret) - break; - if (i == PT_SR) { - tmp &= SR_MASK; - tmp |= get_reg(child, PT_SR) & ~SR_MASK; - } - put_reg(child, i, tmp); - datap++; - } - break; - - case PTRACE_GETFPREGS: /* Get the child FPU state. */ - if (copy_to_user(datap, &child->thread.fp, - sizeof(struct user_m68kfp_struct))) - ret = -EFAULT; - break; - - case PTRACE_SETFPREGS: /* Set the child FPU state. */ - if (copy_from_user(&child->thread.fp, datap, - sizeof(struct user_m68kfp_struct))) - ret = -EFAULT; - break; - - case PTRACE_GET_THREAD_AREA: - ret = put_user(task_thread_info(child)->tp_value, datap); - break; - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -out_eio: - return -EIO; -} - -asmlinkage void syscall_trace(void) -{ - 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) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} +#ifdef CONFIG_MMU +#include "ptrace_mm.c" +#else +#include "ptrace_no.c" +#endif diff --git a/trunk/arch/m68k/kernel/ptrace_mm.c b/trunk/arch/m68k/kernel/ptrace_mm.c new file mode 100644 index 000000000000..0b252683cefb --- /dev/null +++ b/trunk/arch/m68k/kernel/ptrace_mm.c @@ -0,0 +1,277 @@ +/* + * linux/arch/m68k/kernel/ptrace.c + * + * Copyright (C) 1994 by Hamish Macdonald + * Taken from linux/kernel/ptrace.c and modified for M680x0. + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. + */ + +/* determines which bits in the SR the user has access to. */ +/* 1 = access 0 = no access */ +#define SR_MASK 0x001f + +/* sets the trace bits. */ +#define TRACE_BITS 0xC000 +#define T1_BIT 0x8000 +#define T0_BIT 0x4000 + +/* Find the stack offset for a register, relative to thread.esp0. */ +#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) +#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ + - sizeof(struct switch_stack)) +/* Mapping from PT_xxx to the stack offset at which the register is + saved. Notice that usp has no stack-slot and needs to be treated + specially (see get_reg/put_reg below). */ +static const int regoff[] = { + [0] = PT_REG(d1), + [1] = PT_REG(d2), + [2] = PT_REG(d3), + [3] = PT_REG(d4), + [4] = PT_REG(d5), + [5] = SW_REG(d6), + [6] = SW_REG(d7), + [7] = PT_REG(a0), + [8] = PT_REG(a1), + [9] = PT_REG(a2), + [10] = SW_REG(a3), + [11] = SW_REG(a4), + [12] = SW_REG(a5), + [13] = SW_REG(a6), + [14] = PT_REG(d0), + [15] = -1, + [16] = PT_REG(orig_d0), + [17] = PT_REG(sr), + [18] = PT_REG(pc), +}; + +/* + * Get contents of register REGNO in task TASK. + */ +static inline long get_reg(struct task_struct *task, int regno) +{ + unsigned long *addr; + + if (regno == PT_USP) + addr = &task->thread.usp; + else if (regno < ARRAY_SIZE(regoff)) + addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); + else + return 0; + /* Need to take stkadj into account. */ + if (regno == PT_SR || regno == PT_PC) { + long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); + addr = (unsigned long *) ((unsigned long)addr + stkadj); + /* The sr is actually a 16 bit register. */ + if (regno == PT_SR) + return *(unsigned short *)addr; + } + return *addr; +} + +/* + * Write contents of register REGNO in task TASK. + */ +static inline int put_reg(struct task_struct *task, int regno, + unsigned long data) +{ + unsigned long *addr; + + if (regno == PT_USP) + addr = &task->thread.usp; + else if (regno < ARRAY_SIZE(regoff)) + addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); + else + return -1; + /* Need to take stkadj into account. */ + if (regno == PT_SR || regno == PT_PC) { + long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); + addr = (unsigned long *) ((unsigned long)addr + stkadj); + /* The sr is actually a 16 bit register. */ + if (regno == PT_SR) { + *(unsigned short *)addr = data; + return 0; + } + } + *addr = data; + return 0; +} + +/* + * Make sure the single step bit is not set. + */ +static inline void singlestep_disable(struct task_struct *child) +{ + unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; + put_reg(child, PT_SR, tmp); + clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); +} + +/* + * Called by kernel/ptrace.c when detaching.. + */ +void ptrace_disable(struct task_struct *child) +{ + singlestep_disable(child); +} + +void user_enable_single_step(struct task_struct *child) +{ + unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; + put_reg(child, PT_SR, tmp | T1_BIT); + set_tsk_thread_flag(child, TIF_DELAYED_TRACE); +} + +void user_enable_block_step(struct task_struct *child) +{ + unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; + put_reg(child, PT_SR, tmp | T0_BIT); +} + +void user_disable_single_step(struct task_struct *child) +{ + singlestep_disable(child); +} + +long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) +{ + unsigned long tmp; + int i, ret = 0; + int regno = addr >> 2; /* temporary hack. */ + unsigned long __user *datap = (unsigned long __user *) data; + + switch (request) { + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: + if (addr & 3) + goto out_eio; + + if (regno >= 0 && regno < 19) { + tmp = get_reg(child, regno); + } else if (regno >= 21 && regno < 49) { + tmp = child->thread.fp[regno - 21]; + /* Convert internal fpu reg representation + * into long double format + */ + if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) + tmp = ((tmp & 0xffff0000) << 15) | + ((tmp & 0x0000ffff) << 16); + } else + goto out_eio; + ret = put_user(tmp, datap); + break; + + case PTRACE_POKEUSR: + /* write the word at location addr in the USER area */ + if (addr & 3) + goto out_eio; + + if (regno == PT_SR) { + data &= SR_MASK; + data |= get_reg(child, PT_SR) & ~SR_MASK; + } + if (regno >= 0 && regno < 19) { + if (put_reg(child, regno, data)) + goto out_eio; + } else if (regno >= 21 && regno < 48) { + /* Convert long double format + * into internal fpu reg representation + */ + if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) { + data <<= 15; + data = (data & 0xffff0000) | + ((data & 0x0000ffff) >> 1); + } + child->thread.fp[regno - 21] = data; + } else + goto out_eio; + break; + + case PTRACE_GETREGS: /* Get all gp regs from the child. */ + for (i = 0; i < 19; i++) { + tmp = get_reg(child, i); + ret = put_user(tmp, datap); + if (ret) + break; + datap++; + } + break; + + case PTRACE_SETREGS: /* Set all gp regs in the child. */ + for (i = 0; i < 19; i++) { + ret = get_user(tmp, datap); + if (ret) + break; + if (i == PT_SR) { + tmp &= SR_MASK; + tmp |= get_reg(child, PT_SR) & ~SR_MASK; + } + put_reg(child, i, tmp); + datap++; + } + break; + + case PTRACE_GETFPREGS: /* Get the child FPU state. */ + if (copy_to_user(datap, &child->thread.fp, + sizeof(struct user_m68kfp_struct))) + ret = -EFAULT; + break; + + case PTRACE_SETFPREGS: /* Set the child FPU state. */ + if (copy_from_user(&child->thread.fp, datap, + sizeof(struct user_m68kfp_struct))) + ret = -EFAULT; + break; + + case PTRACE_GET_THREAD_AREA: + ret = put_user(task_thread_info(child)->tp_value, datap); + break; + + default: + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; +out_eio: + return -EIO; +} + +asmlinkage void syscall_trace(void) +{ + 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) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} diff --git a/trunk/arch/m68knommu/kernel/ptrace.c b/trunk/arch/m68k/kernel/ptrace_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/ptrace.c rename to trunk/arch/m68k/kernel/ptrace_no.c diff --git a/trunk/arch/m68k/kernel/setup.c b/trunk/arch/m68k/kernel/setup.c index 334d83640376..4bf129f1d2e2 100644 --- a/trunk/arch/m68k/kernel/setup.c +++ b/trunk/arch/m68k/kernel/setup.c @@ -1,533 +1,5 @@ -/* - * linux/arch/m68k/kernel/setup.c - * - * Copyright (C) 1995 Hamish Macdonald - */ - -/* - * This file handles the architecture-dependent parts of system setup - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_AMIGA -#include -#endif -#ifdef CONFIG_ATARI -#include -#include -#endif -#ifdef CONFIG_SUN3X -#include -#endif -#include - -#if !FPSTATESIZE || !NR_IRQS -#warning No CPU/platform type selected, your kernel will not work! -#warning Are you building an allnoconfig kernel? -#endif - -unsigned long m68k_machtype; -EXPORT_SYMBOL(m68k_machtype); -unsigned long m68k_cputype; -EXPORT_SYMBOL(m68k_cputype); -unsigned long m68k_fputype; -unsigned long m68k_mmutype; -EXPORT_SYMBOL(m68k_mmutype); -#ifdef CONFIG_VME -unsigned long vme_brdtype; -EXPORT_SYMBOL(vme_brdtype); -#endif - -int m68k_is040or060; -EXPORT_SYMBOL(m68k_is040or060); - -extern unsigned long availmem; - -int m68k_num_memory; -EXPORT_SYMBOL(m68k_num_memory); -int m68k_realnum_memory; -EXPORT_SYMBOL(m68k_realnum_memory); -unsigned long m68k_memoffset; -struct mem_info m68k_memory[NUM_MEMINFO]; -EXPORT_SYMBOL(m68k_memory); - -struct mem_info m68k_ramdisk; - -static char m68k_command_line[CL_SIZE]; - -void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; -/* machine dependent irq functions */ -void (*mach_init_IRQ) (void) __initdata = NULL; -void (*mach_get_model) (char *model); -void (*mach_get_hardware_list) (struct seq_file *m); -/* machine dependent timer functions */ -unsigned long (*mach_gettimeoffset) (void); -int (*mach_hwclk) (int, struct rtc_time*); -EXPORT_SYMBOL(mach_hwclk); -int (*mach_set_clock_mmss) (unsigned long); -unsigned int (*mach_get_ss)(void); -int (*mach_get_rtc_pll)(struct rtc_pll_info *); -int (*mach_set_rtc_pll)(struct rtc_pll_info *); -EXPORT_SYMBOL(mach_get_ss); -EXPORT_SYMBOL(mach_get_rtc_pll); -EXPORT_SYMBOL(mach_set_rtc_pll); -void (*mach_reset)( void ); -void (*mach_halt)( void ); -void (*mach_power_off)( void ); -long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#ifdef CONFIG_HEARTBEAT -void (*mach_heartbeat) (int); -EXPORT_SYMBOL(mach_heartbeat); -#endif -#ifdef CONFIG_M68K_L2_CACHE -void (*mach_l2_flush) (int); -#endif -#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) -void (*mach_beep)(unsigned int, unsigned int); -EXPORT_SYMBOL(mach_beep); -#endif -#if defined(CONFIG_ISA) && defined(MULTI_ISA) -int isa_type; -int isa_sex; -EXPORT_SYMBOL(isa_type); -EXPORT_SYMBOL(isa_sex); -#endif - -extern int amiga_parse_bootinfo(const struct bi_record *); -extern int atari_parse_bootinfo(const struct bi_record *); -extern int mac_parse_bootinfo(const struct bi_record *); -extern int q40_parse_bootinfo(const struct bi_record *); -extern int bvme6000_parse_bootinfo(const struct bi_record *); -extern int mvme16x_parse_bootinfo(const struct bi_record *); -extern int mvme147_parse_bootinfo(const struct bi_record *); -extern int hp300_parse_bootinfo(const struct bi_record *); -extern int apollo_parse_bootinfo(const struct bi_record *); - -extern void config_amiga(void); -extern void config_atari(void); -extern void config_mac(void); -extern void config_sun3(void); -extern void config_apollo(void); -extern void config_mvme147(void); -extern void config_mvme16x(void); -extern void config_bvme6000(void); -extern void config_hp300(void); -extern void config_q40(void); -extern void config_sun3x(void); - -#define MASK_256K 0xfffc0000 - -extern void paging_init(void); - -static void __init m68k_parse_bootinfo(const struct bi_record *record) -{ - while (record->tag != BI_LAST) { - int unknown = 0; - const unsigned long *data = record->data; - - switch (record->tag) { - case BI_MACHTYPE: - case BI_CPUTYPE: - case BI_FPUTYPE: - case BI_MMUTYPE: - /* Already set up by head.S */ - break; - - case BI_MEMCHUNK: - if (m68k_num_memory < NUM_MEMINFO) { - m68k_memory[m68k_num_memory].addr = data[0]; - m68k_memory[m68k_num_memory].size = data[1]; - m68k_num_memory++; - } else - printk("m68k_parse_bootinfo: too many memory chunks\n"); - break; - - case BI_RAMDISK: - m68k_ramdisk.addr = data[0]; - m68k_ramdisk.size = data[1]; - break; - - case BI_COMMAND_LINE: - strlcpy(m68k_command_line, (const char *)data, - sizeof(m68k_command_line)); - break; - - default: - if (MACH_IS_AMIGA) - unknown = amiga_parse_bootinfo(record); - else if (MACH_IS_ATARI) - unknown = atari_parse_bootinfo(record); - else if (MACH_IS_MAC) - unknown = mac_parse_bootinfo(record); - else if (MACH_IS_Q40) - unknown = q40_parse_bootinfo(record); - else if (MACH_IS_BVME6000) - unknown = bvme6000_parse_bootinfo(record); - else if (MACH_IS_MVME16x) - unknown = mvme16x_parse_bootinfo(record); - else if (MACH_IS_MVME147) - unknown = mvme147_parse_bootinfo(record); - else if (MACH_IS_HP300) - unknown = hp300_parse_bootinfo(record); - else if (MACH_IS_APOLLO) - unknown = apollo_parse_bootinfo(record); - else - unknown = 1; - } - if (unknown) - printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n", - record->tag); - record = (struct bi_record *)((unsigned long)record + - record->size); - } - - m68k_realnum_memory = m68k_num_memory; -#ifdef CONFIG_SINGLE_MEMORY_CHUNK - if (m68k_num_memory > 1) { - printk("Ignoring last %i chunks of physical memory\n", - (m68k_num_memory - 1)); - m68k_num_memory = 1; - } -#endif -} - -void __init setup_arch(char **cmdline_p) -{ - int i; - - /* The bootinfo is located right after the kernel bss */ - m68k_parse_bootinfo((const struct bi_record *)_end); - - if (CPU_IS_040) - m68k_is040or060 = 4; - else if (CPU_IS_060) - m68k_is040or060 = 6; - - /* FIXME: m68k_fputype is passed in by Penguin booter, which can - * be confused by software FPU emulation. BEWARE. - * We should really do our own FPU check at startup. - * [what do we do with buggy 68LC040s? if we have problems - * with them, we should add a test to check_bugs() below] */ -#ifndef CONFIG_M68KFPU_EMU_ONLY - /* clear the fpu if we have one */ - if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) { - volatile int zero = 0; - asm volatile ("frestore %0" : : "m" (zero)); - } -#endif - - if (CPU_IS_060) { - u32 pcr; - - asm (".chip 68060; movec %%pcr,%0; .chip 68k" - : "=d" (pcr)); - if (((pcr >> 8) & 0xff) <= 5) { - printk("Enabling workaround for errata I14\n"); - asm (".chip 68060; movec %0,%%pcr; .chip 68k" - : : "d" (pcr | 0x20)); - } - } - - init_mm.start_code = PAGE_OFFSET; - init_mm.end_code = (unsigned long)_etext; - init_mm.end_data = (unsigned long)_edata; - init_mm.brk = (unsigned long)_end; - - *cmdline_p = m68k_command_line; - memcpy(boot_command_line, *cmdline_p, CL_SIZE); - - parse_early_param(); - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - - switch (m68k_machtype) { -#ifdef CONFIG_AMIGA - case MACH_AMIGA: - config_amiga(); - break; -#endif -#ifdef CONFIG_ATARI - case MACH_ATARI: - config_atari(); - break; -#endif -#ifdef CONFIG_MAC - case MACH_MAC: - config_mac(); - break; -#endif -#ifdef CONFIG_SUN3 - case MACH_SUN3: - config_sun3(); - break; -#endif -#ifdef CONFIG_APOLLO - case MACH_APOLLO: - config_apollo(); - break; -#endif -#ifdef CONFIG_MVME147 - case MACH_MVME147: - config_mvme147(); - break; -#endif -#ifdef CONFIG_MVME16x - case MACH_MVME16x: - config_mvme16x(); - break; -#endif -#ifdef CONFIG_BVME6000 - case MACH_BVME6000: - config_bvme6000(); - break; -#endif -#ifdef CONFIG_HP300 - case MACH_HP300: - config_hp300(); - break; -#endif -#ifdef CONFIG_Q40 - case MACH_Q40: - config_q40(); - break; -#endif -#ifdef CONFIG_SUN3X - case MACH_SUN3X: - config_sun3x(); - break; -#endif - default: - panic("No configuration setup"); - } - -#ifdef CONFIG_NATFEAT - nf_init(); -#endif - - paging_init(); - -#ifndef CONFIG_SUN3 - for (i = 1; i < m68k_num_memory; i++) - free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, - m68k_memory[i].size); -#ifdef CONFIG_BLK_DEV_INITRD - if (m68k_ramdisk.size) { - reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)), - m68k_ramdisk.addr, m68k_ramdisk.size, - BOOTMEM_DEFAULT); - initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); - initrd_end = initrd_start + m68k_ramdisk.size; - printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end); - } -#endif - -#ifdef CONFIG_ATARI - if (MACH_IS_ATARI) - atari_stram_reserve_pages((void *)availmem); -#endif -#ifdef CONFIG_SUN3X - if (MACH_IS_SUN3X) { - dvma_init(); - } -#endif - -#endif /* !CONFIG_SUN3 */ - -/* set ISA defs early as possible */ -#if defined(CONFIG_ISA) && defined(MULTI_ISA) - if (MACH_IS_Q40) { - isa_type = ISA_TYPE_Q40; - isa_sex = 0; - } -#ifdef CONFIG_AMIGA_PCMCIA - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) { - isa_type = ISA_TYPE_AG; - isa_sex = 1; - } -#endif -#endif -} - -static int show_cpuinfo(struct seq_file *m, void *v) -{ - const char *cpu, *mmu, *fpu; - unsigned long clockfreq, clockfactor; - -#define LOOP_CYCLES_68020 (8) -#define LOOP_CYCLES_68030 (8) -#define LOOP_CYCLES_68040 (3) -#define LOOP_CYCLES_68060 (1) - - if (CPU_IS_020) { - cpu = "68020"; - clockfactor = LOOP_CYCLES_68020; - } else if (CPU_IS_030) { - cpu = "68030"; - clockfactor = LOOP_CYCLES_68030; - } else if (CPU_IS_040) { - cpu = "68040"; - clockfactor = LOOP_CYCLES_68040; - } else if (CPU_IS_060) { - cpu = "68060"; - clockfactor = LOOP_CYCLES_68060; - } else { - cpu = "680x0"; - clockfactor = 0; - } - -#ifdef CONFIG_M68KFPU_EMU_ONLY - fpu = "none(soft float)"; +#ifdef CONFIG_MMU +#include "setup_mm.c" #else - if (m68k_fputype & FPU_68881) - fpu = "68881"; - else if (m68k_fputype & FPU_68882) - fpu = "68882"; - else if (m68k_fputype & FPU_68040) - fpu = "68040"; - else if (m68k_fputype & FPU_68060) - fpu = "68060"; - else if (m68k_fputype & FPU_SUNFPA) - fpu = "Sun FPA"; - else - fpu = "none"; -#endif - - if (m68k_mmutype & MMU_68851) - mmu = "68851"; - else if (m68k_mmutype & MMU_68030) - mmu = "68030"; - else if (m68k_mmutype & MMU_68040) - mmu = "68040"; - else if (m68k_mmutype & MMU_68060) - mmu = "68060"; - else if (m68k_mmutype & MMU_SUN3) - mmu = "Sun-3"; - else if (m68k_mmutype & MMU_APOLLO) - mmu = "Apollo"; - else - mmu = "unknown"; - - clockfreq = loops_per_jiffy * HZ * clockfactor; - - seq_printf(m, "CPU:\t\t%s\n" - "MMU:\t\t%s\n" - "FPU:\t\t%s\n" - "Clocking:\t%lu.%1luMHz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu, mmu, fpu, - clockfreq/1000000,(clockfreq/100000)%10, - loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100, - loops_per_jiffy); - 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) -{ -} -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; - -#ifdef CONFIG_PROC_HARDWARE -static int hardware_proc_show(struct seq_file *m, void *v) -{ - char model[80]; - unsigned long mem; - int i; - - if (mach_get_model) - mach_get_model(model); - else - strcpy(model, "Unknown m68k"); - - seq_printf(m, "Model:\t\t%s\n", model); - for (mem = 0, i = 0; i < m68k_num_memory; i++) - mem += m68k_memory[i].size; - seq_printf(m, "System Memory:\t%ldK\n", mem >> 10); - - if (mach_get_hardware_list) - mach_get_hardware_list(m); - - return 0; -} - -static int hardware_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, hardware_proc_show, NULL); -} - -static const struct file_operations hardware_proc_fops = { - .open = hardware_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init proc_hardware_init(void) -{ - proc_create("hardware", 0, NULL, &hardware_proc_fops); - return 0; -} -module_init(proc_hardware_init); +#include "setup_no.c" #endif - -void check_bugs(void) -{ -#ifndef CONFIG_M68KFPU_EMU - if (m68k_fputype == 0) { - printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, " - "WHICH IS REQUIRED BY LINUX/M68K ***\n"); - printk(KERN_EMERG "Upgrade your hardware or join the FPU " - "emulation project\n"); - panic("no FPU"); - } -#endif /* !CONFIG_M68KFPU_EMU */ -} - -#ifdef CONFIG_ADB -static int __init adb_probe_sync_enable (char *str) { - extern int __adb_probe_sync; - __adb_probe_sync = 1; - return 1; -} - -__setup("adb_sync", adb_probe_sync_enable); -#endif /* CONFIG_ADB */ diff --git a/trunk/arch/m68k/kernel/setup_mm.c b/trunk/arch/m68k/kernel/setup_mm.c new file mode 100644 index 000000000000..334d83640376 --- /dev/null +++ b/trunk/arch/m68k/kernel/setup_mm.c @@ -0,0 +1,533 @@ +/* + * linux/arch/m68k/kernel/setup.c + * + * Copyright (C) 1995 Hamish Macdonald + */ + +/* + * This file handles the architecture-dependent parts of system setup + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AMIGA +#include +#endif +#ifdef CONFIG_ATARI +#include +#include +#endif +#ifdef CONFIG_SUN3X +#include +#endif +#include + +#if !FPSTATESIZE || !NR_IRQS +#warning No CPU/platform type selected, your kernel will not work! +#warning Are you building an allnoconfig kernel? +#endif + +unsigned long m68k_machtype; +EXPORT_SYMBOL(m68k_machtype); +unsigned long m68k_cputype; +EXPORT_SYMBOL(m68k_cputype); +unsigned long m68k_fputype; +unsigned long m68k_mmutype; +EXPORT_SYMBOL(m68k_mmutype); +#ifdef CONFIG_VME +unsigned long vme_brdtype; +EXPORT_SYMBOL(vme_brdtype); +#endif + +int m68k_is040or060; +EXPORT_SYMBOL(m68k_is040or060); + +extern unsigned long availmem; + +int m68k_num_memory; +EXPORT_SYMBOL(m68k_num_memory); +int m68k_realnum_memory; +EXPORT_SYMBOL(m68k_realnum_memory); +unsigned long m68k_memoffset; +struct mem_info m68k_memory[NUM_MEMINFO]; +EXPORT_SYMBOL(m68k_memory); + +struct mem_info m68k_ramdisk; + +static char m68k_command_line[CL_SIZE]; + +void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; +/* machine dependent irq functions */ +void (*mach_init_IRQ) (void) __initdata = NULL; +void (*mach_get_model) (char *model); +void (*mach_get_hardware_list) (struct seq_file *m); +/* machine dependent timer functions */ +unsigned long (*mach_gettimeoffset) (void); +int (*mach_hwclk) (int, struct rtc_time*); +EXPORT_SYMBOL(mach_hwclk); +int (*mach_set_clock_mmss) (unsigned long); +unsigned int (*mach_get_ss)(void); +int (*mach_get_rtc_pll)(struct rtc_pll_info *); +int (*mach_set_rtc_pll)(struct rtc_pll_info *); +EXPORT_SYMBOL(mach_get_ss); +EXPORT_SYMBOL(mach_get_rtc_pll); +EXPORT_SYMBOL(mach_set_rtc_pll); +void (*mach_reset)( void ); +void (*mach_halt)( void ); +void (*mach_power_off)( void ); +long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ +#ifdef CONFIG_HEARTBEAT +void (*mach_heartbeat) (int); +EXPORT_SYMBOL(mach_heartbeat); +#endif +#ifdef CONFIG_M68K_L2_CACHE +void (*mach_l2_flush) (int); +#endif +#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) +void (*mach_beep)(unsigned int, unsigned int); +EXPORT_SYMBOL(mach_beep); +#endif +#if defined(CONFIG_ISA) && defined(MULTI_ISA) +int isa_type; +int isa_sex; +EXPORT_SYMBOL(isa_type); +EXPORT_SYMBOL(isa_sex); +#endif + +extern int amiga_parse_bootinfo(const struct bi_record *); +extern int atari_parse_bootinfo(const struct bi_record *); +extern int mac_parse_bootinfo(const struct bi_record *); +extern int q40_parse_bootinfo(const struct bi_record *); +extern int bvme6000_parse_bootinfo(const struct bi_record *); +extern int mvme16x_parse_bootinfo(const struct bi_record *); +extern int mvme147_parse_bootinfo(const struct bi_record *); +extern int hp300_parse_bootinfo(const struct bi_record *); +extern int apollo_parse_bootinfo(const struct bi_record *); + +extern void config_amiga(void); +extern void config_atari(void); +extern void config_mac(void); +extern void config_sun3(void); +extern void config_apollo(void); +extern void config_mvme147(void); +extern void config_mvme16x(void); +extern void config_bvme6000(void); +extern void config_hp300(void); +extern void config_q40(void); +extern void config_sun3x(void); + +#define MASK_256K 0xfffc0000 + +extern void paging_init(void); + +static void __init m68k_parse_bootinfo(const struct bi_record *record) +{ + while (record->tag != BI_LAST) { + int unknown = 0; + const unsigned long *data = record->data; + + switch (record->tag) { + case BI_MACHTYPE: + case BI_CPUTYPE: + case BI_FPUTYPE: + case BI_MMUTYPE: + /* Already set up by head.S */ + break; + + case BI_MEMCHUNK: + if (m68k_num_memory < NUM_MEMINFO) { + m68k_memory[m68k_num_memory].addr = data[0]; + m68k_memory[m68k_num_memory].size = data[1]; + m68k_num_memory++; + } else + printk("m68k_parse_bootinfo: too many memory chunks\n"); + break; + + case BI_RAMDISK: + m68k_ramdisk.addr = data[0]; + m68k_ramdisk.size = data[1]; + break; + + case BI_COMMAND_LINE: + strlcpy(m68k_command_line, (const char *)data, + sizeof(m68k_command_line)); + break; + + default: + if (MACH_IS_AMIGA) + unknown = amiga_parse_bootinfo(record); + else if (MACH_IS_ATARI) + unknown = atari_parse_bootinfo(record); + else if (MACH_IS_MAC) + unknown = mac_parse_bootinfo(record); + else if (MACH_IS_Q40) + unknown = q40_parse_bootinfo(record); + else if (MACH_IS_BVME6000) + unknown = bvme6000_parse_bootinfo(record); + else if (MACH_IS_MVME16x) + unknown = mvme16x_parse_bootinfo(record); + else if (MACH_IS_MVME147) + unknown = mvme147_parse_bootinfo(record); + else if (MACH_IS_HP300) + unknown = hp300_parse_bootinfo(record); + else if (MACH_IS_APOLLO) + unknown = apollo_parse_bootinfo(record); + else + unknown = 1; + } + if (unknown) + printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n", + record->tag); + record = (struct bi_record *)((unsigned long)record + + record->size); + } + + m68k_realnum_memory = m68k_num_memory; +#ifdef CONFIG_SINGLE_MEMORY_CHUNK + if (m68k_num_memory > 1) { + printk("Ignoring last %i chunks of physical memory\n", + (m68k_num_memory - 1)); + m68k_num_memory = 1; + } +#endif +} + +void __init setup_arch(char **cmdline_p) +{ + int i; + + /* The bootinfo is located right after the kernel bss */ + m68k_parse_bootinfo((const struct bi_record *)_end); + + if (CPU_IS_040) + m68k_is040or060 = 4; + else if (CPU_IS_060) + m68k_is040or060 = 6; + + /* FIXME: m68k_fputype is passed in by Penguin booter, which can + * be confused by software FPU emulation. BEWARE. + * We should really do our own FPU check at startup. + * [what do we do with buggy 68LC040s? if we have problems + * with them, we should add a test to check_bugs() below] */ +#ifndef CONFIG_M68KFPU_EMU_ONLY + /* clear the fpu if we have one */ + if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) { + volatile int zero = 0; + asm volatile ("frestore %0" : : "m" (zero)); + } +#endif + + if (CPU_IS_060) { + u32 pcr; + + asm (".chip 68060; movec %%pcr,%0; .chip 68k" + : "=d" (pcr)); + if (((pcr >> 8) & 0xff) <= 5) { + printk("Enabling workaround for errata I14\n"); + asm (".chip 68060; movec %0,%%pcr; .chip 68k" + : : "d" (pcr | 0x20)); + } + } + + init_mm.start_code = PAGE_OFFSET; + init_mm.end_code = (unsigned long)_etext; + init_mm.end_data = (unsigned long)_edata; + init_mm.brk = (unsigned long)_end; + + *cmdline_p = m68k_command_line; + memcpy(boot_command_line, *cmdline_p, CL_SIZE); + + parse_early_param(); + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + switch (m68k_machtype) { +#ifdef CONFIG_AMIGA + case MACH_AMIGA: + config_amiga(); + break; +#endif +#ifdef CONFIG_ATARI + case MACH_ATARI: + config_atari(); + break; +#endif +#ifdef CONFIG_MAC + case MACH_MAC: + config_mac(); + break; +#endif +#ifdef CONFIG_SUN3 + case MACH_SUN3: + config_sun3(); + break; +#endif +#ifdef CONFIG_APOLLO + case MACH_APOLLO: + config_apollo(); + break; +#endif +#ifdef CONFIG_MVME147 + case MACH_MVME147: + config_mvme147(); + break; +#endif +#ifdef CONFIG_MVME16x + case MACH_MVME16x: + config_mvme16x(); + break; +#endif +#ifdef CONFIG_BVME6000 + case MACH_BVME6000: + config_bvme6000(); + break; +#endif +#ifdef CONFIG_HP300 + case MACH_HP300: + config_hp300(); + break; +#endif +#ifdef CONFIG_Q40 + case MACH_Q40: + config_q40(); + break; +#endif +#ifdef CONFIG_SUN3X + case MACH_SUN3X: + config_sun3x(); + break; +#endif + default: + panic("No configuration setup"); + } + +#ifdef CONFIG_NATFEAT + nf_init(); +#endif + + paging_init(); + +#ifndef CONFIG_SUN3 + for (i = 1; i < m68k_num_memory; i++) + free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, + m68k_memory[i].size); +#ifdef CONFIG_BLK_DEV_INITRD + if (m68k_ramdisk.size) { + reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)), + m68k_ramdisk.addr, m68k_ramdisk.size, + BOOTMEM_DEFAULT); + initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); + initrd_end = initrd_start + m68k_ramdisk.size; + printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end); + } +#endif + +#ifdef CONFIG_ATARI + if (MACH_IS_ATARI) + atari_stram_reserve_pages((void *)availmem); +#endif +#ifdef CONFIG_SUN3X + if (MACH_IS_SUN3X) { + dvma_init(); + } +#endif + +#endif /* !CONFIG_SUN3 */ + +/* set ISA defs early as possible */ +#if defined(CONFIG_ISA) && defined(MULTI_ISA) + if (MACH_IS_Q40) { + isa_type = ISA_TYPE_Q40; + isa_sex = 0; + } +#ifdef CONFIG_AMIGA_PCMCIA + if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) { + isa_type = ISA_TYPE_AG; + isa_sex = 1; + } +#endif +#endif +} + +static int show_cpuinfo(struct seq_file *m, void *v) +{ + const char *cpu, *mmu, *fpu; + unsigned long clockfreq, clockfactor; + +#define LOOP_CYCLES_68020 (8) +#define LOOP_CYCLES_68030 (8) +#define LOOP_CYCLES_68040 (3) +#define LOOP_CYCLES_68060 (1) + + if (CPU_IS_020) { + cpu = "68020"; + clockfactor = LOOP_CYCLES_68020; + } else if (CPU_IS_030) { + cpu = "68030"; + clockfactor = LOOP_CYCLES_68030; + } else if (CPU_IS_040) { + cpu = "68040"; + clockfactor = LOOP_CYCLES_68040; + } else if (CPU_IS_060) { + cpu = "68060"; + clockfactor = LOOP_CYCLES_68060; + } else { + cpu = "680x0"; + clockfactor = 0; + } + +#ifdef CONFIG_M68KFPU_EMU_ONLY + fpu = "none(soft float)"; +#else + if (m68k_fputype & FPU_68881) + fpu = "68881"; + else if (m68k_fputype & FPU_68882) + fpu = "68882"; + else if (m68k_fputype & FPU_68040) + fpu = "68040"; + else if (m68k_fputype & FPU_68060) + fpu = "68060"; + else if (m68k_fputype & FPU_SUNFPA) + fpu = "Sun FPA"; + else + fpu = "none"; +#endif + + if (m68k_mmutype & MMU_68851) + mmu = "68851"; + else if (m68k_mmutype & MMU_68030) + mmu = "68030"; + else if (m68k_mmutype & MMU_68040) + mmu = "68040"; + else if (m68k_mmutype & MMU_68060) + mmu = "68060"; + else if (m68k_mmutype & MMU_SUN3) + mmu = "Sun-3"; + else if (m68k_mmutype & MMU_APOLLO) + mmu = "Apollo"; + else + mmu = "unknown"; + + clockfreq = loops_per_jiffy * HZ * clockfactor; + + seq_printf(m, "CPU:\t\t%s\n" + "MMU:\t\t%s\n" + "FPU:\t\t%s\n" + "Clocking:\t%lu.%1luMHz\n" + "BogoMips:\t%lu.%02lu\n" + "Calibration:\t%lu loops\n", + cpu, mmu, fpu, + clockfreq/1000000,(clockfreq/100000)%10, + loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100, + loops_per_jiffy); + 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) +{ +} +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; + +#ifdef CONFIG_PROC_HARDWARE +static int hardware_proc_show(struct seq_file *m, void *v) +{ + char model[80]; + unsigned long mem; + int i; + + if (mach_get_model) + mach_get_model(model); + else + strcpy(model, "Unknown m68k"); + + seq_printf(m, "Model:\t\t%s\n", model); + for (mem = 0, i = 0; i < m68k_num_memory; i++) + mem += m68k_memory[i].size; + seq_printf(m, "System Memory:\t%ldK\n", mem >> 10); + + if (mach_get_hardware_list) + mach_get_hardware_list(m); + + return 0; +} + +static int hardware_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, hardware_proc_show, NULL); +} + +static const struct file_operations hardware_proc_fops = { + .open = hardware_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init proc_hardware_init(void) +{ + proc_create("hardware", 0, NULL, &hardware_proc_fops); + return 0; +} +module_init(proc_hardware_init); +#endif + +void check_bugs(void) +{ +#ifndef CONFIG_M68KFPU_EMU + if (m68k_fputype == 0) { + printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, " + "WHICH IS REQUIRED BY LINUX/M68K ***\n"); + printk(KERN_EMERG "Upgrade your hardware or join the FPU " + "emulation project\n"); + panic("no FPU"); + } +#endif /* !CONFIG_M68KFPU_EMU */ +} + +#ifdef CONFIG_ADB +static int __init adb_probe_sync_enable (char *str) { + extern int __adb_probe_sync; + __adb_probe_sync = 1; + return 1; +} + +__setup("adb_sync", adb_probe_sync_enable); +#endif /* CONFIG_ADB */ diff --git a/trunk/arch/m68knommu/kernel/setup.c b/trunk/arch/m68k/kernel/setup_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/setup.c rename to trunk/arch/m68k/kernel/setup_no.c diff --git a/trunk/arch/m68k/kernel/signal.c b/trunk/arch/m68k/kernel/signal.c index a0afc239304e..2e25713e2ead 100644 --- a/trunk/arch/m68k/kernel/signal.c +++ b/trunk/arch/m68k/kernel/signal.c @@ -1,1017 +1,5 @@ -/* - * linux/arch/m68k/kernel/signal.c - * - * Copyright (C) 1991, 1992 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. - */ - -/* - * Linux/m68k support by Hamish Macdonald - * - * 68060 fixes by Jesper Skov - * - * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab - * - * mathemu support by Roman Zippel - * (Note: fpstate in the signal context is completely ignored for the emulator - * and the internal floating point format is put on stack) - */ - -/* - * ++roman (07/09/96): implemented signal stacks (specially for tosemu on - * Atari :-) Current limitation: Only one sigstack can be active at one time. - * If a second signal with SA_ONSTACK set arrives while working on a sigstack, - * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested - * signal handlers! - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -static const int frame_extra_sizes[16] = { - [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ - [2] = sizeof(((struct frame *)0)->un.fmt2), - [3] = sizeof(((struct frame *)0)->un.fmt3), - [4] = sizeof(((struct frame *)0)->un.fmt4), - [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ - [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ - [7] = sizeof(((struct frame *)0)->un.fmt7), - [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */ - [9] = sizeof(((struct frame *)0)->un.fmt9), - [10] = sizeof(((struct frame *)0)->un.fmta), - [11] = sizeof(((struct frame *)0)->un.fmtb), - [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */ - [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */ - [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */ - [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ -}; - -int handle_kernel_fault(struct pt_regs *regs) -{ - const struct exception_table_entry *fixup; - struct pt_regs *tregs; - - /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->pc); - if (!fixup) - return 0; - - /* Create a new four word stack frame, discarding the old one. */ - regs->stkadj = frame_extra_sizes[regs->format]; - tregs = (struct pt_regs *)((long)regs + regs->stkadj); - tregs->vector = regs->vector; - tregs->format = 0; - tregs->pc = fixup->fixup; - tregs->sr = regs->sr; - - return 1; -} - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) -{ - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_restore_sigmask(); - - return -ERESTARTNOHAND; -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags) || - __get_user(mask, &act->sa_mask)) - return -EFAULT; - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) - return -EFAULT; - } - - return ret; -} - -asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, rdusp()); -} - - -/* - * Do a signal return; undo the signal stack. - * - * Keep the return code on the stack quadword aligned! - * That makes the cache flush below easier. - */ - -struct sigframe -{ - char __user *pretcode; - int sig; - int code; - struct sigcontext __user *psc; - char retcode[8]; - unsigned long extramask[_NSIG_WORDS-1]; - struct sigcontext sc; -}; - -struct rt_sigframe -{ - char __user *pretcode; - int sig; - struct siginfo __user *pinfo; - void __user *puc; - char retcode[8]; - struct siginfo info; - struct ucontext uc; -}; - - -static unsigned char fpu_version; /* version number of fpu, set by setup_frame */ - -static inline int restore_fpu_state(struct sigcontext *sc) -{ - int err = 1; - - if (FPU_IS_EMU) { - /* restore registers */ - memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12); - memcpy(current->thread.fp, sc->sc_fpregs, 24); - return 0; - } - - if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { - /* Verify the frame format. */ - if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) - goto out; - if (CPU_IS_020_OR_030) { - if (m68k_fputype & FPU_68881 && - !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4)) - goto out; - if (m68k_fputype & FPU_68882 && - !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4)) - goto out; - } else if (CPU_IS_040) { - if (!(sc->sc_fpstate[1] == 0x00 || - sc->sc_fpstate[1] == 0x28 || - sc->sc_fpstate[1] == 0x60)) - goto out; - } else if (CPU_IS_060) { - if (!(sc->sc_fpstate[3] == 0x00 || - sc->sc_fpstate[3] == 0x60 || - sc->sc_fpstate[3] == 0xe0)) - goto out; - } else - goto out; - - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%%fp0-%%fp1\n\t" - "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" - ".chip 68k" - : /* no outputs */ - : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); - } - __asm__ volatile (".chip 68k/68881\n\t" - "frestore %0\n\t" - ".chip 68k" : : "m" (*sc->sc_fpstate)); - err = 0; - -out: - return err; -} - -#define FPCONTEXT_SIZE 216 -#define uc_fpstate uc_filler[0] -#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] -#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] - -static inline int rt_restore_fpu_state(struct ucontext __user *uc) -{ - unsigned char fpstate[FPCONTEXT_SIZE]; - int context_size = CPU_IS_060 ? 8 : 0; - fpregset_t fpregs; - int err = 1; - - if (FPU_IS_EMU) { - /* restore fpu control register */ - if (__copy_from_user(current->thread.fpcntl, - uc->uc_mcontext.fpregs.f_fpcntl, 12)) - goto out; - /* restore all other fpu register */ - if (__copy_from_user(current->thread.fp, - uc->uc_mcontext.fpregs.f_fpregs, 96)) - goto out; - return 0; - } - - if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) - goto out; - if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { - if (!CPU_IS_060) - context_size = fpstate[1]; - /* Verify the frame format. */ - if (!CPU_IS_060 && (fpstate[0] != fpu_version)) - goto out; - if (CPU_IS_020_OR_030) { - if (m68k_fputype & FPU_68881 && - !(context_size == 0x18 || context_size == 0xb4)) - goto out; - if (m68k_fputype & FPU_68882 && - !(context_size == 0x38 || context_size == 0xd4)) - goto out; - } else if (CPU_IS_040) { - if (!(context_size == 0x00 || - context_size == 0x28 || - context_size == 0x60)) - goto out; - } else if (CPU_IS_060) { - if (!(fpstate[3] == 0x00 || - fpstate[3] == 0x60 || - fpstate[3] == 0xe0)) - goto out; - } else - goto out; - if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, - sizeof(fpregs))) - goto out; - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%%fp0-%%fp7\n\t" - "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" - ".chip 68k" - : /* no outputs */ - : "m" (*fpregs.f_fpregs), - "m" (*fpregs.f_fpcntl)); - } - if (context_size && - __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, - context_size)) - goto out; - __asm__ volatile (".chip 68k/68881\n\t" - "frestore %0\n\t" - ".chip 68k" : : "m" (*fpstate)); - err = 0; - -out: - return err; -} - -static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, - void __user *fp) -{ - int fsize = frame_extra_sizes[formatvec >> 12]; - if (fsize < 0) { - /* - * user process trying to return with weird frame format - */ -#ifdef DEBUG - printk("user process returning with weird frame format\n"); -#endif - return 1; - } - if (!fsize) { - regs->format = formatvec >> 12; - regs->vector = formatvec & 0xfff; - } else { - struct switch_stack *sw = (struct switch_stack *)regs - 1; - unsigned long buf[fsize / 2]; /* yes, twice as much */ - - /* that'll make sure that expansion won't crap over data */ - if (copy_from_user(buf + fsize / 4, fp, fsize)) - return 1; - - /* point of no return */ - regs->format = formatvec >> 12; - regs->vector = formatvec & 0xfff; -#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) - __asm__ __volatile__ - (" movel %0,%/a0\n\t" - " subl %1,%/a0\n\t" /* make room on stack */ - " movel %/a0,%/sp\n\t" /* set stack pointer */ - /* move switch_stack and pt_regs */ - "1: movel %0@+,%/a0@+\n\t" - " dbra %2,1b\n\t" - " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ - " lsrl #2,%1\n\t" - " subql #1,%1\n\t" - /* copy to the gap we'd made */ - "2: movel %4@+,%/a0@+\n\t" - " dbra %1,2b\n\t" - " bral ret_from_signal\n" - : /* no outputs, it doesn't ever return */ - : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), - "n" (frame_offset), "a" (buf + fsize/4) - : "a0"); -#undef frame_offset - } - return 0; -} - -static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp) -{ - int formatvec; - struct sigcontext context; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* get previous context */ - if (copy_from_user(&context, usc, sizeof(context))) - goto badframe; - - /* restore passed registers */ - regs->d0 = context.sc_d0; - regs->d1 = context.sc_d1; - regs->a0 = context.sc_a0; - regs->a1 = context.sc_a1; - regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); - regs->pc = context.sc_pc; - regs->orig_d0 = -1; /* disable syscall checks */ - wrusp(context.sc_usp); - formatvec = context.sc_formatvec; - - err = restore_fpu_state(&context); - - if (err || mangle_kernel_stack(regs, formatvec, fp)) - goto badframe; - - return 0; - -badframe: - return 1; -} - -static inline int -rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, - struct ucontext __user *uc) -{ - int temp; - greg_t __user *gregs = uc->uc_mcontext.gregs; - unsigned long usp; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - err = __get_user(temp, &uc->uc_mcontext.version); - if (temp != MCONTEXT_VERSION) - goto badframe; - /* restore passed registers */ - err |= __get_user(regs->d0, &gregs[0]); - err |= __get_user(regs->d1, &gregs[1]); - err |= __get_user(regs->d2, &gregs[2]); - err |= __get_user(regs->d3, &gregs[3]); - err |= __get_user(regs->d4, &gregs[4]); - err |= __get_user(regs->d5, &gregs[5]); - err |= __get_user(sw->d6, &gregs[6]); - err |= __get_user(sw->d7, &gregs[7]); - err |= __get_user(regs->a0, &gregs[8]); - err |= __get_user(regs->a1, &gregs[9]); - err |= __get_user(regs->a2, &gregs[10]); - err |= __get_user(sw->a3, &gregs[11]); - err |= __get_user(sw->a4, &gregs[12]); - err |= __get_user(sw->a5, &gregs[13]); - err |= __get_user(sw->a6, &gregs[14]); - err |= __get_user(usp, &gregs[15]); - wrusp(usp); - err |= __get_user(regs->pc, &gregs[16]); - err |= __get_user(temp, &gregs[17]); - regs->sr = (regs->sr & 0xff00) | (temp & 0xff); - regs->orig_d0 = -1; /* disable syscall checks */ - err |= __get_user(temp, &uc->uc_formatvec); - - err |= rt_restore_fpu_state(uc); - - if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) - goto badframe; - - if (mangle_kernel_stack(regs, temp, &uc->uc_extra)) - goto badframe; - - return 0; - -badframe: - return 1; -} - -asmlinkage int do_sigreturn(unsigned long __unused) -{ - struct switch_stack *sw = (struct switch_stack *) &__unused; - struct pt_regs *regs = (struct pt_regs *) (sw + 1); - unsigned long usp = rdusp(); - struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); - sigset_t set; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.sc_mask) || - (_NSIG_WORDS > 1 && - __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - current->blocked = set; - recalc_sigpending(); - - if (restore_sigcontext(regs, &frame->sc, frame + 1)) - goto badframe; - return regs->d0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int do_rt_sigreturn(unsigned long __unused) -{ - struct switch_stack *sw = (struct switch_stack *) &__unused; - struct pt_regs *regs = (struct pt_regs *) (sw + 1); - unsigned long usp = rdusp(); - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); - sigset_t set; - - 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); - current->blocked = set; - recalc_sigpending(); - - if (rt_restore_ucontext(regs, sw, &frame->uc)) - goto badframe; - return regs->d0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) -{ - if (FPU_IS_EMU) { - /* save registers */ - memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); - memcpy(sc->sc_fpregs, current->thread.fp, 24); - return; - } - - __asm__ volatile (".chip 68k/68881\n\t" - "fsave %0\n\t" - ".chip 68k" - : : "m" (*sc->sc_fpstate) : "memory"); - - if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { - fpu_version = sc->sc_fpstate[0]; - if (CPU_IS_020_OR_030 && - regs->vector >= (VEC_FPBRUC * 4) && - regs->vector <= (VEC_FPNAN * 4)) { - /* Clear pending exception in 68882 idle frame */ - if (*(unsigned short *) sc->sc_fpstate == 0x1f38) - sc->sc_fpstate[0x38] |= 1 << 3; - } - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %%fp0-%%fp1,%0\n\t" - "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" - ".chip 68k" - : "=m" (*sc->sc_fpregs), - "=m" (*sc->sc_fpcntl) - : /* no inputs */ - : "memory"); - } -} - -static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) -{ - unsigned char fpstate[FPCONTEXT_SIZE]; - int context_size = CPU_IS_060 ? 8 : 0; - int err = 0; - - if (FPU_IS_EMU) { - /* save fpu control register */ - err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, - current->thread.fpcntl, 12); - /* save all other fpu register */ - err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, - current->thread.fp, 96); - return err; - } - - __asm__ volatile (".chip 68k/68881\n\t" - "fsave %0\n\t" - ".chip 68k" - : : "m" (*fpstate) : "memory"); - - err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); - if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { - fpregset_t fpregs; - if (!CPU_IS_060) - context_size = fpstate[1]; - fpu_version = fpstate[0]; - if (CPU_IS_020_OR_030 && - regs->vector >= (VEC_FPBRUC * 4) && - regs->vector <= (VEC_FPNAN * 4)) { - /* Clear pending exception in 68882 idle frame */ - if (*(unsigned short *) fpstate == 0x1f38) - fpstate[0x38] |= 1 << 3; - } - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %%fp0-%%fp7,%0\n\t" - "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" - ".chip 68k" - : "=m" (*fpregs.f_fpregs), - "=m" (*fpregs.f_fpcntl) - : /* no inputs */ - : "memory"); - err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, - sizeof(fpregs)); - } - if (context_size) - err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, - context_size); - return err; -} - -static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, - unsigned long mask) -{ - sc->sc_mask = mask; - sc->sc_usp = rdusp(); - sc->sc_d0 = regs->d0; - sc->sc_d1 = regs->d1; - sc->sc_a0 = regs->a0; - sc->sc_a1 = regs->a1; - sc->sc_sr = regs->sr; - sc->sc_pc = regs->pc; - sc->sc_formatvec = regs->format << 12 | regs->vector; - save_fpu_state(sc, regs); -} - -static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) -{ - struct switch_stack *sw = (struct switch_stack *)regs - 1; - greg_t __user *gregs = uc->uc_mcontext.gregs; - int err = 0; - - err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); - err |= __put_user(regs->d0, &gregs[0]); - err |= __put_user(regs->d1, &gregs[1]); - err |= __put_user(regs->d2, &gregs[2]); - err |= __put_user(regs->d3, &gregs[3]); - err |= __put_user(regs->d4, &gregs[4]); - err |= __put_user(regs->d5, &gregs[5]); - err |= __put_user(sw->d6, &gregs[6]); - err |= __put_user(sw->d7, &gregs[7]); - err |= __put_user(regs->a0, &gregs[8]); - err |= __put_user(regs->a1, &gregs[9]); - err |= __put_user(regs->a2, &gregs[10]); - err |= __put_user(sw->a3, &gregs[11]); - err |= __put_user(sw->a4, &gregs[12]); - err |= __put_user(sw->a5, &gregs[13]); - err |= __put_user(sw->a6, &gregs[14]); - err |= __put_user(rdusp(), &gregs[15]); - err |= __put_user(regs->pc, &gregs[16]); - err |= __put_user(regs->sr, &gregs[17]); - err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); - err |= rt_save_fpu_state(uc, regs); - return err; -} - -static inline void push_cache (unsigned long vaddr) -{ - /* - * Using the old cache_push_v() was really a big waste. - * - * What we are trying to do is to flush 8 bytes to ram. - * Flushing 2 cache lines of 16 bytes is much cheaper than - * flushing 1 or 2 pages, as previously done in - * cache_push_v(). - * Jes - */ - if (CPU_IS_040) { - unsigned long temp; - - __asm__ __volatile__ (".chip 68040\n\t" - "nop\n\t" - "ptestr (%1)\n\t" - "movec %%mmusr,%0\n\t" - ".chip 68k" - : "=r" (temp) - : "a" (vaddr)); - - temp &= PAGE_MASK; - temp |= vaddr & ~PAGE_MASK; - - __asm__ __volatile__ (".chip 68040\n\t" - "nop\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (temp)); - } - else if (CPU_IS_060) { - unsigned long temp; - __asm__ __volatile__ (".chip 68060\n\t" - "plpar (%0)\n\t" - ".chip 68k" - : "=a" (temp) - : "0" (vaddr)); - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (temp)); - } - else { - /* - * 68030/68020 have no writeback cache; - * still need to clear icache. - * Note that vaddr is guaranteed to be long word aligned. - */ - unsigned long temp; - asm volatile ("movec %%cacr,%0" : "=r" (temp)); - temp += 4; - asm volatile ("movec %0,%%caar\n\t" - "movec %1,%%cacr" - : : "r" (vaddr), "r" (temp)); - asm volatile ("movec %0,%%caar\n\t" - "movec %1,%%cacr" - : : "r" (vaddr + 4), "r" (temp)); - } -} - -static inline void __user * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) -{ - unsigned long usp; - - /* Default to using normal stack. */ - usp = rdusp(); - - /* This is the X/Open sanctioned signal stack switching. */ - if (ka->sa.sa_flags & SA_ONSTACK) { - if (!sas_ss_flags(usp)) - usp = current->sas_ss_sp + current->sas_ss_size; - } - return (void __user *)((usp - frame_size) & -8UL); -} - -static int setup_frame (int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame; - int fsize = frame_extra_sizes[regs->format]; - struct sigcontext context; - int err = 0; - - if (fsize < 0) { -#ifdef DEBUG - printk ("setup_frame: Unknown frame format %#x\n", - regs->format); -#endif - goto give_sigsegv; - } - - frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); - - if (fsize) - err |= copy_to_user (frame + 1, regs + 1, fsize); - - err |= __put_user((current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); - - err |= __put_user(regs->vector, &frame->code); - err |= __put_user(&frame->sc, &frame->psc); - - if (_NSIG_WORDS > 1) - err |= copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - - setup_sigcontext(&context, regs, set->sig[0]); - err |= copy_to_user (&frame->sc, &context, sizeof(context)); - - /* Set up to return from userspace. */ - err |= __put_user(frame->retcode, &frame->pretcode); - /* moveq #,d0; trap #0 */ - err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), - (long __user *)(frame->retcode)); - - if (err) - goto give_sigsegv; - - push_cache ((unsigned long) &frame->retcode); - - /* - * Set up registers for signal handler. All the state we are about - * to destroy is successfully copied to sigframe. - */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ka->sa.sa_handler; - - /* - * This is subtle; if we build more than one sigframe, all but the - * first one will see frame format 0 and have fsize == 0, so we won't - * screw stkadj. - */ - if (fsize) - regs->stkadj = fsize; - - /* Prepare to skip over the extra stuff in the exception frame. */ - if (regs->stkadj) { - struct pt_regs *tregs = - (struct pt_regs *)((ulong)regs + regs->stkadj); -#ifdef DEBUG - printk("Performing stackadjust=%04x\n", regs->stkadj); -#endif - /* This must be copied with decreasing addresses to - handle overlaps. */ - tregs->vector = 0; - tregs->format = 0; - tregs->pc = regs->pc; - tregs->sr = regs->sr; - } - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return err; -} - -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 fsize = frame_extra_sizes[regs->format]; - int err = 0; - - if (fsize < 0) { -#ifdef DEBUG - printk ("setup_frame: Unknown frame format %#x\n", - regs->format); -#endif - goto give_sigsegv; - } - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (fsize) - err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); - - err |= __put_user((current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - - /* Create 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(rdusp()), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= rt_setup_ucontext(&frame->uc, regs); - err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); - - /* Set up to return from userspace. */ - err |= __put_user(frame->retcode, &frame->pretcode); -#ifdef __mcoldfire__ - /* movel #__NR_rt_sigreturn,d0; trap #0 */ - err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0)); - err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16), - (long __user *)(frame->retcode + 4)); +#ifdef CONFIG_MMU +#include "signal_mm.c" #else - /* moveq #,d0; notb d0; trap #0 */ - err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), - (long __user *)(frame->retcode + 0)); - err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); -#endif - - if (err) - goto give_sigsegv; - - push_cache ((unsigned long) &frame->retcode); - - /* - * Set up registers for signal handler. All the state we are about - * to destroy is successfully copied to sigframe. - */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ka->sa.sa_handler; - - /* - * This is subtle; if we build more than one sigframe, all but the - * first one will see frame format 0 and have fsize == 0, so we won't - * screw stkadj. - */ - if (fsize) - regs->stkadj = fsize; - - /* Prepare to skip over the extra stuff in the exception frame. */ - if (regs->stkadj) { - struct pt_regs *tregs = - (struct pt_regs *)((ulong)regs + regs->stkadj); -#ifdef DEBUG - printk("Performing stackadjust=%04x\n", regs->stkadj); +#include "signal_no.c" #endif - /* This must be copied with decreasing addresses to - handle overlaps. */ - tregs->vector = 0; - tregs->format = 0; - tregs->pc = regs->pc; - tregs->sr = regs->sr; - } - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return err; -} - -static inline void -handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) -{ - switch (regs->d0) { - case -ERESTARTNOHAND: - if (!has_handler) - goto do_restart; - regs->d0 = -EINTR; - break; - - case -ERESTART_RESTARTBLOCK: - if (!has_handler) { - regs->d0 = __NR_restart_syscall; - regs->pc -= 2; - break; - } - regs->d0 = -EINTR; - break; - - case -ERESTARTSYS: - if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { - regs->d0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - do_restart: - regs->d0 = regs->orig_d0; - regs->pc -= 2; - break; - } -} - -void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) -{ - if (regs->orig_d0 < 0) - return; - switch (regs->d0) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - regs->d0 = regs->orig_d0; - regs->orig_d0 = -1; - regs->pc -= 2; - break; - } -} - -/* - * OK, we're invoking a handler - */ -static void -handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) -{ - int err; - /* are we from a system call? */ - if (regs->orig_d0 >= 0) - /* If so, check system call restarting.. */ - handle_restart(regs, ka, 1); - - /* set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - err = setup_rt_frame(sig, ka, info, oldset, regs); - else - err = setup_frame(sig, ka, oldset, regs); - - if (err) - return; - - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - - if (test_thread_flag(TIF_DELAYED_TRACE)) { - regs->sr &= ~0x8000; - send_sig(SIGTRAP, current, 1); - } - - clear_thread_flag(TIF_RESTORE_SIGMASK); -} - -/* - * 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. - */ -asmlinkage void do_signal(struct pt_regs *regs) -{ - siginfo_t info; - struct k_sigaction ka; - int signr; - sigset_t *oldset; - - current->thread.esp0 = (unsigned long) regs; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->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; - } - - /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) - /* Restart the system call - no handlers present */ - handle_restart(regs, NULL, 0); - - /* If there's no signal to deliver, we just restore the saved mask. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } -} diff --git a/trunk/arch/m68k/kernel/signal_mm.c b/trunk/arch/m68k/kernel/signal_mm.c new file mode 100644 index 000000000000..a0afc239304e --- /dev/null +++ b/trunk/arch/m68k/kernel/signal_mm.c @@ -0,0 +1,1017 @@ +/* + * linux/arch/m68k/kernel/signal.c + * + * Copyright (C) 1991, 1992 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. + */ + +/* + * Linux/m68k support by Hamish Macdonald + * + * 68060 fixes by Jesper Skov + * + * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab + * + * mathemu support by Roman Zippel + * (Note: fpstate in the signal context is completely ignored for the emulator + * and the internal floating point format is put on stack) + */ + +/* + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on + * Atari :-) Current limitation: Only one sigstack can be active at one time. + * If a second signal with SA_ONSTACK set arrives while working on a sigstack, + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested + * signal handlers! + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +static const int frame_extra_sizes[16] = { + [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ + [2] = sizeof(((struct frame *)0)->un.fmt2), + [3] = sizeof(((struct frame *)0)->un.fmt3), + [4] = sizeof(((struct frame *)0)->un.fmt4), + [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ + [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ + [7] = sizeof(((struct frame *)0)->un.fmt7), + [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */ + [9] = sizeof(((struct frame *)0)->un.fmt9), + [10] = sizeof(((struct frame *)0)->un.fmta), + [11] = sizeof(((struct frame *)0)->un.fmtb), + [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */ + [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */ + [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */ + [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ +}; + +int handle_kernel_fault(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + struct pt_regs *tregs; + + /* Are we prepared to handle this kernel fault? */ + fixup = search_exception_tables(regs->pc); + if (!fixup) + return 0; + + /* Create a new four word stack frame, discarding the old one. */ + regs->stkadj = frame_extra_sizes[regs->format]; + tregs = (struct pt_regs *)((long)regs + regs->stkadj); + tregs->vector = regs->vector; + tregs->format = 0; + tregs->pc = fixup->fixup; + tregs->sr = regs->sr; + + return 1; +} + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) +{ + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + current->saved_sigmask = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_restore_sigmask(); + + return -ERESTARTNOHAND; +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) + return -EFAULT; + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) +{ + return do_sigaltstack(uss, uoss, rdusp()); +} + + +/* + * Do a signal return; undo the signal stack. + * + * Keep the return code on the stack quadword aligned! + * That makes the cache flush below easier. + */ + +struct sigframe +{ + char __user *pretcode; + int sig; + int code; + struct sigcontext __user *psc; + char retcode[8]; + unsigned long extramask[_NSIG_WORDS-1]; + struct sigcontext sc; +}; + +struct rt_sigframe +{ + char __user *pretcode; + int sig; + struct siginfo __user *pinfo; + void __user *puc; + char retcode[8]; + struct siginfo info; + struct ucontext uc; +}; + + +static unsigned char fpu_version; /* version number of fpu, set by setup_frame */ + +static inline int restore_fpu_state(struct sigcontext *sc) +{ + int err = 1; + + if (FPU_IS_EMU) { + /* restore registers */ + memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12); + memcpy(current->thread.fp, sc->sc_fpregs, 24); + return 0; + } + + if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { + /* Verify the frame format. */ + if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) + goto out; + if (CPU_IS_020_OR_030) { + if (m68k_fputype & FPU_68881 && + !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4)) + goto out; + if (m68k_fputype & FPU_68882 && + !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4)) + goto out; + } else if (CPU_IS_040) { + if (!(sc->sc_fpstate[1] == 0x00 || + sc->sc_fpstate[1] == 0x28 || + sc->sc_fpstate[1] == 0x60)) + goto out; + } else if (CPU_IS_060) { + if (!(sc->sc_fpstate[3] == 0x00 || + sc->sc_fpstate[3] == 0x60 || + sc->sc_fpstate[3] == 0xe0)) + goto out; + } else + goto out; + + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%%fp0-%%fp1\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); + } + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" : : "m" (*sc->sc_fpstate)); + err = 0; + +out: + return err; +} + +#define FPCONTEXT_SIZE 216 +#define uc_fpstate uc_filler[0] +#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] +#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] + +static inline int rt_restore_fpu_state(struct ucontext __user *uc) +{ + unsigned char fpstate[FPCONTEXT_SIZE]; + int context_size = CPU_IS_060 ? 8 : 0; + fpregset_t fpregs; + int err = 1; + + if (FPU_IS_EMU) { + /* restore fpu control register */ + if (__copy_from_user(current->thread.fpcntl, + uc->uc_mcontext.fpregs.f_fpcntl, 12)) + goto out; + /* restore all other fpu register */ + if (__copy_from_user(current->thread.fp, + uc->uc_mcontext.fpregs.f_fpregs, 96)) + goto out; + return 0; + } + + if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) + goto out; + if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { + if (!CPU_IS_060) + context_size = fpstate[1]; + /* Verify the frame format. */ + if (!CPU_IS_060 && (fpstate[0] != fpu_version)) + goto out; + if (CPU_IS_020_OR_030) { + if (m68k_fputype & FPU_68881 && + !(context_size == 0x18 || context_size == 0xb4)) + goto out; + if (m68k_fputype & FPU_68882 && + !(context_size == 0x38 || context_size == 0xd4)) + goto out; + } else if (CPU_IS_040) { + if (!(context_size == 0x00 || + context_size == 0x28 || + context_size == 0x60)) + goto out; + } else if (CPU_IS_060) { + if (!(fpstate[3] == 0x00 || + fpstate[3] == 0x60 || + fpstate[3] == 0xe0)) + goto out; + } else + goto out; + if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, + sizeof(fpregs))) + goto out; + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%%fp0-%%fp7\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*fpregs.f_fpregs), + "m" (*fpregs.f_fpcntl)); + } + if (context_size && + __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, + context_size)) + goto out; + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" : : "m" (*fpstate)); + err = 0; + +out: + return err; +} + +static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, + void __user *fp) +{ + int fsize = frame_extra_sizes[formatvec >> 12]; + if (fsize < 0) { + /* + * user process trying to return with weird frame format + */ +#ifdef DEBUG + printk("user process returning with weird frame format\n"); +#endif + return 1; + } + if (!fsize) { + regs->format = formatvec >> 12; + regs->vector = formatvec & 0xfff; + } else { + struct switch_stack *sw = (struct switch_stack *)regs - 1; + unsigned long buf[fsize / 2]; /* yes, twice as much */ + + /* that'll make sure that expansion won't crap over data */ + if (copy_from_user(buf + fsize / 4, fp, fsize)) + return 1; + + /* point of no return */ + regs->format = formatvec >> 12; + regs->vector = formatvec & 0xfff; +#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) + __asm__ __volatile__ + (" movel %0,%/a0\n\t" + " subl %1,%/a0\n\t" /* make room on stack */ + " movel %/a0,%/sp\n\t" /* set stack pointer */ + /* move switch_stack and pt_regs */ + "1: movel %0@+,%/a0@+\n\t" + " dbra %2,1b\n\t" + " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ + " lsrl #2,%1\n\t" + " subql #1,%1\n\t" + /* copy to the gap we'd made */ + "2: movel %4@+,%/a0@+\n\t" + " dbra %1,2b\n\t" + " bral ret_from_signal\n" + : /* no outputs, it doesn't ever return */ + : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), + "n" (frame_offset), "a" (buf + fsize/4) + : "a0"); +#undef frame_offset + } + return 0; +} + +static inline int +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp) +{ + int formatvec; + struct sigcontext context; + int err; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + /* get previous context */ + if (copy_from_user(&context, usc, sizeof(context))) + goto badframe; + + /* restore passed registers */ + regs->d0 = context.sc_d0; + regs->d1 = context.sc_d1; + regs->a0 = context.sc_a0; + regs->a1 = context.sc_a1; + regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); + regs->pc = context.sc_pc; + regs->orig_d0 = -1; /* disable syscall checks */ + wrusp(context.sc_usp); + formatvec = context.sc_formatvec; + + err = restore_fpu_state(&context); + + if (err || mangle_kernel_stack(regs, formatvec, fp)) + goto badframe; + + return 0; + +badframe: + return 1; +} + +static inline int +rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, + struct ucontext __user *uc) +{ + int temp; + greg_t __user *gregs = uc->uc_mcontext.gregs; + unsigned long usp; + int err; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + err = __get_user(temp, &uc->uc_mcontext.version); + if (temp != MCONTEXT_VERSION) + goto badframe; + /* restore passed registers */ + err |= __get_user(regs->d0, &gregs[0]); + err |= __get_user(regs->d1, &gregs[1]); + err |= __get_user(regs->d2, &gregs[2]); + err |= __get_user(regs->d3, &gregs[3]); + err |= __get_user(regs->d4, &gregs[4]); + err |= __get_user(regs->d5, &gregs[5]); + err |= __get_user(sw->d6, &gregs[6]); + err |= __get_user(sw->d7, &gregs[7]); + err |= __get_user(regs->a0, &gregs[8]); + err |= __get_user(regs->a1, &gregs[9]); + err |= __get_user(regs->a2, &gregs[10]); + err |= __get_user(sw->a3, &gregs[11]); + err |= __get_user(sw->a4, &gregs[12]); + err |= __get_user(sw->a5, &gregs[13]); + err |= __get_user(sw->a6, &gregs[14]); + err |= __get_user(usp, &gregs[15]); + wrusp(usp); + err |= __get_user(regs->pc, &gregs[16]); + err |= __get_user(temp, &gregs[17]); + regs->sr = (regs->sr & 0xff00) | (temp & 0xff); + regs->orig_d0 = -1; /* disable syscall checks */ + err |= __get_user(temp, &uc->uc_formatvec); + + err |= rt_restore_fpu_state(uc); + + if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) + goto badframe; + + if (mangle_kernel_stack(regs, temp, &uc->uc_extra)) + goto badframe; + + return 0; + +badframe: + return 1; +} + +asmlinkage int do_sigreturn(unsigned long __unused) +{ + struct switch_stack *sw = (struct switch_stack *) &__unused; + struct pt_regs *regs = (struct pt_regs *) (sw + 1); + unsigned long usp = rdusp(); + struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); + sigset_t set; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.sc_mask) || + (_NSIG_WORDS > 1 && + __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + current->blocked = set; + recalc_sigpending(); + + if (restore_sigcontext(regs, &frame->sc, frame + 1)) + goto badframe; + return regs->d0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int do_rt_sigreturn(unsigned long __unused) +{ + struct switch_stack *sw = (struct switch_stack *) &__unused; + struct pt_regs *regs = (struct pt_regs *) (sw + 1); + unsigned long usp = rdusp(); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); + sigset_t set; + + 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); + current->blocked = set; + recalc_sigpending(); + + if (rt_restore_ucontext(regs, sw, &frame->uc)) + goto badframe; + return regs->d0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) +{ + if (FPU_IS_EMU) { + /* save registers */ + memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); + memcpy(sc->sc_fpregs, current->thread.fp, 24); + return; + } + + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*sc->sc_fpstate) : "memory"); + + if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { + fpu_version = sc->sc_fpstate[0]; + if (CPU_IS_020_OR_030 && + regs->vector >= (VEC_FPBRUC * 4) && + regs->vector <= (VEC_FPNAN * 4)) { + /* Clear pending exception in 68882 idle frame */ + if (*(unsigned short *) sc->sc_fpstate == 0x1f38) + sc->sc_fpstate[0x38] |= 1 << 3; + } + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %%fp0-%%fp1,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" + ".chip 68k" + : "=m" (*sc->sc_fpregs), + "=m" (*sc->sc_fpcntl) + : /* no inputs */ + : "memory"); + } +} + +static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) +{ + unsigned char fpstate[FPCONTEXT_SIZE]; + int context_size = CPU_IS_060 ? 8 : 0; + int err = 0; + + if (FPU_IS_EMU) { + /* save fpu control register */ + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, + current->thread.fpcntl, 12); + /* save all other fpu register */ + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, + current->thread.fp, 96); + return err; + } + + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*fpstate) : "memory"); + + err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); + if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { + fpregset_t fpregs; + if (!CPU_IS_060) + context_size = fpstate[1]; + fpu_version = fpstate[0]; + if (CPU_IS_020_OR_030 && + regs->vector >= (VEC_FPBRUC * 4) && + regs->vector <= (VEC_FPNAN * 4)) { + /* Clear pending exception in 68882 idle frame */ + if (*(unsigned short *) fpstate == 0x1f38) + fpstate[0x38] |= 1 << 3; + } + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %%fp0-%%fp7,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" + ".chip 68k" + : "=m" (*fpregs.f_fpregs), + "=m" (*fpregs.f_fpcntl) + : /* no inputs */ + : "memory"); + err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, + sizeof(fpregs)); + } + if (context_size) + err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, + context_size); + return err; +} + +static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + unsigned long mask) +{ + sc->sc_mask = mask; + sc->sc_usp = rdusp(); + sc->sc_d0 = regs->d0; + sc->sc_d1 = regs->d1; + sc->sc_a0 = regs->a0; + sc->sc_a1 = regs->a1; + sc->sc_sr = regs->sr; + sc->sc_pc = regs->pc; + sc->sc_formatvec = regs->format << 12 | regs->vector; + save_fpu_state(sc, regs); +} + +static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) +{ + struct switch_stack *sw = (struct switch_stack *)regs - 1; + greg_t __user *gregs = uc->uc_mcontext.gregs; + int err = 0; + + err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); + err |= __put_user(regs->d0, &gregs[0]); + err |= __put_user(regs->d1, &gregs[1]); + err |= __put_user(regs->d2, &gregs[2]); + err |= __put_user(regs->d3, &gregs[3]); + err |= __put_user(regs->d4, &gregs[4]); + err |= __put_user(regs->d5, &gregs[5]); + err |= __put_user(sw->d6, &gregs[6]); + err |= __put_user(sw->d7, &gregs[7]); + err |= __put_user(regs->a0, &gregs[8]); + err |= __put_user(regs->a1, &gregs[9]); + err |= __put_user(regs->a2, &gregs[10]); + err |= __put_user(sw->a3, &gregs[11]); + err |= __put_user(sw->a4, &gregs[12]); + err |= __put_user(sw->a5, &gregs[13]); + err |= __put_user(sw->a6, &gregs[14]); + err |= __put_user(rdusp(), &gregs[15]); + err |= __put_user(regs->pc, &gregs[16]); + err |= __put_user(regs->sr, &gregs[17]); + err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); + err |= rt_save_fpu_state(uc, regs); + return err; +} + +static inline void push_cache (unsigned long vaddr) +{ + /* + * Using the old cache_push_v() was really a big waste. + * + * What we are trying to do is to flush 8 bytes to ram. + * Flushing 2 cache lines of 16 bytes is much cheaper than + * flushing 1 or 2 pages, as previously done in + * cache_push_v(). + * Jes + */ + if (CPU_IS_040) { + unsigned long temp; + + __asm__ __volatile__ (".chip 68040\n\t" + "nop\n\t" + "ptestr (%1)\n\t" + "movec %%mmusr,%0\n\t" + ".chip 68k" + : "=r" (temp) + : "a" (vaddr)); + + temp &= PAGE_MASK; + temp |= vaddr & ~PAGE_MASK; + + __asm__ __volatile__ (".chip 68040\n\t" + "nop\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (temp)); + } + else if (CPU_IS_060) { + unsigned long temp; + __asm__ __volatile__ (".chip 68060\n\t" + "plpar (%0)\n\t" + ".chip 68k" + : "=a" (temp) + : "0" (vaddr)); + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (temp)); + } + else { + /* + * 68030/68020 have no writeback cache; + * still need to clear icache. + * Note that vaddr is guaranteed to be long word aligned. + */ + unsigned long temp; + asm volatile ("movec %%cacr,%0" : "=r" (temp)); + temp += 4; + asm volatile ("movec %0,%%caar\n\t" + "movec %1,%%cacr" + : : "r" (vaddr), "r" (temp)); + asm volatile ("movec %0,%%caar\n\t" + "movec %1,%%cacr" + : : "r" (vaddr + 4), "r" (temp)); + } +} + +static inline void __user * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + unsigned long usp; + + /* Default to using normal stack. */ + usp = rdusp(); + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (!sas_ss_flags(usp)) + usp = current->sas_ss_sp + current->sas_ss_size; + } + return (void __user *)((usp - frame_size) & -8UL); +} + +static int setup_frame (int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe __user *frame; + int fsize = frame_extra_sizes[regs->format]; + struct sigcontext context; + int err = 0; + + if (fsize < 0) { +#ifdef DEBUG + printk ("setup_frame: Unknown frame format %#x\n", + regs->format); +#endif + goto give_sigsegv; + } + + frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); + + if (fsize) + err |= copy_to_user (frame + 1, regs + 1, fsize); + + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + + err |= __put_user(regs->vector, &frame->code); + err |= __put_user(&frame->sc, &frame->psc); + + if (_NSIG_WORDS > 1) + err |= copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + + setup_sigcontext(&context, regs, set->sig[0]); + err |= copy_to_user (&frame->sc, &context, sizeof(context)); + + /* Set up to return from userspace. */ + err |= __put_user(frame->retcode, &frame->pretcode); + /* moveq #,d0; trap #0 */ + err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), + (long __user *)(frame->retcode)); + + if (err) + goto give_sigsegv; + + push_cache ((unsigned long) &frame->retcode); + + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ + wrusp ((unsigned long) frame); + regs->pc = (unsigned long) ka->sa.sa_handler; + + /* + * This is subtle; if we build more than one sigframe, all but the + * first one will see frame format 0 and have fsize == 0, so we won't + * screw stkadj. + */ + if (fsize) + regs->stkadj = fsize; + + /* Prepare to skip over the extra stuff in the exception frame. */ + if (regs->stkadj) { + struct pt_regs *tregs = + (struct pt_regs *)((ulong)regs + regs->stkadj); +#ifdef DEBUG + printk("Performing stackadjust=%04x\n", regs->stkadj); +#endif + /* This must be copied with decreasing addresses to + handle overlaps. */ + tregs->vector = 0; + tregs->format = 0; + tregs->pc = regs->pc; + tregs->sr = regs->sr; + } + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return err; +} + +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 fsize = frame_extra_sizes[regs->format]; + int err = 0; + + if (fsize < 0) { +#ifdef DEBUG + printk ("setup_frame: Unknown frame format %#x\n", + regs->format); +#endif + goto give_sigsegv; + } + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (fsize) + err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); + + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create 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(rdusp()), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= rt_setup_ucontext(&frame->uc, regs); + err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. */ + err |= __put_user(frame->retcode, &frame->pretcode); +#ifdef __mcoldfire__ + /* movel #__NR_rt_sigreturn,d0; trap #0 */ + err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0)); + err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16), + (long __user *)(frame->retcode + 4)); +#else + /* moveq #,d0; notb d0; trap #0 */ + err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), + (long __user *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); +#endif + + if (err) + goto give_sigsegv; + + push_cache ((unsigned long) &frame->retcode); + + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ + wrusp ((unsigned long) frame); + regs->pc = (unsigned long) ka->sa.sa_handler; + + /* + * This is subtle; if we build more than one sigframe, all but the + * first one will see frame format 0 and have fsize == 0, so we won't + * screw stkadj. + */ + if (fsize) + regs->stkadj = fsize; + + /* Prepare to skip over the extra stuff in the exception frame. */ + if (regs->stkadj) { + struct pt_regs *tregs = + (struct pt_regs *)((ulong)regs + regs->stkadj); +#ifdef DEBUG + printk("Performing stackadjust=%04x\n", regs->stkadj); +#endif + /* This must be copied with decreasing addresses to + handle overlaps. */ + tregs->vector = 0; + tregs->format = 0; + tregs->pc = regs->pc; + tregs->sr = regs->sr; + } + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return err; +} + +static inline void +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) +{ + switch (regs->d0) { + case -ERESTARTNOHAND: + if (!has_handler) + goto do_restart; + regs->d0 = -EINTR; + break; + + case -ERESTART_RESTARTBLOCK: + if (!has_handler) { + regs->d0 = __NR_restart_syscall; + regs->pc -= 2; + break; + } + regs->d0 = -EINTR; + break; + + case -ERESTARTSYS: + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { + regs->d0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + do_restart: + regs->d0 = regs->orig_d0; + regs->pc -= 2; + break; + } +} + +void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) +{ + if (regs->orig_d0 < 0) + return; + switch (regs->d0) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + regs->d0 = regs->orig_d0; + regs->orig_d0 = -1; + regs->pc -= 2; + break; + } +} + +/* + * OK, we're invoking a handler + */ +static void +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) +{ + int err; + /* are we from a system call? */ + if (regs->orig_d0 >= 0) + /* If so, check system call restarting.. */ + handle_restart(regs, ka, 1); + + /* set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + err = setup_rt_frame(sig, ka, info, oldset, regs); + else + err = setup_frame(sig, ka, oldset, regs); + + if (err) + return; + + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + + if (test_thread_flag(TIF_DELAYED_TRACE)) { + regs->sr &= ~0x8000; + send_sig(SIGTRAP, current, 1); + } + + clear_thread_flag(TIF_RESTORE_SIGMASK); +} + +/* + * 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. + */ +asmlinkage void do_signal(struct pt_regs *regs) +{ + siginfo_t info; + struct k_sigaction ka; + int signr; + sigset_t *oldset; + + current->thread.esp0 = (unsigned long) regs; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->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; + } + + /* Did we come from a system call? */ + if (regs->orig_d0 >= 0) + /* Restart the system call - no handlers present */ + handle_restart(regs, NULL, 0); + + /* If there's no signal to deliver, we just restore the saved mask. */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } +} diff --git a/trunk/arch/m68knommu/kernel/signal.c b/trunk/arch/m68k/kernel/signal_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/signal.c rename to trunk/arch/m68k/kernel/signal_no.c diff --git a/trunk/arch/m68k/kernel/sys_m68k.c b/trunk/arch/m68k/kernel/sys_m68k.c index 3db2e7f902aa..63013df33584 100644 --- a/trunk/arch/m68k/kernel/sys_m68k.c +++ b/trunk/arch/m68k/kernel/sys_m68k.c @@ -1,546 +1,5 @@ -/* - * linux/arch/m68k/kernel/sys_m68k.c - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/m68k - * platform. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - /* - * This is wrong for sun3 - there PAGE_SIZE is 8Kb, - * so we need to shift the argument down by 1; m68k mmap64(3) - * (in libc) expects the last argument of mmap2 in 4Kb units. - */ - return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); -} - -/* Convert virtual (user) address VADDR to physical address PADDR */ -#define virt_to_phys_040(vaddr) \ -({ \ - unsigned long _mmusr, _paddr; \ - \ - __asm__ __volatile__ (".chip 68040\n\t" \ - "ptestr (%1)\n\t" \ - "movec %%mmusr,%0\n\t" \ - ".chip 68k" \ - : "=r" (_mmusr) \ - : "a" (vaddr)); \ - _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \ - _paddr; \ -}) - -static inline int -cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len) -{ - unsigned long paddr, i; - - switch (scope) - { - case FLUSH_SCOPE_ALL: - switch (cache) - { - case FLUSH_CACHE_DATA: - /* This nop is needed for some broken versions of the 68040. */ - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %dc\n\t" - ".chip 68k"); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %ic\n\t" - ".chip 68k"); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %bc\n\t" - ".chip 68k"); - break; - } - break; - - case FLUSH_SCOPE_LINE: - /* Find the physical address of the first mapped page in the - address range. */ - if ((paddr = virt_to_phys_040(addr))) { - paddr += addr & ~(PAGE_MASK | 15); - len = (len + (addr & 15) + 15) >> 4; - } else { - unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); - - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - tmp = PAGE_SIZE; - for (;;) - { - if ((paddr = virt_to_phys_040(addr))) - break; - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - } - len = (len + 15) >> 4; - } - i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; - while (len--) - { - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - if (!--i && len) - { - /* - * No need to page align here since it is done by - * virt_to_phys_040(). - */ - addr += PAGE_SIZE; - i = PAGE_SIZE / 16; - /* Recompute physical address when crossing a page - boundary. */ - for (;;) - { - if ((paddr = virt_to_phys_040(addr))) - break; - if (len <= i) - return 0; - len -= i; - addr += PAGE_SIZE; - } - } - else - paddr += 16; - } - break; - - default: - case FLUSH_SCOPE_PAGE: - len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); - for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) - { - if (!(paddr = virt_to_phys_040(addr))) - continue; - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - } - break; - } - return 0; -} - -#define virt_to_phys_060(vaddr) \ -({ \ - unsigned long paddr; \ - __asm__ __volatile__ (".chip 68060\n\t" \ - "plpar (%0)\n\t" \ - ".chip 68k" \ - : "=a" (paddr) \ - : "0" (vaddr)); \ - (paddr); /* XXX */ \ -}) - -static inline int -cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) -{ - unsigned long paddr, i; - - /* - * 68060 manual says: - * cpush %dc : flush DC, remains valid (with our %cacr setup) - * cpush %ic : invalidate IC - * cpush %bc : flush DC + invalidate IC - */ - switch (scope) - { - case FLUSH_SCOPE_ALL: - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %dc\n\t" - ".chip 68k"); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %ic\n\t" - ".chip 68k"); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %bc\n\t" - ".chip 68k"); - break; - } - break; - - case FLUSH_SCOPE_LINE: - /* Find the physical address of the first mapped page in the - address range. */ - len += addr & 15; - addr &= -16; - if (!(paddr = virt_to_phys_060(addr))) { - unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); - - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - tmp = PAGE_SIZE; - for (;;) - { - if ((paddr = virt_to_phys_060(addr))) - break; - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - } - } - len = (len + 15) >> 4; - i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; - while (len--) - { - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - if (!--i && len) - { - - /* - * We just want to jump to the first cache line - * in the next page. - */ - addr += PAGE_SIZE; - addr &= PAGE_MASK; - - i = PAGE_SIZE / 16; - /* Recompute physical address when crossing a page - boundary. */ - for (;;) - { - if ((paddr = virt_to_phys_060(addr))) - break; - if (len <= i) - return 0; - len -= i; - addr += PAGE_SIZE; - } - } - else - paddr += 16; - } - break; - - default: - case FLUSH_SCOPE_PAGE: - len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); - addr &= PAGE_MASK; /* Workaround for bug in some - revisions of the 68060 */ - for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) - { - if (!(paddr = virt_to_phys_060(addr))) - continue; - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - } - break; - } - return 0; -} - -/* sys_cacheflush -- flush (part of) the processor cache. */ -asmlinkage int -sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) -{ - struct vm_area_struct *vma; - int ret = -EINVAL; - - if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || - cache & ~FLUSH_CACHE_BOTH) - goto out; - - if (scope == FLUSH_SCOPE_ALL) { - /* Only the superuser may explicitly flush the whole cache. */ - ret = -EPERM; - if (!capable(CAP_SYS_ADMIN)) - goto out; - } else { - /* - * Verify that the specified address region actually belongs - * to this process. - */ - vma = find_vma (current->mm, addr); - ret = -EINVAL; - /* Check for overflow. */ - if (addr + len < addr) - goto out; - if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) - goto out; - } - - if (CPU_IS_020_OR_030) { - if (scope == FLUSH_SCOPE_LINE && len < 256) { - unsigned long cacr; - __asm__ ("movec %%cacr, %0" : "=r" (cacr)); - if (cache & FLUSH_CACHE_INSN) - cacr |= 4; - if (cache & FLUSH_CACHE_DATA) - cacr |= 0x400; - len >>= 2; - while (len--) { - __asm__ __volatile__ ("movec %1, %%caar\n\t" - "movec %0, %%cacr" - : /* no outputs */ - : "r" (cacr), "r" (addr)); - addr += 4; - } - } else { - /* Flush the whole cache, even if page granularity requested. */ - unsigned long cacr; - __asm__ ("movec %%cacr, %0" : "=r" (cacr)); - if (cache & FLUSH_CACHE_INSN) - cacr |= 8; - if (cache & FLUSH_CACHE_DATA) - cacr |= 0x800; - __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); - } - ret = 0; - goto out; - } else { - /* - * 040 or 060: don't blindly trust 'scope', someone could - * try to flush a few megs of memory. - */ - - if (len>=3*PAGE_SIZE && scope=10*PAGE_SIZE && scopetp_value; -} - -asmlinkage int sys_set_thread_area(unsigned long tp) -{ - current_thread_info()->tp_value = tp; - return 0; -} - -/* This syscall gets its arguments in A0 (mem), D2 (oldval) and - D1 (newval). */ -asmlinkage int -sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, - unsigned long __user * mem) -{ - /* This was borrowed from ARM's implementation. */ - for (;;) { - struct mm_struct *mm = current->mm; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - spinlock_t *ptl; - unsigned long mem_value; - - down_read(&mm->mmap_sem); - pgd = pgd_offset(mm, (unsigned long)mem); - if (!pgd_present(*pgd)) - goto bad_access; - pmd = pmd_offset(pgd, (unsigned long)mem); - if (!pmd_present(*pmd)) - goto bad_access; - pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); - if (!pte_present(*pte) || !pte_dirty(*pte) - || !pte_write(*pte)) { - pte_unmap_unlock(pte, ptl); - goto bad_access; - } - - mem_value = *mem; - if (mem_value == oldval) - *mem = newval; - - pte_unmap_unlock(pte, ptl); - up_read(&mm->mmap_sem); - return mem_value; - - bad_access: - up_read(&mm->mmap_sem); - /* This is not necessarily a bad access, we can get here if - a memory we're trying to write to should be copied-on-write. - Make the kernel do the necessary page stuff, then re-iterate. - Simulate a write access fault to do that. */ - { - /* The first argument of the function corresponds to - D1, which is the first field of struct pt_regs. */ - struct pt_regs *fp = (struct pt_regs *)&newval; - - /* '3' is an RMW flag. */ - if (do_page_fault(fp, (unsigned long)mem, 3)) - /* If the do_page_fault() failed, we don't - have anything meaningful to return. - There should be a SIGSEGV pending for - the process. */ - return 0xdeadbeef; - } - } -} - -asmlinkage int sys_atomic_barrier(void) -{ - /* no code needed for uniprocs */ - return 0; -} +#ifdef CONFIG_MMU +#include "sys_m68k_mm.c" +#else +#include "sys_m68k_no.c" +#endif diff --git a/trunk/arch/m68k/kernel/sys_m68k_mm.c b/trunk/arch/m68k/kernel/sys_m68k_mm.c new file mode 100644 index 000000000000..3db2e7f902aa --- /dev/null +++ b/trunk/arch/m68k/kernel/sys_m68k_mm.c @@ -0,0 +1,546 @@ +/* + * linux/arch/m68k/kernel/sys_m68k.c + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/m68k + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code); + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + /* + * This is wrong for sun3 - there PAGE_SIZE is 8Kb, + * so we need to shift the argument down by 1; m68k mmap64(3) + * (in libc) expects the last argument of mmap2 in 4Kb units. + */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); +} + +/* Convert virtual (user) address VADDR to physical address PADDR */ +#define virt_to_phys_040(vaddr) \ +({ \ + unsigned long _mmusr, _paddr; \ + \ + __asm__ __volatile__ (".chip 68040\n\t" \ + "ptestr (%1)\n\t" \ + "movec %%mmusr,%0\n\t" \ + ".chip 68k" \ + : "=r" (_mmusr) \ + : "a" (vaddr)); \ + _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \ + _paddr; \ +}) + +static inline int +cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len) +{ + unsigned long paddr, i; + + switch (scope) + { + case FLUSH_SCOPE_ALL: + switch (cache) + { + case FLUSH_CACHE_DATA: + /* This nop is needed for some broken versions of the 68040. */ + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %dc\n\t" + ".chip 68k"); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %ic\n\t" + ".chip 68k"); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %bc\n\t" + ".chip 68k"); + break; + } + break; + + case FLUSH_SCOPE_LINE: + /* Find the physical address of the first mapped page in the + address range. */ + if ((paddr = virt_to_phys_040(addr))) { + paddr += addr & ~(PAGE_MASK | 15); + len = (len + (addr & 15) + 15) >> 4; + } else { + unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); + + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + tmp = PAGE_SIZE; + for (;;) + { + if ((paddr = virt_to_phys_040(addr))) + break; + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + } + len = (len + 15) >> 4; + } + i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; + while (len--) + { + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + if (!--i && len) + { + /* + * No need to page align here since it is done by + * virt_to_phys_040(). + */ + addr += PAGE_SIZE; + i = PAGE_SIZE / 16; + /* Recompute physical address when crossing a page + boundary. */ + for (;;) + { + if ((paddr = virt_to_phys_040(addr))) + break; + if (len <= i) + return 0; + len -= i; + addr += PAGE_SIZE; + } + } + else + paddr += 16; + } + break; + + default: + case FLUSH_SCOPE_PAGE: + len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); + for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) + { + if (!(paddr = virt_to_phys_040(addr))) + continue; + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + } + break; + } + return 0; +} + +#define virt_to_phys_060(vaddr) \ +({ \ + unsigned long paddr; \ + __asm__ __volatile__ (".chip 68060\n\t" \ + "plpar (%0)\n\t" \ + ".chip 68k" \ + : "=a" (paddr) \ + : "0" (vaddr)); \ + (paddr); /* XXX */ \ +}) + +static inline int +cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) +{ + unsigned long paddr, i; + + /* + * 68060 manual says: + * cpush %dc : flush DC, remains valid (with our %cacr setup) + * cpush %ic : invalidate IC + * cpush %bc : flush DC + invalidate IC + */ + switch (scope) + { + case FLUSH_SCOPE_ALL: + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %dc\n\t" + ".chip 68k"); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %ic\n\t" + ".chip 68k"); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %bc\n\t" + ".chip 68k"); + break; + } + break; + + case FLUSH_SCOPE_LINE: + /* Find the physical address of the first mapped page in the + address range. */ + len += addr & 15; + addr &= -16; + if (!(paddr = virt_to_phys_060(addr))) { + unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); + + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + tmp = PAGE_SIZE; + for (;;) + { + if ((paddr = virt_to_phys_060(addr))) + break; + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + } + } + len = (len + 15) >> 4; + i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; + while (len--) + { + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + if (!--i && len) + { + + /* + * We just want to jump to the first cache line + * in the next page. + */ + addr += PAGE_SIZE; + addr &= PAGE_MASK; + + i = PAGE_SIZE / 16; + /* Recompute physical address when crossing a page + boundary. */ + for (;;) + { + if ((paddr = virt_to_phys_060(addr))) + break; + if (len <= i) + return 0; + len -= i; + addr += PAGE_SIZE; + } + } + else + paddr += 16; + } + break; + + default: + case FLUSH_SCOPE_PAGE: + len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); + addr &= PAGE_MASK; /* Workaround for bug in some + revisions of the 68060 */ + for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) + { + if (!(paddr = virt_to_phys_060(addr))) + continue; + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + } + break; + } + return 0; +} + +/* sys_cacheflush -- flush (part of) the processor cache. */ +asmlinkage int +sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) +{ + struct vm_area_struct *vma; + int ret = -EINVAL; + + if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || + cache & ~FLUSH_CACHE_BOTH) + goto out; + + if (scope == FLUSH_SCOPE_ALL) { + /* Only the superuser may explicitly flush the whole cache. */ + ret = -EPERM; + if (!capable(CAP_SYS_ADMIN)) + goto out; + } else { + /* + * Verify that the specified address region actually belongs + * to this process. + */ + vma = find_vma (current->mm, addr); + ret = -EINVAL; + /* Check for overflow. */ + if (addr + len < addr) + goto out; + if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) + goto out; + } + + if (CPU_IS_020_OR_030) { + if (scope == FLUSH_SCOPE_LINE && len < 256) { + unsigned long cacr; + __asm__ ("movec %%cacr, %0" : "=r" (cacr)); + if (cache & FLUSH_CACHE_INSN) + cacr |= 4; + if (cache & FLUSH_CACHE_DATA) + cacr |= 0x400; + len >>= 2; + while (len--) { + __asm__ __volatile__ ("movec %1, %%caar\n\t" + "movec %0, %%cacr" + : /* no outputs */ + : "r" (cacr), "r" (addr)); + addr += 4; + } + } else { + /* Flush the whole cache, even if page granularity requested. */ + unsigned long cacr; + __asm__ ("movec %%cacr, %0" : "=r" (cacr)); + if (cache & FLUSH_CACHE_INSN) + cacr |= 8; + if (cache & FLUSH_CACHE_DATA) + cacr |= 0x800; + __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); + } + ret = 0; + goto out; + } else { + /* + * 040 or 060: don't blindly trust 'scope', someone could + * try to flush a few megs of memory. + */ + + if (len>=3*PAGE_SIZE && scope=10*PAGE_SIZE && scopetp_value; +} + +asmlinkage int sys_set_thread_area(unsigned long tp) +{ + current_thread_info()->tp_value = tp; + return 0; +} + +/* This syscall gets its arguments in A0 (mem), D2 (oldval) and + D1 (newval). */ +asmlinkage int +sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, + unsigned long __user * mem) +{ + /* This was borrowed from ARM's implementation. */ + for (;;) { + struct mm_struct *mm = current->mm; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + spinlock_t *ptl; + unsigned long mem_value; + + down_read(&mm->mmap_sem); + pgd = pgd_offset(mm, (unsigned long)mem); + if (!pgd_present(*pgd)) + goto bad_access; + pmd = pmd_offset(pgd, (unsigned long)mem); + if (!pmd_present(*pmd)) + goto bad_access; + pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); + if (!pte_present(*pte) || !pte_dirty(*pte) + || !pte_write(*pte)) { + pte_unmap_unlock(pte, ptl); + goto bad_access; + } + + mem_value = *mem; + if (mem_value == oldval) + *mem = newval; + + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return mem_value; + + bad_access: + up_read(&mm->mmap_sem); + /* This is not necessarily a bad access, we can get here if + a memory we're trying to write to should be copied-on-write. + Make the kernel do the necessary page stuff, then re-iterate. + Simulate a write access fault to do that. */ + { + /* The first argument of the function corresponds to + D1, which is the first field of struct pt_regs. */ + struct pt_regs *fp = (struct pt_regs *)&newval; + + /* '3' is an RMW flag. */ + if (do_page_fault(fp, (unsigned long)mem, 3)) + /* If the do_page_fault() failed, we don't + have anything meaningful to return. + There should be a SIGSEGV pending for + the process. */ + return 0xdeadbeef; + } + } +} + +asmlinkage int sys_atomic_barrier(void) +{ + /* no code needed for uniprocs */ + return 0; +} diff --git a/trunk/arch/m68knommu/kernel/sys_m68k.c b/trunk/arch/m68k/kernel/sys_m68k_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/sys_m68k.c rename to trunk/arch/m68k/kernel/sys_m68k_no.c diff --git a/trunk/arch/m68knommu/kernel/syscalltable.S b/trunk/arch/m68k/kernel/syscalltable.S similarity index 100% rename from trunk/arch/m68knommu/kernel/syscalltable.S rename to trunk/arch/m68k/kernel/syscalltable.S diff --git a/trunk/arch/m68k/kernel/time.c b/trunk/arch/m68k/kernel/time.c index 18b34ee5db3b..a5cf40c26de5 100644 --- a/trunk/arch/m68k/kernel/time.c +++ b/trunk/arch/m68k/kernel/time.c @@ -1,114 +1,5 @@ -/* - * linux/arch/m68k/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * - * This file contains the m68k-specific time handling details. - * Most of the stuff is located in the machine specific files. - * - * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 - * "A Kernel Model for Precision Timekeeping" by Dave Mills - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -static inline int set_rtc_mmss(unsigned long nowtime) -{ - if (mach_set_clock_mmss) - return mach_set_clock_mmss (nowtime); - return -1; -} - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ -static irqreturn_t timer_interrupt(int irq, void *dummy) -{ - xtime_update(1); - update_process_times(user_mode(get_irq_regs())); - profile_tick(CPU_PROFILING); - -#ifdef CONFIG_HEARTBEAT - /* use power LED as a heartbeat instead -- much more useful - for debugging -- based on the version for PReP by Cort */ - /* acts like an actual heart beat -- ie thump-thump-pause... */ - if (mach_heartbeat) { - static unsigned cnt = 0, period = 0, dist = 0; - - if (cnt == 0 || cnt == dist) - mach_heartbeat( 1 ); - else if (cnt == 7 || cnt == dist+7) - mach_heartbeat( 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<tv_sec = 0; - ts->tv_nsec = 0; - - if (mach_hwclk) { - mach_hwclk(0, &time); - - if ((time.tm_year += 1900) < 1970) - time.tm_year += 100; - ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday, - time.tm_hour, time.tm_min, time.tm_sec); - } -} - -void __init time_init(void) -{ - mach_sched_init(timer_interrupt); -} - -u32 arch_gettimeoffset(void) -{ - return mach_gettimeoffset() * 1000; -} - -static int __init rtc_init(void) -{ - struct platform_device *pdev; - - if (!mach_hwclk) - return -ENODEV; - - pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - return 0; -} - -module_init(rtc_init); +#ifdef CONFIG_MMU +#include "time_mm.c" +#else +#include "time_no.c" +#endif diff --git a/trunk/arch/m68k/kernel/time_mm.c b/trunk/arch/m68k/kernel/time_mm.c new file mode 100644 index 000000000000..18b34ee5db3b --- /dev/null +++ b/trunk/arch/m68k/kernel/time_mm.c @@ -0,0 +1,114 @@ +/* + * linux/arch/m68k/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * + * This file contains the m68k-specific time handling details. + * Most of the stuff is located in the machine specific files. + * + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static inline int set_rtc_mmss(unsigned long nowtime) +{ + if (mach_set_clock_mmss) + return mach_set_clock_mmss (nowtime); + return -1; +} + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "xtime_update()" routine every clocktick + */ +static irqreturn_t timer_interrupt(int irq, void *dummy) +{ + xtime_update(1); + update_process_times(user_mode(get_irq_regs())); + profile_tick(CPU_PROFILING); + +#ifdef CONFIG_HEARTBEAT + /* use power LED as a heartbeat instead -- much more useful + for debugging -- based on the version for PReP by Cort */ + /* acts like an actual heart beat -- ie thump-thump-pause... */ + if (mach_heartbeat) { + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_heartbeat( 1 ); + else if (cnt == 7 || cnt == dist+7) + mach_heartbeat( 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<tv_sec = 0; + ts->tv_nsec = 0; + + if (mach_hwclk) { + mach_hwclk(0, &time); + + if ((time.tm_year += 1900) < 1970) + time.tm_year += 100; + ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday, + time.tm_hour, time.tm_min, time.tm_sec); + } +} + +void __init time_init(void) +{ + mach_sched_init(timer_interrupt); +} + +u32 arch_gettimeoffset(void) +{ + return mach_gettimeoffset() * 1000; +} + +static int __init rtc_init(void) +{ + struct platform_device *pdev; + + if (!mach_hwclk) + return -ENODEV; + + pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return 0; +} + +module_init(rtc_init); diff --git a/trunk/arch/m68knommu/kernel/time.c b/trunk/arch/m68k/kernel/time_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/time.c rename to trunk/arch/m68k/kernel/time_no.c diff --git a/trunk/arch/m68k/kernel/traps.c b/trunk/arch/m68k/kernel/traps.c index 4022bbc28878..c98add3f5f0f 100644 --- a/trunk/arch/m68k/kernel/traps.c +++ b/trunk/arch/m68k/kernel/traps.c @@ -1,1207 +1,5 @@ -/* - * linux/arch/m68k/kernel/traps.c - * - * Copyright (C) 1993, 1994 by Hamish Macdonald - * - * 68040 fixes by Michael Rausch - * 68040 fixes by Martin Apel - * 68040 fixes and writeback by Richard Zidlicky - * 68060 fixes by Roman Hodek - * 68060 fixes by Jesper Skov - * - * 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. - */ - -/* - * Sets up all exception vectors - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* assembler routines */ -asmlinkage void system_call(void); -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void nmihandler(void); -#ifdef CONFIG_M68KFPU_EMU -asmlinkage void fpu_emu(void); -#endif - -e_vector vectors[256]; - -/* nmi handler for the Amiga */ -asm(".text\n" - __ALIGN_STR "\n" - "nmihandler: rte"); - -/* - * this must be called very early as the kernel might - * use some instruction that are emulated on the 060 - * and so we're prepared for early probe attempts (e.g. nf_init). - */ -void __init base_trap_init(void) -{ - if (MACH_IS_SUN3X) { - extern e_vector *sun3x_prom_vbr; - - __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); - } - - /* setup the exception vector table */ - __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); - - if (CPU_IS_060) { - /* set up ISP entry points */ - asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); - - vectors[VEC_UNIMPII] = unimp_vec; - } - - vectors[VEC_BUSERR] = buserr; - vectors[VEC_ILLEGAL] = trap; - vectors[VEC_SYS] = system_call; -} - -void __init trap_init (void) -{ - int i; - - for (i = VEC_SPUR; i <= VEC_INT7; i++) - vectors[i] = bad_inthandler; - - for (i = 0; i < VEC_USER; i++) - if (!vectors[i]) - vectors[i] = trap; - - for (i = VEC_USER; i < 256; i++) - vectors[i] = bad_inthandler; - -#ifdef CONFIG_M68KFPU_EMU - if (FPU_IS_EMU) - vectors[VEC_LINE11] = fpu_emu; -#endif - - if (CPU_IS_040 && !FPU_IS_EMU) { - /* set up FPSP entry points */ - asmlinkage void dz_vec(void) asm ("dz"); - asmlinkage void inex_vec(void) asm ("inex"); - asmlinkage void ovfl_vec(void) asm ("ovfl"); - asmlinkage void unfl_vec(void) asm ("unfl"); - asmlinkage void snan_vec(void) asm ("snan"); - asmlinkage void operr_vec(void) asm ("operr"); - asmlinkage void bsun_vec(void) asm ("bsun"); - asmlinkage void fline_vec(void) asm ("fline"); - asmlinkage void unsupp_vec(void) asm ("unsupp"); - - vectors[VEC_FPDIVZ] = dz_vec; - vectors[VEC_FPIR] = inex_vec; - vectors[VEC_FPOVER] = ovfl_vec; - vectors[VEC_FPUNDER] = unfl_vec; - vectors[VEC_FPNAN] = snan_vec; - vectors[VEC_FPOE] = operr_vec; - vectors[VEC_FPBRUC] = bsun_vec; - vectors[VEC_LINE11] = fline_vec; - vectors[VEC_FPUNSUP] = unsupp_vec; - } - - if (CPU_IS_060 && !FPU_IS_EMU) { - /* set up IFPSP entry points */ - asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); - asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); - asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); - asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); - asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); - asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); - asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); - asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); - asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); - - vectors[VEC_FPNAN] = snan_vec6; - vectors[VEC_FPOE] = operr_vec6; - vectors[VEC_FPOVER] = ovfl_vec6; - vectors[VEC_FPUNDER] = unfl_vec6; - vectors[VEC_FPDIVZ] = dz_vec6; - vectors[VEC_FPIR] = inex_vec6; - vectors[VEC_LINE11] = fline_vec6; - vectors[VEC_FPUNSUP] = unsupp_vec6; - vectors[VEC_UNIMPEA] = effadd_vec6; - } - - /* if running on an amiga, make the NMI interrupt do nothing */ - if (MACH_IS_AMIGA) { - vectors[VEC_INT7] = nmihandler; - } -} - - -static const char *vec_names[] = { - [VEC_RESETSP] = "RESET SP", - [VEC_RESETPC] = "RESET PC", - [VEC_BUSERR] = "BUS ERROR", - [VEC_ADDRERR] = "ADDRESS ERROR", - [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION", - [VEC_ZERODIV] = "ZERO DIVIDE", - [VEC_CHK] = "CHK", - [VEC_TRAP] = "TRAPcc", - [VEC_PRIV] = "PRIVILEGE VIOLATION", - [VEC_TRACE] = "TRACE", - [VEC_LINE10] = "LINE 1010", - [VEC_LINE11] = "LINE 1111", - [VEC_RESV12] = "UNASSIGNED RESERVED 12", - [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION", - [VEC_FORMAT] = "FORMAT ERROR", - [VEC_UNINT] = "UNINITIALIZED INTERRUPT", - [VEC_RESV16] = "UNASSIGNED RESERVED 16", - [VEC_RESV17] = "UNASSIGNED RESERVED 17", - [VEC_RESV18] = "UNASSIGNED RESERVED 18", - [VEC_RESV19] = "UNASSIGNED RESERVED 19", - [VEC_RESV20] = "UNASSIGNED RESERVED 20", - [VEC_RESV21] = "UNASSIGNED RESERVED 21", - [VEC_RESV22] = "UNASSIGNED RESERVED 22", - [VEC_RESV23] = "UNASSIGNED RESERVED 23", - [VEC_SPUR] = "SPURIOUS INTERRUPT", - [VEC_INT1] = "LEVEL 1 INT", - [VEC_INT2] = "LEVEL 2 INT", - [VEC_INT3] = "LEVEL 3 INT", - [VEC_INT4] = "LEVEL 4 INT", - [VEC_INT5] = "LEVEL 5 INT", - [VEC_INT6] = "LEVEL 6 INT", - [VEC_INT7] = "LEVEL 7 INT", - [VEC_SYS] = "SYSCALL", - [VEC_TRAP1] = "TRAP #1", - [VEC_TRAP2] = "TRAP #2", - [VEC_TRAP3] = "TRAP #3", - [VEC_TRAP4] = "TRAP #4", - [VEC_TRAP5] = "TRAP #5", - [VEC_TRAP6] = "TRAP #6", - [VEC_TRAP7] = "TRAP #7", - [VEC_TRAP8] = "TRAP #8", - [VEC_TRAP9] = "TRAP #9", - [VEC_TRAP10] = "TRAP #10", - [VEC_TRAP11] = "TRAP #11", - [VEC_TRAP12] = "TRAP #12", - [VEC_TRAP13] = "TRAP #13", - [VEC_TRAP14] = "TRAP #14", - [VEC_TRAP15] = "TRAP #15", - [VEC_FPBRUC] = "FPCP BSUN", - [VEC_FPIR] = "FPCP INEXACT", - [VEC_FPDIVZ] = "FPCP DIV BY 0", - [VEC_FPUNDER] = "FPCP UNDERFLOW", - [VEC_FPOE] = "FPCP OPERAND ERROR", - [VEC_FPOVER] = "FPCP OVERFLOW", - [VEC_FPNAN] = "FPCP SNAN", - [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION", - [VEC_MMUCFG] = "MMU CONFIGURATION ERROR", - [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR", - [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR", - [VEC_RESV59] = "UNASSIGNED RESERVED 59", - [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60", - [VEC_UNIMPII] = "UNASSIGNED RESERVED 61", - [VEC_RESV62] = "UNASSIGNED RESERVED 62", - [VEC_RESV63] = "UNASSIGNED RESERVED 63", -}; - -static const char *space_names[] = { - [0] = "Space 0", - [USER_DATA] = "User Data", - [USER_PROGRAM] = "User Program", -#ifndef CONFIG_SUN3 - [3] = "Space 3", +#ifdef CONFIG_MMU +#include "traps_mm.c" #else - [FC_CONTROL] = "Control", -#endif - [4] = "Space 4", - [SUPER_DATA] = "Super Data", - [SUPER_PROGRAM] = "Super Program", - [CPU_SPACE] = "CPU" -}; - -void die_if_kernel(char *,struct pt_regs *,int); -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); -int send_fault_sig(struct pt_regs *regs); - -asmlinkage void trap_c(struct frame *fp); - -#if defined (CONFIG_M68060) -static inline void access_error060 (struct frame *fp) -{ - unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ - -#ifdef DEBUG - printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); -#endif - - if (fslw & MMU060_BPE) { - /* branch prediction error -> clear branch cache */ - __asm__ __volatile__ ("movec %/cacr,%/d0\n\t" - "orl #0x00400000,%/d0\n\t" - "movec %/d0,%/cacr" - : : : "d0" ); - /* return if there's no other error */ - if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) - return; - } - - if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { - unsigned long errorcode; - unsigned long addr = fp->un.fmt4.effaddr; - - if (fslw & MMU060_MA) - addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; - - errorcode = 1; - if (fslw & MMU060_DESC_ERR) { - __flush_tlb040_one(addr); - errorcode = 0; - } - if (fslw & MMU060_W) - errorcode |= 2; -#ifdef DEBUG - printk("errorcode = %d\n", errorcode ); -#endif - do_page_fault(&fp->ptregs, addr, errorcode); - } else if (fslw & (MMU060_SEE)){ - /* Software Emulation Error. - * fault during mem_read/mem_write in ifpsp060/os.S - */ - send_fault_sig(&fp->ptregs); - } else if (!(fslw & (MMU060_RE|MMU060_WE)) || - send_fault_sig(&fp->ptregs) > 0) { - printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); - printk( "68060 access error, fslw=%lx\n", fslw ); - trap_c( fp ); - } -} -#endif /* CONFIG_M68060 */ - -#if defined (CONFIG_M68040) -static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) -{ - unsigned long mmusr; - mm_segment_t old_fs = get_fs(); - - set_fs(MAKE_MM_SEG(wbs)); - - if (iswrite) - asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); - else - asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); - - asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); - - set_fs(old_fs); - - return mmusr; -} - -static inline int do_040writeback1(unsigned short wbs, unsigned long wba, - unsigned long wbd) -{ - int res = 0; - mm_segment_t old_fs = get_fs(); - - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(MAKE_MM_SEG(wbs)); - - switch (wbs & WBSIZ_040) { - case BA_SIZE_BYTE: - res = put_user(wbd & 0xff, (char __user *)wba); - break; - case BA_SIZE_WORD: - res = put_user(wbd & 0xffff, (short __user *)wba); - break; - case BA_SIZE_LONG: - res = put_user(wbd, (int __user *)wba); - break; - } - - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(old_fs); - - -#ifdef DEBUG - printk("do_040writeback1, res=%d\n",res); -#endif - - return res; -} - -/* after an exception in a writeback the stack frame corresponding - * to that exception is discarded, set a few bits in the old frame - * to simulate what it should look like - */ -static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs) -{ - fp->un.fmt7.faddr = wba; - fp->un.fmt7.ssw = wbs & 0xff; - if (wba != current->thread.faddr) - fp->un.fmt7.ssw |= MA_040; -} - -static inline void do_040writebacks(struct frame *fp) -{ - int res = 0; -#if 0 - if (fp->un.fmt7.wb1s & WBV_040) - printk("access_error040: cannot handle 1st writeback. oops.\n"); -#endif - - if ((fp->un.fmt7.wb2s & WBV_040) && - !(fp->un.fmt7.wb2s & WBTT_040)) { - res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, - fp->un.fmt7.wb2d); - if (res) - fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); - else - fp->un.fmt7.wb2s = 0; - } - - /* do the 2nd wb only if the first one was successful (except for a kernel wb) */ - if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { - res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, - fp->un.fmt7.wb3d); - if (res) - { - fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); - - fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; - fp->un.fmt7.wb3s &= (~WBV_040); - fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; - fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; - } - else - fp->un.fmt7.wb3s = 0; - } - - if (res) - send_fault_sig(&fp->ptregs); -} - -/* - * called from sigreturn(), must ensure userspace code didn't - * manipulate exception frame to circumvent protection, then complete - * pending writebacks - * we just clear TM2 to turn it into a userspace access - */ -asmlinkage void berr_040cleanup(struct frame *fp) -{ - fp->un.fmt7.wb2s &= ~4; - fp->un.fmt7.wb3s &= ~4; - - do_040writebacks(fp); -} - -static inline void access_error040(struct frame *fp) -{ - unsigned short ssw = fp->un.fmt7.ssw; - unsigned long mmusr; - -#ifdef DEBUG - printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); - printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, - fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); - printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", - fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, - fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); -#endif - - if (ssw & ATC_040) { - unsigned long addr = fp->un.fmt7.faddr; - unsigned long errorcode; - - /* - * The MMU status has to be determined AFTER the address - * has been corrected if there was a misaligned access (MA). - */ - if (ssw & MA_040) - addr = (addr + 7) & -8; - - /* MMU error, get the MMUSR info for this access */ - mmusr = probe040(!(ssw & RW_040), addr, ssw); -#ifdef DEBUG - printk("mmusr = %lx\n", mmusr); -#endif - errorcode = 1; - if (!(mmusr & MMU_R_040)) { - /* clear the invalid atc entry */ - __flush_tlb040_one(addr); - errorcode = 0; - } - - /* despite what documentation seems to say, RMW - * accesses have always both the LK and RW bits set */ - if (!(ssw & RW_040) || (ssw & LK_040)) - errorcode |= 2; - - if (do_page_fault(&fp->ptregs, addr, errorcode)) { -#ifdef DEBUG - printk("do_page_fault() !=0\n"); -#endif - if (user_mode(&fp->ptregs)){ - /* delay writebacks after signal delivery */ -#ifdef DEBUG - printk(".. was usermode - return\n"); -#endif - return; - } - /* disable writeback into user space from kernel - * (if do_page_fault didn't fix the mapping, - * the writeback won't do good) - */ -disable_wb: -#ifdef DEBUG - printk(".. disabling wb2\n"); -#endif - if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) - fp->un.fmt7.wb2s &= ~WBV_040; - if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) - fp->un.fmt7.wb3s &= ~WBV_040; - } - } else { - /* In case of a bus error we either kill the process or expect - * the kernel to catch the fault, which then is also responsible - * for cleaning up the mess. - */ - current->thread.signo = SIGBUS; - current->thread.faddr = fp->un.fmt7.faddr; - if (send_fault_sig(&fp->ptregs) >= 0) - printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, - fp->un.fmt7.faddr); - goto disable_wb; - } - - do_040writebacks(fp); -} -#endif /* CONFIG_M68040 */ - -#if defined(CONFIG_SUN3) -#include - -extern int mmu_emu_handle_fault (unsigned long, int, int); - -/* sun3 version of bus_error030 */ - -static inline void bus_error030 (struct frame *fp) -{ - unsigned char buserr_type = sun3_get_buserr (); - unsigned long addr, errorcode; - unsigned short ssw = fp->un.fmtb.ssw; - extern unsigned long _sun3_map_test_start, _sun3_map_test_end; - -#ifdef DEBUG - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - ssw & FC ? - fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 - : - fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); -#endif - - /* - * Check if this page should be demand-mapped. This needs to go before - * the testing for a bad kernel-space access (demand-mapping applies - * to kernel accesses too). - */ - - if ((ssw & DF) - && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) { - if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0)) - return; - } - - /* Check for kernel-space pagefault (BAD). */ - if (fp->ptregs.sr & PS_S) { - /* kernel fault must be a data fault to user space */ - if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { - // try checking the kernel mappings before surrender - if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1)) - return; - /* instruction fault or kernel data fault! */ - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - fp->ptregs.pc); - if (ssw & DF) { - /* was this fault incurred testing bus mappings? */ - if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && - (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { - send_fault_sig(&fp->ptregs); - return; - } - - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); - } - printk ("BAD KERNEL BUSERR\n"); - - die_if_kernel("Oops", &fp->ptregs,0); - force_sig(SIGKILL, current); - return; - } - } else { - /* user fault */ - if (!(ssw & (FC | FB)) && !(ssw & DF)) - /* not an instruction fault or data fault! BAD */ - panic ("USER BUSERR w/o instruction or data fault"); - } - - - /* First handle the data fault, if any. */ - if (ssw & DF) { - addr = fp->un.fmtb.daddr; - -// errorcode bit 0: 0 -> no page 1 -> protection fault -// errorcode bit 1: 0 -> read fault 1 -> write fault - -// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault -// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault - - if (buserr_type & SUN3_BUSERR_PROTERR) - errorcode = 0x01; - else if (buserr_type & SUN3_BUSERR_INVALID) - errorcode = 0x00; - else { -#ifdef DEBUG - printk ("*** unexpected busfault type=%#04x\n", buserr_type); - printk ("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc); -#endif - die_if_kernel ("Oops", &fp->ptregs, buserr_type); - force_sig (SIGBUS, current); - return; - } - -//todo: wtf is RM bit? --m - if (!(ssw & RW) || ssw & RM) - errorcode |= 0x02; - - /* Handle page fault. */ - do_page_fault (&fp->ptregs, addr, errorcode); - - /* Retry the data fault now. */ - return; - } - - /* Now handle the instruction fault. */ - - /* Get the fault address. */ - if (fp->ptregs.format == 0xA) - addr = fp->ptregs.pc + 4; - else - addr = fp->un.fmtb.baddr; - if (ssw & FC) - addr -= 2; - - if (buserr_type & SUN3_BUSERR_INVALID) { - if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) - do_page_fault (&fp->ptregs, addr, 0); - } else { -#ifdef DEBUG - printk ("protection fault on insn access (segv).\n"); -#endif - force_sig (SIGSEGV, current); - } -} -#else -#if defined(CPU_M68020_OR_M68030) -static inline void bus_error030 (struct frame *fp) -{ - volatile unsigned short temp; - unsigned short mmusr; - unsigned long addr, errorcode; - unsigned short ssw = fp->un.fmtb.ssw; -#ifdef DEBUG - unsigned long desc; - - printk ("pid = %x ", current->pid); - printk ("SSW=%#06x ", ssw); - - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - ssw & FC ? - fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 - : - fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); -#endif - - /* ++andreas: If a data fault and an instruction fault happen - at the same time map in both pages. */ - - /* First handle the data fault, if any. */ - if (ssw & DF) { - addr = fp->un.fmtb.daddr; - -#ifdef DEBUG - asm volatile ("ptestr %3,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr), "d" (ssw)); -#else - asm volatile ("ptestr %2,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr), "d" (ssw)); -#endif - mmusr = temp; - -#ifdef DEBUG - printk("mmusr is %#x for addr %#lx in task %p\n", - mmusr, addr, current); - printk("descriptor address is %#lx, contents %#lx\n", - __va(desc), *(unsigned long *)__va(desc)); -#endif - - errorcode = (mmusr & MMU_I) ? 0 : 1; - if (!(ssw & RW) || (ssw & RM)) - errorcode |= 2; - - if (mmusr & (MMU_I | MMU_WP)) { - if (ssw & 4) { - printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); - goto buserr; - } - /* Don't try to do anything further if an exception was - handled. */ - if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) - return; - } else if (!(mmusr & MMU_I)) { - /* probably a 020 cas fault */ - if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) - printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); - } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { - printk("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc); - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } else { -#if 0 - static volatile long tlong; -#endif - - printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc, ssw); - asm volatile ("ptestr #1,%1@,#0\n\t" - "pmove %%psr,%0@" - : /* no outputs */ - : "a" (&temp), "a" (addr)); - mmusr = temp; - - printk ("level 0 mmusr is %#x\n", mmusr); -#if 0 - asm volatile ("pmove %%tt0,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk("tt0 is %#lx, ", tlong); - asm volatile ("pmove %%tt1,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk("tt1 is %#lx\n", tlong); -#endif -#ifdef DEBUG - printk("Unknown SIGSEGV - 1\n"); -#endif - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } - - /* setup an ATC entry for the access about to be retried */ - if (!(ssw & RW) || (ssw & RM)) - asm volatile ("ploadw %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - else - asm volatile ("ploadr %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - } - - /* Now handle the instruction fault. */ - - if (!(ssw & (FC|FB))) - return; - - if (fp->ptregs.sr & PS_S) { - printk("Instruction fault at %#010lx\n", - fp->ptregs.pc); - buserr: - printk ("BAD KERNEL BUSERR\n"); - die_if_kernel("Oops",&fp->ptregs,0); - force_sig(SIGKILL, current); - return; - } - - /* get the fault address */ - if (fp->ptregs.format == 10) - addr = fp->ptregs.pc + 4; - else - addr = fp->un.fmtb.baddr; - if (ssw & FC) - addr -= 2; - - if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0) - /* Insn fault on same page as data fault. But we - should still create the ATC entry. */ - goto create_atc_entry; - -#ifdef DEBUG - asm volatile ("ptestr #1,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr)); -#else - asm volatile ("ptestr #1,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr)); -#endif - mmusr = temp; - -#ifdef DEBUG - printk ("mmusr is %#x for addr %#lx in task %p\n", - mmusr, addr, current); - printk ("descriptor address is %#lx, contents %#lx\n", - __va(desc), *(unsigned long *)__va(desc)); -#endif - - if (mmusr & MMU_I) - do_page_fault (&fp->ptregs, addr, 0); - else if (mmusr & (MMU_B|MMU_L|MMU_S)) { - printk ("invalid insn access at %#lx from pc %#lx\n", - addr, fp->ptregs.pc); -#ifdef DEBUG - printk("Unknown SIGSEGV - 2\n"); -#endif - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } - -create_atc_entry: - /* setup an ATC entry for the access about to be retried */ - asm volatile ("ploadr #2,%0@" : /* no outputs */ - : "a" (addr)); -} -#endif /* CPU_M68020_OR_M68030 */ -#endif /* !CONFIG_SUN3 */ - -asmlinkage void buserr_c(struct frame *fp) -{ - /* Only set esp0 if coming from user mode */ - if (user_mode(&fp->ptregs)) - current->thread.esp0 = (unsigned long) fp; - -#ifdef DEBUG - printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); -#endif - - switch (fp->ptregs.format) { -#if defined (CONFIG_M68060) - case 4: /* 68060 access error */ - access_error060 (fp); - break; -#endif -#if defined (CONFIG_M68040) - case 0x7: /* 68040 access error */ - access_error040 (fp); - break; -#endif -#if defined (CPU_M68020_OR_M68030) - case 0xa: - case 0xb: - bus_error030 (fp); - break; -#endif - default: - die_if_kernel("bad frame format",&fp->ptregs,0); -#ifdef DEBUG - printk("Unknown SIGSEGV - 4\n"); -#endif - force_sig(SIGSEGV, current); - } -} - - -static int kstack_depth_to_print = 48; - -void show_trace(unsigned long *stack) -{ - unsigned long *endstack; - unsigned long addr; - int i; - - printk("Call Trace:"); - addr = (unsigned long)stack + THREAD_SIZE - 1; - endstack = (unsigned long *)(addr & -THREAD_SIZE); - i = 0; - while (stack + 1 <= endstack) { - addr = *stack++; - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ - if (__kernel_text_address(addr)) { -#ifndef CONFIG_KALLSYMS - if (i % 5 == 0) - printk("\n "); -#endif - printk(" [<%08lx>] %pS\n", addr, (void *)addr); - i++; - } - } - printk("\n"); -} - -void show_registers(struct pt_regs *regs) -{ - struct frame *fp = (struct frame *)regs; - mm_segment_t old_fs = get_fs(); - u16 c, *cp; - unsigned long addr; - int i; - - print_modules(); - printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); - printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); - printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - regs->d0, regs->d1, regs->d2, regs->d3); - printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - regs->d4, regs->d5, regs->a0, regs->a1); - - printk("Process %s (pid: %d, task=%p)\n", - current->comm, task_pid_nr(current), current); - addr = (unsigned long)&fp->un; - printk("Frame format=%X ", regs->format); - switch (regs->format) { - case 0x2: - printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); - addr += sizeof(fp->un.fmt2); - break; - case 0x3: - printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); - addr += sizeof(fp->un.fmt3); - break; - case 0x4: - printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" - : "eff addr=%08lx pc=%08lx\n"), - fp->un.fmt4.effaddr, fp->un.fmt4.pc); - addr += sizeof(fp->un.fmt4); - break; - case 0x7: - printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", - fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); - printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); - printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); - printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); - printk("push data: %08lx %08lx %08lx %08lx\n", - fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, - fp->un.fmt7.pd3); - addr += sizeof(fp->un.fmt7); - break; - case 0x9: - printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); - addr += sizeof(fp->un.fmt9); - break; - case 0xa: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, - fp->un.fmta.daddr, fp->un.fmta.dobuf); - addr += sizeof(fp->un.fmta); - break; - case 0xb: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, - fp->un.fmtb.daddr, fp->un.fmtb.dobuf); - printk("baddr=%08lx dibuf=%08lx ver=%x\n", - fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); - addr += sizeof(fp->un.fmtb); - break; - default: - printk("\n"); - } - show_stack(NULL, (unsigned long *)addr); - - printk("Code:"); - set_fs(KERNEL_DS); - cp = (u16 *)regs->pc; - for (i = -8; i < 16; i++) { - if (get_user(c, cp + i) && i >= 0) { - printk(" Bad PC value."); - break; - } - printk(i ? " %04x" : " <%04x>", c); - } - set_fs(old_fs); - printk ("\n"); -} - -void show_stack(struct task_struct *task, unsigned long *stack) -{ - unsigned long *p; - unsigned long *endstack; - int i; - - if (!stack) { - if (task) - stack = (unsigned long *)task->thread.esp0; - else - stack = (unsigned long *)&stack; - } - endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); - - printk("Stack from %08lx:", (unsigned long)stack); - p = stack; - for (i = 0; i < kstack_depth_to_print; i++) { - if (p + 1 > endstack) - break; - if (i % 8 == 0) - printk("\n "); - printk(" %08lx", *p++); - } - printk("\n"); - show_trace(stack); -} - -/* - * The architecture-independent backtrace generator - */ -void dump_stack(void) -{ - unsigned long stack; - - show_trace(&stack); -} - -EXPORT_SYMBOL(dump_stack); - -void bad_super_trap (struct frame *fp) -{ - console_verbose(); - if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names)) - printk ("*** %s *** FORMAT=%X\n", - vec_names[(fp->ptregs.vector) >> 2], - fp->ptregs.format); - else - printk ("*** Exception %d *** FORMAT=%X\n", - (fp->ptregs.vector) >> 2, - fp->ptregs.format); - if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) { - unsigned short ssw = fp->un.fmtb.ssw; - - printk ("SSW=%#06x ", ssw); - - if (ssw & RC) - printk ("Pipe stage C instruction fault at %#010lx\n", - (fp->ptregs.format) == 0xA ? - fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); - if (ssw & RB) - printk ("Pipe stage B instruction fault at %#010lx\n", - (fp->ptregs.format) == 0xA ? - fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, space_names[ssw & DFC], - fp->ptregs.pc); - } - printk ("Current process id is %d\n", task_pid_nr(current)); - die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); -} - -asmlinkage void trap_c(struct frame *fp) -{ - int sig; - siginfo_t info; - - if (fp->ptregs.sr & PS_S) { - if (fp->ptregs.vector == VEC_TRACE << 2) { - /* traced a trapping instruction on a 68020/30, - * real exception will be executed afterwards. - */ - } else if (!handle_kernel_fault(&fp->ptregs)) - bad_super_trap(fp); - return; - } - - /* send the appropriate signal to the user program */ - switch ((fp->ptregs.vector) >> 2) { - case VEC_ADDRERR: - info.si_code = BUS_ADRALN; - sig = SIGBUS; - break; - case VEC_ILLEGAL: - case VEC_LINE10: - case VEC_LINE11: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - case VEC_PRIV: - info.si_code = ILL_PRVOPC; - sig = SIGILL; - break; - case VEC_COPROC: - info.si_code = ILL_COPROC; - sig = SIGILL; - break; - case VEC_TRAP1: - case VEC_TRAP2: - case VEC_TRAP3: - case VEC_TRAP4: - case VEC_TRAP5: - case VEC_TRAP6: - case VEC_TRAP7: - case VEC_TRAP8: - case VEC_TRAP9: - case VEC_TRAP10: - case VEC_TRAP11: - case VEC_TRAP12: - case VEC_TRAP13: - case VEC_TRAP14: - info.si_code = ILL_ILLTRP; - sig = SIGILL; - break; - case VEC_FPBRUC: - case VEC_FPOE: - case VEC_FPNAN: - info.si_code = FPE_FLTINV; - sig = SIGFPE; - break; - case VEC_FPIR: - info.si_code = FPE_FLTRES; - sig = SIGFPE; - break; - case VEC_FPDIVZ: - info.si_code = FPE_FLTDIV; - sig = SIGFPE; - break; - case VEC_FPUNDER: - info.si_code = FPE_FLTUND; - sig = SIGFPE; - break; - case VEC_FPOVER: - info.si_code = FPE_FLTOVF; - sig = SIGFPE; - break; - case VEC_ZERODIV: - info.si_code = FPE_INTDIV; - sig = SIGFPE; - break; - case VEC_CHK: - case VEC_TRAP: - info.si_code = FPE_INTOVF; - sig = SIGFPE; - break; - case VEC_TRACE: /* ptrace single step */ - info.si_code = TRAP_TRACE; - sig = SIGTRAP; - break; - case VEC_TRAP15: /* breakpoint */ - info.si_code = TRAP_BRKPT; - sig = SIGTRAP; - break; - default: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - } - info.si_signo = sig; - info.si_errno = 0; - switch (fp->ptregs.format) { - default: - info.si_addr = (void *) fp->ptregs.pc; - break; - case 2: - info.si_addr = (void *) fp->un.fmt2.iaddr; - break; - case 7: - info.si_addr = (void *) fp->un.fmt7.effaddr; - break; - case 9: - info.si_addr = (void *) fp->un.fmt9.iaddr; - break; - case 10: - info.si_addr = (void *) fp->un.fmta.daddr; - break; - case 11: - info.si_addr = (void *) fp->un.fmtb.daddr; - break; - } - force_sig_info (sig, &info, current); -} - -void die_if_kernel (char *str, struct pt_regs *fp, int nr) -{ - if (!(fp->sr & PS_S)) - return; - - console_verbose(); - printk("%s: %08x\n",str,nr); - show_registers(fp); - add_taint(TAINT_DIE); - do_exit(SIGSEGV); -} - -/* - * This function is called if an error occur while accessing - * user-space from the fpsp040 code. - */ -asmlinkage void fpsp040_die(void) -{ - do_exit(SIGSEGV); -} - -#ifdef CONFIG_M68KFPU_EMU -asmlinkage void fpemu_signal(int signal, int code, void *addr) -{ - siginfo_t info; - - info.si_signo = signal; - info.si_errno = 0; - info.si_code = code; - info.si_addr = addr; - force_sig_info(signal, &info, current); -} +#include "traps_no.c" #endif diff --git a/trunk/arch/m68k/kernel/traps_mm.c b/trunk/arch/m68k/kernel/traps_mm.c new file mode 100644 index 000000000000..4022bbc28878 --- /dev/null +++ b/trunk/arch/m68k/kernel/traps_mm.c @@ -0,0 +1,1207 @@ +/* + * linux/arch/m68k/kernel/traps.c + * + * Copyright (C) 1993, 1994 by Hamish Macdonald + * + * 68040 fixes by Michael Rausch + * 68040 fixes by Martin Apel + * 68040 fixes and writeback by Richard Zidlicky + * 68060 fixes by Roman Hodek + * 68060 fixes by Jesper Skov + * + * 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. + */ + +/* + * Sets up all exception vectors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* assembler routines */ +asmlinkage void system_call(void); +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void nmihandler(void); +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpu_emu(void); +#endif + +e_vector vectors[256]; + +/* nmi handler for the Amiga */ +asm(".text\n" + __ALIGN_STR "\n" + "nmihandler: rte"); + +/* + * this must be called very early as the kernel might + * use some instruction that are emulated on the 060 + * and so we're prepared for early probe attempts (e.g. nf_init). + */ +void __init base_trap_init(void) +{ + if (MACH_IS_SUN3X) { + extern e_vector *sun3x_prom_vbr; + + __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); + } + + /* setup the exception vector table */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + + if (CPU_IS_060) { + /* set up ISP entry points */ + asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); + + vectors[VEC_UNIMPII] = unimp_vec; + } + + vectors[VEC_BUSERR] = buserr; + vectors[VEC_ILLEGAL] = trap; + vectors[VEC_SYS] = system_call; +} + +void __init trap_init (void) +{ + int i; + + for (i = VEC_SPUR; i <= VEC_INT7; i++) + vectors[i] = bad_inthandler; + + for (i = 0; i < VEC_USER; i++) + if (!vectors[i]) + vectors[i] = trap; + + for (i = VEC_USER; i < 256; i++) + vectors[i] = bad_inthandler; + +#ifdef CONFIG_M68KFPU_EMU + if (FPU_IS_EMU) + vectors[VEC_LINE11] = fpu_emu; +#endif + + if (CPU_IS_040 && !FPU_IS_EMU) { + /* set up FPSP entry points */ + asmlinkage void dz_vec(void) asm ("dz"); + asmlinkage void inex_vec(void) asm ("inex"); + asmlinkage void ovfl_vec(void) asm ("ovfl"); + asmlinkage void unfl_vec(void) asm ("unfl"); + asmlinkage void snan_vec(void) asm ("snan"); + asmlinkage void operr_vec(void) asm ("operr"); + asmlinkage void bsun_vec(void) asm ("bsun"); + asmlinkage void fline_vec(void) asm ("fline"); + asmlinkage void unsupp_vec(void) asm ("unsupp"); + + vectors[VEC_FPDIVZ] = dz_vec; + vectors[VEC_FPIR] = inex_vec; + vectors[VEC_FPOVER] = ovfl_vec; + vectors[VEC_FPUNDER] = unfl_vec; + vectors[VEC_FPNAN] = snan_vec; + vectors[VEC_FPOE] = operr_vec; + vectors[VEC_FPBRUC] = bsun_vec; + vectors[VEC_LINE11] = fline_vec; + vectors[VEC_FPUNSUP] = unsupp_vec; + } + + if (CPU_IS_060 && !FPU_IS_EMU) { + /* set up IFPSP entry points */ + asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); + asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); + asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); + asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); + asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); + asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); + asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); + asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); + asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); + + vectors[VEC_FPNAN] = snan_vec6; + vectors[VEC_FPOE] = operr_vec6; + vectors[VEC_FPOVER] = ovfl_vec6; + vectors[VEC_FPUNDER] = unfl_vec6; + vectors[VEC_FPDIVZ] = dz_vec6; + vectors[VEC_FPIR] = inex_vec6; + vectors[VEC_LINE11] = fline_vec6; + vectors[VEC_FPUNSUP] = unsupp_vec6; + vectors[VEC_UNIMPEA] = effadd_vec6; + } + + /* if running on an amiga, make the NMI interrupt do nothing */ + if (MACH_IS_AMIGA) { + vectors[VEC_INT7] = nmihandler; + } +} + + +static const char *vec_names[] = { + [VEC_RESETSP] = "RESET SP", + [VEC_RESETPC] = "RESET PC", + [VEC_BUSERR] = "BUS ERROR", + [VEC_ADDRERR] = "ADDRESS ERROR", + [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION", + [VEC_ZERODIV] = "ZERO DIVIDE", + [VEC_CHK] = "CHK", + [VEC_TRAP] = "TRAPcc", + [VEC_PRIV] = "PRIVILEGE VIOLATION", + [VEC_TRACE] = "TRACE", + [VEC_LINE10] = "LINE 1010", + [VEC_LINE11] = "LINE 1111", + [VEC_RESV12] = "UNASSIGNED RESERVED 12", + [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION", + [VEC_FORMAT] = "FORMAT ERROR", + [VEC_UNINT] = "UNINITIALIZED INTERRUPT", + [VEC_RESV16] = "UNASSIGNED RESERVED 16", + [VEC_RESV17] = "UNASSIGNED RESERVED 17", + [VEC_RESV18] = "UNASSIGNED RESERVED 18", + [VEC_RESV19] = "UNASSIGNED RESERVED 19", + [VEC_RESV20] = "UNASSIGNED RESERVED 20", + [VEC_RESV21] = "UNASSIGNED RESERVED 21", + [VEC_RESV22] = "UNASSIGNED RESERVED 22", + [VEC_RESV23] = "UNASSIGNED RESERVED 23", + [VEC_SPUR] = "SPURIOUS INTERRUPT", + [VEC_INT1] = "LEVEL 1 INT", + [VEC_INT2] = "LEVEL 2 INT", + [VEC_INT3] = "LEVEL 3 INT", + [VEC_INT4] = "LEVEL 4 INT", + [VEC_INT5] = "LEVEL 5 INT", + [VEC_INT6] = "LEVEL 6 INT", + [VEC_INT7] = "LEVEL 7 INT", + [VEC_SYS] = "SYSCALL", + [VEC_TRAP1] = "TRAP #1", + [VEC_TRAP2] = "TRAP #2", + [VEC_TRAP3] = "TRAP #3", + [VEC_TRAP4] = "TRAP #4", + [VEC_TRAP5] = "TRAP #5", + [VEC_TRAP6] = "TRAP #6", + [VEC_TRAP7] = "TRAP #7", + [VEC_TRAP8] = "TRAP #8", + [VEC_TRAP9] = "TRAP #9", + [VEC_TRAP10] = "TRAP #10", + [VEC_TRAP11] = "TRAP #11", + [VEC_TRAP12] = "TRAP #12", + [VEC_TRAP13] = "TRAP #13", + [VEC_TRAP14] = "TRAP #14", + [VEC_TRAP15] = "TRAP #15", + [VEC_FPBRUC] = "FPCP BSUN", + [VEC_FPIR] = "FPCP INEXACT", + [VEC_FPDIVZ] = "FPCP DIV BY 0", + [VEC_FPUNDER] = "FPCP UNDERFLOW", + [VEC_FPOE] = "FPCP OPERAND ERROR", + [VEC_FPOVER] = "FPCP OVERFLOW", + [VEC_FPNAN] = "FPCP SNAN", + [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION", + [VEC_MMUCFG] = "MMU CONFIGURATION ERROR", + [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR", + [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR", + [VEC_RESV59] = "UNASSIGNED RESERVED 59", + [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60", + [VEC_UNIMPII] = "UNASSIGNED RESERVED 61", + [VEC_RESV62] = "UNASSIGNED RESERVED 62", + [VEC_RESV63] = "UNASSIGNED RESERVED 63", +}; + +static const char *space_names[] = { + [0] = "Space 0", + [USER_DATA] = "User Data", + [USER_PROGRAM] = "User Program", +#ifndef CONFIG_SUN3 + [3] = "Space 3", +#else + [FC_CONTROL] = "Control", +#endif + [4] = "Space 4", + [SUPER_DATA] = "Super Data", + [SUPER_PROGRAM] = "Super Program", + [CPU_SPACE] = "CPU" +}; + +void die_if_kernel(char *,struct pt_regs *,int); +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code); +int send_fault_sig(struct pt_regs *regs); + +asmlinkage void trap_c(struct frame *fp); + +#if defined (CONFIG_M68060) +static inline void access_error060 (struct frame *fp) +{ + unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ + +#ifdef DEBUG + printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); +#endif + + if (fslw & MMU060_BPE) { + /* branch prediction error -> clear branch cache */ + __asm__ __volatile__ ("movec %/cacr,%/d0\n\t" + "orl #0x00400000,%/d0\n\t" + "movec %/d0,%/cacr" + : : : "d0" ); + /* return if there's no other error */ + if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) + return; + } + + if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { + unsigned long errorcode; + unsigned long addr = fp->un.fmt4.effaddr; + + if (fslw & MMU060_MA) + addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; + + errorcode = 1; + if (fslw & MMU060_DESC_ERR) { + __flush_tlb040_one(addr); + errorcode = 0; + } + if (fslw & MMU060_W) + errorcode |= 2; +#ifdef DEBUG + printk("errorcode = %d\n", errorcode ); +#endif + do_page_fault(&fp->ptregs, addr, errorcode); + } else if (fslw & (MMU060_SEE)){ + /* Software Emulation Error. + * fault during mem_read/mem_write in ifpsp060/os.S + */ + send_fault_sig(&fp->ptregs); + } else if (!(fslw & (MMU060_RE|MMU060_WE)) || + send_fault_sig(&fp->ptregs) > 0) { + printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); + printk( "68060 access error, fslw=%lx\n", fslw ); + trap_c( fp ); + } +} +#endif /* CONFIG_M68060 */ + +#if defined (CONFIG_M68040) +static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) +{ + unsigned long mmusr; + mm_segment_t old_fs = get_fs(); + + set_fs(MAKE_MM_SEG(wbs)); + + if (iswrite) + asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); + else + asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); + + asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); + + set_fs(old_fs); + + return mmusr; +} + +static inline int do_040writeback1(unsigned short wbs, unsigned long wba, + unsigned long wbd) +{ + int res = 0; + mm_segment_t old_fs = get_fs(); + + /* set_fs can not be moved, otherwise put_user() may oops */ + set_fs(MAKE_MM_SEG(wbs)); + + switch (wbs & WBSIZ_040) { + case BA_SIZE_BYTE: + res = put_user(wbd & 0xff, (char __user *)wba); + break; + case BA_SIZE_WORD: + res = put_user(wbd & 0xffff, (short __user *)wba); + break; + case BA_SIZE_LONG: + res = put_user(wbd, (int __user *)wba); + break; + } + + /* set_fs can not be moved, otherwise put_user() may oops */ + set_fs(old_fs); + + +#ifdef DEBUG + printk("do_040writeback1, res=%d\n",res); +#endif + + return res; +} + +/* after an exception in a writeback the stack frame corresponding + * to that exception is discarded, set a few bits in the old frame + * to simulate what it should look like + */ +static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs) +{ + fp->un.fmt7.faddr = wba; + fp->un.fmt7.ssw = wbs & 0xff; + if (wba != current->thread.faddr) + fp->un.fmt7.ssw |= MA_040; +} + +static inline void do_040writebacks(struct frame *fp) +{ + int res = 0; +#if 0 + if (fp->un.fmt7.wb1s & WBV_040) + printk("access_error040: cannot handle 1st writeback. oops.\n"); +#endif + + if ((fp->un.fmt7.wb2s & WBV_040) && + !(fp->un.fmt7.wb2s & WBTT_040)) { + res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, + fp->un.fmt7.wb2d); + if (res) + fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); + else + fp->un.fmt7.wb2s = 0; + } + + /* do the 2nd wb only if the first one was successful (except for a kernel wb) */ + if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { + res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, + fp->un.fmt7.wb3d); + if (res) + { + fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); + + fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; + fp->un.fmt7.wb3s &= (~WBV_040); + fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; + fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; + } + else + fp->un.fmt7.wb3s = 0; + } + + if (res) + send_fault_sig(&fp->ptregs); +} + +/* + * called from sigreturn(), must ensure userspace code didn't + * manipulate exception frame to circumvent protection, then complete + * pending writebacks + * we just clear TM2 to turn it into a userspace access + */ +asmlinkage void berr_040cleanup(struct frame *fp) +{ + fp->un.fmt7.wb2s &= ~4; + fp->un.fmt7.wb3s &= ~4; + + do_040writebacks(fp); +} + +static inline void access_error040(struct frame *fp) +{ + unsigned short ssw = fp->un.fmt7.ssw; + unsigned long mmusr; + +#ifdef DEBUG + printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); + printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, + fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); + printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", + fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, + fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); +#endif + + if (ssw & ATC_040) { + unsigned long addr = fp->un.fmt7.faddr; + unsigned long errorcode; + + /* + * The MMU status has to be determined AFTER the address + * has been corrected if there was a misaligned access (MA). + */ + if (ssw & MA_040) + addr = (addr + 7) & -8; + + /* MMU error, get the MMUSR info for this access */ + mmusr = probe040(!(ssw & RW_040), addr, ssw); +#ifdef DEBUG + printk("mmusr = %lx\n", mmusr); +#endif + errorcode = 1; + if (!(mmusr & MMU_R_040)) { + /* clear the invalid atc entry */ + __flush_tlb040_one(addr); + errorcode = 0; + } + + /* despite what documentation seems to say, RMW + * accesses have always both the LK and RW bits set */ + if (!(ssw & RW_040) || (ssw & LK_040)) + errorcode |= 2; + + if (do_page_fault(&fp->ptregs, addr, errorcode)) { +#ifdef DEBUG + printk("do_page_fault() !=0\n"); +#endif + if (user_mode(&fp->ptregs)){ + /* delay writebacks after signal delivery */ +#ifdef DEBUG + printk(".. was usermode - return\n"); +#endif + return; + } + /* disable writeback into user space from kernel + * (if do_page_fault didn't fix the mapping, + * the writeback won't do good) + */ +disable_wb: +#ifdef DEBUG + printk(".. disabling wb2\n"); +#endif + if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) + fp->un.fmt7.wb2s &= ~WBV_040; + if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) + fp->un.fmt7.wb3s &= ~WBV_040; + } + } else { + /* In case of a bus error we either kill the process or expect + * the kernel to catch the fault, which then is also responsible + * for cleaning up the mess. + */ + current->thread.signo = SIGBUS; + current->thread.faddr = fp->un.fmt7.faddr; + if (send_fault_sig(&fp->ptregs) >= 0) + printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, + fp->un.fmt7.faddr); + goto disable_wb; + } + + do_040writebacks(fp); +} +#endif /* CONFIG_M68040 */ + +#if defined(CONFIG_SUN3) +#include + +extern int mmu_emu_handle_fault (unsigned long, int, int); + +/* sun3 version of bus_error030 */ + +static inline void bus_error030 (struct frame *fp) +{ + unsigned char buserr_type = sun3_get_buserr (); + unsigned long addr, errorcode; + unsigned short ssw = fp->un.fmtb.ssw; + extern unsigned long _sun3_map_test_start, _sun3_map_test_end; + +#ifdef DEBUG + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + ssw & FC ? + fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 + : + fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); +#endif + + /* + * Check if this page should be demand-mapped. This needs to go before + * the testing for a bad kernel-space access (demand-mapping applies + * to kernel accesses too). + */ + + if ((ssw & DF) + && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) { + if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0)) + return; + } + + /* Check for kernel-space pagefault (BAD). */ + if (fp->ptregs.sr & PS_S) { + /* kernel fault must be a data fault to user space */ + if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { + // try checking the kernel mappings before surrender + if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1)) + return; + /* instruction fault or kernel data fault! */ + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + fp->ptregs.pc); + if (ssw & DF) { + /* was this fault incurred testing bus mappings? */ + if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && + (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { + send_fault_sig(&fp->ptregs); + return; + } + + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); + } + printk ("BAD KERNEL BUSERR\n"); + + die_if_kernel("Oops", &fp->ptregs,0); + force_sig(SIGKILL, current); + return; + } + } else { + /* user fault */ + if (!(ssw & (FC | FB)) && !(ssw & DF)) + /* not an instruction fault or data fault! BAD */ + panic ("USER BUSERR w/o instruction or data fault"); + } + + + /* First handle the data fault, if any. */ + if (ssw & DF) { + addr = fp->un.fmtb.daddr; + +// errorcode bit 0: 0 -> no page 1 -> protection fault +// errorcode bit 1: 0 -> read fault 1 -> write fault + +// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault +// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault + + if (buserr_type & SUN3_BUSERR_PROTERR) + errorcode = 0x01; + else if (buserr_type & SUN3_BUSERR_INVALID) + errorcode = 0x00; + else { +#ifdef DEBUG + printk ("*** unexpected busfault type=%#04x\n", buserr_type); + printk ("invalid %s access at %#lx from pc %#lx\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc); +#endif + die_if_kernel ("Oops", &fp->ptregs, buserr_type); + force_sig (SIGBUS, current); + return; + } + +//todo: wtf is RM bit? --m + if (!(ssw & RW) || ssw & RM) + errorcode |= 0x02; + + /* Handle page fault. */ + do_page_fault (&fp->ptregs, addr, errorcode); + + /* Retry the data fault now. */ + return; + } + + /* Now handle the instruction fault. */ + + /* Get the fault address. */ + if (fp->ptregs.format == 0xA) + addr = fp->ptregs.pc + 4; + else + addr = fp->un.fmtb.baddr; + if (ssw & FC) + addr -= 2; + + if (buserr_type & SUN3_BUSERR_INVALID) { + if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) + do_page_fault (&fp->ptregs, addr, 0); + } else { +#ifdef DEBUG + printk ("protection fault on insn access (segv).\n"); +#endif + force_sig (SIGSEGV, current); + } +} +#else +#if defined(CPU_M68020_OR_M68030) +static inline void bus_error030 (struct frame *fp) +{ + volatile unsigned short temp; + unsigned short mmusr; + unsigned long addr, errorcode; + unsigned short ssw = fp->un.fmtb.ssw; +#ifdef DEBUG + unsigned long desc; + + printk ("pid = %x ", current->pid); + printk ("SSW=%#06x ", ssw); + + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + ssw & FC ? + fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 + : + fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); +#endif + + /* ++andreas: If a data fault and an instruction fault happen + at the same time map in both pages. */ + + /* First handle the data fault, if any. */ + if (ssw & DF) { + addr = fp->un.fmtb.daddr; + +#ifdef DEBUG + asm volatile ("ptestr %3,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr), "d" (ssw)); +#else + asm volatile ("ptestr %2,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr), "d" (ssw)); +#endif + mmusr = temp; + +#ifdef DEBUG + printk("mmusr is %#x for addr %#lx in task %p\n", + mmusr, addr, current); + printk("descriptor address is %#lx, contents %#lx\n", + __va(desc), *(unsigned long *)__va(desc)); +#endif + + errorcode = (mmusr & MMU_I) ? 0 : 1; + if (!(ssw & RW) || (ssw & RM)) + errorcode |= 2; + + if (mmusr & (MMU_I | MMU_WP)) { + if (ssw & 4) { + printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); + goto buserr; + } + /* Don't try to do anything further if an exception was + handled. */ + if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) + return; + } else if (!(mmusr & MMU_I)) { + /* probably a 020 cas fault */ + if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) + printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); + } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { + printk("invalid %s access at %#lx from pc %#lx\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc); + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } else { +#if 0 + static volatile long tlong; +#endif + + printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc, ssw); + asm volatile ("ptestr #1,%1@,#0\n\t" + "pmove %%psr,%0@" + : /* no outputs */ + : "a" (&temp), "a" (addr)); + mmusr = temp; + + printk ("level 0 mmusr is %#x\n", mmusr); +#if 0 + asm volatile ("pmove %%tt0,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt0 is %#lx, ", tlong); + asm volatile ("pmove %%tt1,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt1 is %#lx\n", tlong); +#endif +#ifdef DEBUG + printk("Unknown SIGSEGV - 1\n"); +#endif + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } + + /* setup an ATC entry for the access about to be retried */ + if (!(ssw & RW) || (ssw & RM)) + asm volatile ("ploadw %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + else + asm volatile ("ploadr %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + } + + /* Now handle the instruction fault. */ + + if (!(ssw & (FC|FB))) + return; + + if (fp->ptregs.sr & PS_S) { + printk("Instruction fault at %#010lx\n", + fp->ptregs.pc); + buserr: + printk ("BAD KERNEL BUSERR\n"); + die_if_kernel("Oops",&fp->ptregs,0); + force_sig(SIGKILL, current); + return; + } + + /* get the fault address */ + if (fp->ptregs.format == 10) + addr = fp->ptregs.pc + 4; + else + addr = fp->un.fmtb.baddr; + if (ssw & FC) + addr -= 2; + + if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0) + /* Insn fault on same page as data fault. But we + should still create the ATC entry. */ + goto create_atc_entry; + +#ifdef DEBUG + asm volatile ("ptestr #1,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr)); +#else + asm volatile ("ptestr #1,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr)); +#endif + mmusr = temp; + +#ifdef DEBUG + printk ("mmusr is %#x for addr %#lx in task %p\n", + mmusr, addr, current); + printk ("descriptor address is %#lx, contents %#lx\n", + __va(desc), *(unsigned long *)__va(desc)); +#endif + + if (mmusr & MMU_I) + do_page_fault (&fp->ptregs, addr, 0); + else if (mmusr & (MMU_B|MMU_L|MMU_S)) { + printk ("invalid insn access at %#lx from pc %#lx\n", + addr, fp->ptregs.pc); +#ifdef DEBUG + printk("Unknown SIGSEGV - 2\n"); +#endif + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } + +create_atc_entry: + /* setup an ATC entry for the access about to be retried */ + asm volatile ("ploadr #2,%0@" : /* no outputs */ + : "a" (addr)); +} +#endif /* CPU_M68020_OR_M68030 */ +#endif /* !CONFIG_SUN3 */ + +asmlinkage void buserr_c(struct frame *fp) +{ + /* Only set esp0 if coming from user mode */ + if (user_mode(&fp->ptregs)) + current->thread.esp0 = (unsigned long) fp; + +#ifdef DEBUG + printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); +#endif + + switch (fp->ptregs.format) { +#if defined (CONFIG_M68060) + case 4: /* 68060 access error */ + access_error060 (fp); + break; +#endif +#if defined (CONFIG_M68040) + case 0x7: /* 68040 access error */ + access_error040 (fp); + break; +#endif +#if defined (CPU_M68020_OR_M68030) + case 0xa: + case 0xb: + bus_error030 (fp); + break; +#endif + default: + die_if_kernel("bad frame format",&fp->ptregs,0); +#ifdef DEBUG + printk("Unknown SIGSEGV - 4\n"); +#endif + force_sig(SIGSEGV, current); + } +} + + +static int kstack_depth_to_print = 48; + +void show_trace(unsigned long *stack) +{ + unsigned long *endstack; + unsigned long addr; + int i; + + printk("Call Trace:"); + addr = (unsigned long)stack + THREAD_SIZE - 1; + endstack = (unsigned long *)(addr & -THREAD_SIZE); + i = 0; + while (stack + 1 <= endstack) { + addr = *stack++; + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (__kernel_text_address(addr)) { +#ifndef CONFIG_KALLSYMS + if (i % 5 == 0) + printk("\n "); +#endif + printk(" [<%08lx>] %pS\n", addr, (void *)addr); + i++; + } + } + printk("\n"); +} + +void show_registers(struct pt_regs *regs) +{ + struct frame *fp = (struct frame *)regs; + mm_segment_t old_fs = get_fs(); + u16 c, *cp; + unsigned long addr; + int i; + + print_modules(); + printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); + printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + regs->d0, regs->d1, regs->d2, regs->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + regs->d4, regs->d5, regs->a0, regs->a1); + + printk("Process %s (pid: %d, task=%p)\n", + current->comm, task_pid_nr(current), current); + addr = (unsigned long)&fp->un; + printk("Frame format=%X ", regs->format); + switch (regs->format) { + case 0x2: + printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); + addr += sizeof(fp->un.fmt2); + break; + case 0x3: + printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); + addr += sizeof(fp->un.fmt3); + break; + case 0x4: + printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" + : "eff addr=%08lx pc=%08lx\n"), + fp->un.fmt4.effaddr, fp->un.fmt4.pc); + addr += sizeof(fp->un.fmt4); + break; + case 0x7: + printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", + fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); + printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); + printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); + printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); + printk("push data: %08lx %08lx %08lx %08lx\n", + fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, + fp->un.fmt7.pd3); + addr += sizeof(fp->un.fmt7); + break; + case 0x9: + printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); + addr += sizeof(fp->un.fmt9); + break; + case 0xa: + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, + fp->un.fmta.daddr, fp->un.fmta.dobuf); + addr += sizeof(fp->un.fmta); + break; + case 0xb: + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, + fp->un.fmtb.daddr, fp->un.fmtb.dobuf); + printk("baddr=%08lx dibuf=%08lx ver=%x\n", + fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); + addr += sizeof(fp->un.fmtb); + break; + default: + printk("\n"); + } + show_stack(NULL, (unsigned long *)addr); + + printk("Code:"); + set_fs(KERNEL_DS); + cp = (u16 *)regs->pc; + for (i = -8; i < 16; i++) { + if (get_user(c, cp + i) && i >= 0) { + printk(" Bad PC value."); + break; + } + printk(i ? " %04x" : " <%04x>", c); + } + set_fs(old_fs); + printk ("\n"); +} + +void show_stack(struct task_struct *task, unsigned long *stack) +{ + unsigned long *p; + unsigned long *endstack; + int i; + + if (!stack) { + if (task) + stack = (unsigned long *)task->thread.esp0; + else + stack = (unsigned long *)&stack; + } + endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); + + printk("Stack from %08lx:", (unsigned long)stack); + p = stack; + for (i = 0; i < kstack_depth_to_print; i++) { + if (p + 1 > endstack) + break; + if (i % 8 == 0) + printk("\n "); + printk(" %08lx", *p++); + } + printk("\n"); + show_trace(stack); +} + +/* + * The architecture-independent backtrace generator + */ +void dump_stack(void) +{ + unsigned long stack; + + show_trace(&stack); +} + +EXPORT_SYMBOL(dump_stack); + +void bad_super_trap (struct frame *fp) +{ + console_verbose(); + if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names)) + printk ("*** %s *** FORMAT=%X\n", + vec_names[(fp->ptregs.vector) >> 2], + fp->ptregs.format); + else + printk ("*** Exception %d *** FORMAT=%X\n", + (fp->ptregs.vector) >> 2, + fp->ptregs.format); + if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) { + unsigned short ssw = fp->un.fmtb.ssw; + + printk ("SSW=%#06x ", ssw); + + if (ssw & RC) + printk ("Pipe stage C instruction fault at %#010lx\n", + (fp->ptregs.format) == 0xA ? + fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); + if (ssw & RB) + printk ("Pipe stage B instruction fault at %#010lx\n", + (fp->ptregs.format) == 0xA ? + fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, space_names[ssw & DFC], + fp->ptregs.pc); + } + printk ("Current process id is %d\n", task_pid_nr(current)); + die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); +} + +asmlinkage void trap_c(struct frame *fp) +{ + int sig; + siginfo_t info; + + if (fp->ptregs.sr & PS_S) { + if (fp->ptregs.vector == VEC_TRACE << 2) { + /* traced a trapping instruction on a 68020/30, + * real exception will be executed afterwards. + */ + } else if (!handle_kernel_fault(&fp->ptregs)) + bad_super_trap(fp); + return; + } + + /* send the appropriate signal to the user program */ + switch ((fp->ptregs.vector) >> 2) { + case VEC_ADDRERR: + info.si_code = BUS_ADRALN; + sig = SIGBUS; + break; + case VEC_ILLEGAL: + case VEC_LINE10: + case VEC_LINE11: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + case VEC_PRIV: + info.si_code = ILL_PRVOPC; + sig = SIGILL; + break; + case VEC_COPROC: + info.si_code = ILL_COPROC; + sig = SIGILL; + break; + case VEC_TRAP1: + case VEC_TRAP2: + case VEC_TRAP3: + case VEC_TRAP4: + case VEC_TRAP5: + case VEC_TRAP6: + case VEC_TRAP7: + case VEC_TRAP8: + case VEC_TRAP9: + case VEC_TRAP10: + case VEC_TRAP11: + case VEC_TRAP12: + case VEC_TRAP13: + case VEC_TRAP14: + info.si_code = ILL_ILLTRP; + sig = SIGILL; + break; + case VEC_FPBRUC: + case VEC_FPOE: + case VEC_FPNAN: + info.si_code = FPE_FLTINV; + sig = SIGFPE; + break; + case VEC_FPIR: + info.si_code = FPE_FLTRES; + sig = SIGFPE; + break; + case VEC_FPDIVZ: + info.si_code = FPE_FLTDIV; + sig = SIGFPE; + break; + case VEC_FPUNDER: + info.si_code = FPE_FLTUND; + sig = SIGFPE; + break; + case VEC_FPOVER: + info.si_code = FPE_FLTOVF; + sig = SIGFPE; + break; + case VEC_ZERODIV: + info.si_code = FPE_INTDIV; + sig = SIGFPE; + break; + case VEC_CHK: + case VEC_TRAP: + info.si_code = FPE_INTOVF; + sig = SIGFPE; + break; + case VEC_TRACE: /* ptrace single step */ + info.si_code = TRAP_TRACE; + sig = SIGTRAP; + break; + case VEC_TRAP15: /* breakpoint */ + info.si_code = TRAP_BRKPT; + sig = SIGTRAP; + break; + default: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + } + info.si_signo = sig; + info.si_errno = 0; + switch (fp->ptregs.format) { + default: + info.si_addr = (void *) fp->ptregs.pc; + break; + case 2: + info.si_addr = (void *) fp->un.fmt2.iaddr; + break; + case 7: + info.si_addr = (void *) fp->un.fmt7.effaddr; + break; + case 9: + info.si_addr = (void *) fp->un.fmt9.iaddr; + break; + case 10: + info.si_addr = (void *) fp->un.fmta.daddr; + break; + case 11: + info.si_addr = (void *) fp->un.fmtb.daddr; + break; + } + force_sig_info (sig, &info, current); +} + +void die_if_kernel (char *str, struct pt_regs *fp, int nr) +{ + if (!(fp->sr & PS_S)) + return; + + console_verbose(); + printk("%s: %08x\n",str,nr); + show_registers(fp); + add_taint(TAINT_DIE); + do_exit(SIGSEGV); +} + +/* + * This function is called if an error occur while accessing + * user-space from the fpsp040 code. + */ +asmlinkage void fpsp040_die(void) +{ + do_exit(SIGSEGV); +} + +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpemu_signal(int signal, int code, void *addr) +{ + siginfo_t info; + + info.si_signo = signal; + info.si_errno = 0; + info.si_code = code; + info.si_addr = addr; + force_sig_info(signal, &info, current); +} +#endif diff --git a/trunk/arch/m68knommu/kernel/traps.c b/trunk/arch/m68k/kernel/traps_no.c similarity index 100% rename from trunk/arch/m68knommu/kernel/traps.c rename to trunk/arch/m68k/kernel/traps_no.c diff --git a/trunk/arch/m68k/kernel/vmlinux.lds.S b/trunk/arch/m68k/kernel/vmlinux.lds.S index 99ba315bd0a8..030dabf0bc53 100644 --- a/trunk/arch/m68k/kernel/vmlinux.lds.S +++ b/trunk/arch/m68k/kernel/vmlinux.lds.S @@ -1,10 +1,5 @@ -PHDRS -{ - text PT_LOAD FILEHDR PHDRS FLAGS (7); - data PT_LOAD FLAGS (7); -} -#ifdef CONFIG_SUN3 -#include "vmlinux-sun3.lds" +#ifdef CONFIG_MMU +#include "vmlinux.lds_mm.S" #else -#include "vmlinux-std.lds" +#include "vmlinux.lds_no.S" #endif diff --git a/trunk/arch/m68k/kernel/vmlinux.lds_mm.S b/trunk/arch/m68k/kernel/vmlinux.lds_mm.S new file mode 100644 index 000000000000..99ba315bd0a8 --- /dev/null +++ b/trunk/arch/m68k/kernel/vmlinux.lds_mm.S @@ -0,0 +1,10 @@ +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS (7); + data PT_LOAD FLAGS (7); +} +#ifdef CONFIG_SUN3 +#include "vmlinux-sun3.lds" +#else +#include "vmlinux-std.lds" +#endif diff --git a/trunk/arch/m68knommu/kernel/vmlinux.lds.S b/trunk/arch/m68k/kernel/vmlinux.lds_no.S similarity index 100% rename from trunk/arch/m68knommu/kernel/vmlinux.lds.S rename to trunk/arch/m68k/kernel/vmlinux.lds_no.S diff --git a/trunk/arch/m68k/lib/Makefile b/trunk/arch/m68k/lib/Makefile index af9abf8d9d98..1f95881d8437 100644 --- a/trunk/arch/m68k/lib/Makefile +++ b/trunk/arch/m68k/lib/Makefile @@ -1,6 +1,5 @@ -# -# Makefile for m68k-specific library files.. -# - -lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ - checksum.o string.o uaccess.o +ifdef CONFIG_MMU +include arch/m68k/lib/Makefile_mm +else +include arch/m68k/lib/Makefile_no +endif diff --git a/trunk/arch/m68k/lib/Makefile_mm b/trunk/arch/m68k/lib/Makefile_mm new file mode 100644 index 000000000000..af9abf8d9d98 --- /dev/null +++ b/trunk/arch/m68k/lib/Makefile_mm @@ -0,0 +1,6 @@ +# +# Makefile for m68k-specific library files.. +# + +lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ + checksum.o string.o uaccess.o diff --git a/trunk/arch/m68knommu/lib/Makefile b/trunk/arch/m68k/lib/Makefile_no similarity index 100% rename from trunk/arch/m68knommu/lib/Makefile rename to trunk/arch/m68k/lib/Makefile_no diff --git a/trunk/arch/m68k/lib/checksum.c b/trunk/arch/m68k/lib/checksum.c index 6216f12a756b..1297536060de 100644 --- a/trunk/arch/m68k/lib/checksum.c +++ b/trunk/arch/m68k/lib/checksum.c @@ -1,425 +1,5 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, - * Arnt Gulbrandsen, - * Tom May, - * Andreas Schwab, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: - * Fixed some nasty bugs, causing some horrible crashes. - * A: At some points, the sum (%0) was used as - * length-counter instead of the length counter - * (%1). Thanks to Roman Hodek for pointing this out. - * B: GCC seems to mess up if one uses too many - * data-registers to hold input values and one tries to - * specify d0 and d1 as scratch registers. Letting gcc - * choose these registers itself solves the problem. - * - * 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. - * - * 1998/8/31 Andreas Schwab: - * Zero out rest of buffer on exception in - * csum_partial_copy_from_user. - */ - -#include -#include - -/* - * computes a partial checksum, e.g. for TCP/UDP fragments - */ - -__wsum csum_partial(const void *buff, int len, __wsum sum) -{ - unsigned long tmp1, tmp2; - /* - * Experiments with ethernet and slip connections show that buff - * is aligned on either a 2-byte or 4-byte boundary. - */ - __asm__("movel %2,%3\n\t" - "btst #1,%3\n\t" /* Check alignment */ - "jeq 2f\n\t" - "subql #2,%1\n\t" /* buff%4==2: treat first word */ - "jgt 1f\n\t" - "addql #2,%1\n\t" /* len was == 2, treat only rest */ - "jra 4f\n" - "1:\t" - "addw %2@+,%0\n\t" /* add first word to sum */ - "clrl %3\n\t" - "addxl %3,%0\n" /* add X bit */ - "2:\t" - /* unrolled loop for the main part: do 8 longs at once */ - "movel %1,%3\n\t" /* save len in tmp1 */ - "lsrl #5,%1\n\t" /* len/32 */ - "jeq 2f\n\t" /* not enough... */ - "subql #1,%1\n" - "1:\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "dbra %1,1b\n\t" - "clrl %4\n\t" - "addxl %4,%0\n\t" /* add X bit */ - "clrw %1\n\t" - "subql #1,%1\n\t" - "jcc 1b\n" - "2:\t" - "movel %3,%1\n\t" /* restore len from tmp1 */ - "andw #0x1c,%3\n\t" /* number of rest longs */ - "jeq 4f\n\t" - "lsrw #2,%3\n\t" - "subqw #1,%3\n" - "3:\t" - /* loop for rest longs */ - "movel %2@+,%4\n\t" - "addxl %4,%0\n\t" - "dbra %3,3b\n\t" - "clrl %4\n\t" - "addxl %4,%0\n" /* add X bit */ - "4:\t" - /* now check for rest bytes that do not fit into longs */ - "andw #3,%1\n\t" - "jeq 7f\n\t" - "clrl %4\n\t" /* clear tmp2 for rest bytes */ - "subqw #2,%1\n\t" - "jlt 5f\n\t" - "movew %2@+,%4\n\t" /* have rest >= 2: get word */ - "swap %4\n\t" /* into bits 16..31 */ - "tstw %1\n\t" /* another byte? */ - "jeq 6f\n" - "5:\t" - "moveb %2@,%4\n\t" /* have odd rest: get byte */ - "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */ - "6:\t" - "addl %4,%0\n\t" /* now add rest long to sum */ - "clrl %4\n\t" - "addxl %4,%0\n" /* add X bit */ - "7:\t" - : "=d" (sum), "=d" (len), "=a" (buff), - "=&d" (tmp1), "=&d" (tmp2) - : "0" (sum), "1" (len), "2" (buff) - ); - return(sum); -} - -EXPORT_SYMBOL(csum_partial); - - -/* - * copy from user space while checksumming, with exception handling. - */ - -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err) -{ - /* - * GCC doesn't like more than 10 operands for the asm - * statements so we have to use tmp2 for the error - * code. - */ - unsigned long tmp1, tmp2; - - __asm__("movel %2,%4\n\t" - "btst #1,%4\n\t" /* Check alignment */ - "jeq 2f\n\t" - "subql #2,%1\n\t" /* buff%4==2: treat first word */ - "jgt 1f\n\t" - "addql #2,%1\n\t" /* len was == 2, treat only rest */ - "jra 4f\n" - "1:\n" - "10:\t" - "movesw %2@+,%4\n\t" /* add first word to sum */ - "addw %4,%0\n\t" - "movew %4,%3@+\n\t" - "clrl %4\n\t" - "addxl %4,%0\n" /* add X bit */ - "2:\t" - /* unrolled loop for the main part: do 8 longs at once */ - "movel %1,%4\n\t" /* save len in tmp1 */ - "lsrl #5,%1\n\t" /* len/32 */ - "jeq 2f\n\t" /* not enough... */ - "subql #1,%1\n" - "1:\n" - "11:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "12:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "13:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "14:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "15:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "16:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "17:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "18:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "dbra %1,1b\n\t" - "clrl %5\n\t" - "addxl %5,%0\n\t" /* add X bit */ - "clrw %1\n\t" - "subql #1,%1\n\t" - "jcc 1b\n" - "2:\t" - "movel %4,%1\n\t" /* restore len from tmp1 */ - "andw #0x1c,%4\n\t" /* number of rest longs */ - "jeq 4f\n\t" - "lsrw #2,%4\n\t" - "subqw #1,%4\n" - "3:\n" - /* loop for rest longs */ - "19:\t" - "movesl %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "dbra %4,3b\n\t" - "clrl %5\n\t" - "addxl %5,%0\n" /* add X bit */ - "4:\t" - /* now check for rest bytes that do not fit into longs */ - "andw #3,%1\n\t" - "jeq 7f\n\t" - "clrl %5\n\t" /* clear tmp2 for rest bytes */ - "subqw #2,%1\n\t" - "jlt 5f\n\t" - "20:\t" - "movesw %2@+,%5\n\t" /* have rest >= 2: get word */ - "movew %5,%3@+\n\t" - "swap %5\n\t" /* into bits 16..31 */ - "tstw %1\n\t" /* another byte? */ - "jeq 6f\n" - "5:\n" - "21:\t" - "movesb %2@,%5\n\t" /* have odd rest: get byte */ - "moveb %5,%3@+\n\t" - "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */ - "6:\t" - "addl %5,%0\n\t" /* now add rest long to sum */ - "clrl %5\n\t" - "addxl %5,%0\n\t" /* add X bit */ - "7:\t" - "clrl %5\n" /* no error - clear return value */ - "8:\n" - ".section .fixup,\"ax\"\n" - ".even\n" - /* If any exception occurs zero out the rest. - Similarities with the code above are intentional :-) */ - "90:\t" - "clrw %3@+\n\t" - "movel %1,%4\n\t" - "lsrl #5,%1\n\t" - "jeq 1f\n\t" - "subql #1,%1\n" - "91:\t" - "clrl %3@+\n" - "92:\t" - "clrl %3@+\n" - "93:\t" - "clrl %3@+\n" - "94:\t" - "clrl %3@+\n" - "95:\t" - "clrl %3@+\n" - "96:\t" - "clrl %3@+\n" - "97:\t" - "clrl %3@+\n" - "98:\t" - "clrl %3@+\n\t" - "dbra %1,91b\n\t" - "clrw %1\n\t" - "subql #1,%1\n\t" - "jcc 91b\n" - "1:\t" - "movel %4,%1\n\t" - "andw #0x1c,%4\n\t" - "jeq 1f\n\t" - "lsrw #2,%4\n\t" - "subqw #1,%4\n" - "99:\t" - "clrl %3@+\n\t" - "dbra %4,99b\n\t" - "1:\t" - "andw #3,%1\n\t" - "jeq 9f\n" - "100:\t" - "clrw %3@+\n\t" - "tstw %1\n\t" - "jeq 9f\n" - "101:\t" - "clrb %3@+\n" - "9:\t" -#define STR(X) STR1(X) -#define STR1(X) #X - "moveq #-" STR(EFAULT) ",%5\n\t" - "jra 8b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - ".long 10b,90b\n" - ".long 11b,91b\n" - ".long 12b,92b\n" - ".long 13b,93b\n" - ".long 14b,94b\n" - ".long 15b,95b\n" - ".long 16b,96b\n" - ".long 17b,97b\n" - ".long 18b,98b\n" - ".long 19b,99b\n" - ".long 20b,100b\n" - ".long 21b,101b\n" - ".previous" - : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), - "=&d" (tmp1), "=d" (tmp2) - : "0" (sum), "1" (len), "2" (src), "3" (dst) - ); - - *csum_err = tmp2; - - return(sum); -} - -EXPORT_SYMBOL(csum_partial_copy_from_user); - - -/* - * copy from kernel space while checksumming, otherwise like csum_partial - */ - -__wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) -{ - unsigned long tmp1, tmp2; - __asm__("movel %2,%4\n\t" - "btst #1,%4\n\t" /* Check alignment */ - "jeq 2f\n\t" - "subql #2,%1\n\t" /* buff%4==2: treat first word */ - "jgt 1f\n\t" - "addql #2,%1\n\t" /* len was == 2, treat only rest */ - "jra 4f\n" - "1:\t" - "movew %2@+,%4\n\t" /* add first word to sum */ - "addw %4,%0\n\t" - "movew %4,%3@+\n\t" - "clrl %4\n\t" - "addxl %4,%0\n" /* add X bit */ - "2:\t" - /* unrolled loop for the main part: do 8 longs at once */ - "movel %1,%4\n\t" /* save len in tmp1 */ - "lsrl #5,%1\n\t" /* len/32 */ - "jeq 2f\n\t" /* not enough... */ - "subql #1,%1\n" - "1:\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "dbra %1,1b\n\t" - "clrl %5\n\t" - "addxl %5,%0\n\t" /* add X bit */ - "clrw %1\n\t" - "subql #1,%1\n\t" - "jcc 1b\n" - "2:\t" - "movel %4,%1\n\t" /* restore len from tmp1 */ - "andw #0x1c,%4\n\t" /* number of rest longs */ - "jeq 4f\n\t" - "lsrw #2,%4\n\t" - "subqw #1,%4\n" - "3:\t" - /* loop for rest longs */ - "movel %2@+,%5\n\t" - "addxl %5,%0\n\t" - "movel %5,%3@+\n\t" - "dbra %4,3b\n\t" - "clrl %5\n\t" - "addxl %5,%0\n" /* add X bit */ - "4:\t" - /* now check for rest bytes that do not fit into longs */ - "andw #3,%1\n\t" - "jeq 7f\n\t" - "clrl %5\n\t" /* clear tmp2 for rest bytes */ - "subqw #2,%1\n\t" - "jlt 5f\n\t" - "movew %2@+,%5\n\t" /* have rest >= 2: get word */ - "movew %5,%3@+\n\t" - "swap %5\n\t" /* into bits 16..31 */ - "tstw %1\n\t" /* another byte? */ - "jeq 6f\n" - "5:\t" - "moveb %2@,%5\n\t" /* have odd rest: get byte */ - "moveb %5,%3@+\n\t" - "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */ - "6:\t" - "addl %5,%0\n\t" /* now add rest long to sum */ - "clrl %5\n\t" - "addxl %5,%0\n" /* add X bit */ - "7:\t" - : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), - "=&d" (tmp1), "=&d" (tmp2) - : "0" (sum), "1" (len), "2" (src), "3" (dst) - ); - return(sum); -} -EXPORT_SYMBOL(csum_partial_copy_nocheck); +#ifdef CONFIG_MMU +#include "checksum_mm.c" +#else +#include "checksum_no.c" +#endif diff --git a/trunk/arch/m68k/lib/checksum_mm.c b/trunk/arch/m68k/lib/checksum_mm.c new file mode 100644 index 000000000000..6216f12a756b --- /dev/null +++ b/trunk/arch/m68k/lib/checksum_mm.c @@ -0,0 +1,425 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, + * Arnt Gulbrandsen, + * Tom May, + * Andreas Schwab, + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: + * Fixed some nasty bugs, causing some horrible crashes. + * A: At some points, the sum (%0) was used as + * length-counter instead of the length counter + * (%1). Thanks to Roman Hodek for pointing this out. + * B: GCC seems to mess up if one uses too many + * data-registers to hold input values and one tries to + * specify d0 and d1 as scratch registers. Letting gcc + * choose these registers itself solves the problem. + * + * 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. + * + * 1998/8/31 Andreas Schwab: + * Zero out rest of buffer on exception in + * csum_partial_copy_from_user. + */ + +#include +#include + +/* + * computes a partial checksum, e.g. for TCP/UDP fragments + */ + +__wsum csum_partial(const void *buff, int len, __wsum sum) +{ + unsigned long tmp1, tmp2; + /* + * Experiments with ethernet and slip connections show that buff + * is aligned on either a 2-byte or 4-byte boundary. + */ + __asm__("movel %2,%3\n\t" + "btst #1,%3\n\t" /* Check alignment */ + "jeq 2f\n\t" + "subql #2,%1\n\t" /* buff%4==2: treat first word */ + "jgt 1f\n\t" + "addql #2,%1\n\t" /* len was == 2, treat only rest */ + "jra 4f\n" + "1:\t" + "addw %2@+,%0\n\t" /* add first word to sum */ + "clrl %3\n\t" + "addxl %3,%0\n" /* add X bit */ + "2:\t" + /* unrolled loop for the main part: do 8 longs at once */ + "movel %1,%3\n\t" /* save len in tmp1 */ + "lsrl #5,%1\n\t" /* len/32 */ + "jeq 2f\n\t" /* not enough... */ + "subql #1,%1\n" + "1:\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "dbra %1,1b\n\t" + "clrl %4\n\t" + "addxl %4,%0\n\t" /* add X bit */ + "clrw %1\n\t" + "subql #1,%1\n\t" + "jcc 1b\n" + "2:\t" + "movel %3,%1\n\t" /* restore len from tmp1 */ + "andw #0x1c,%3\n\t" /* number of rest longs */ + "jeq 4f\n\t" + "lsrw #2,%3\n\t" + "subqw #1,%3\n" + "3:\t" + /* loop for rest longs */ + "movel %2@+,%4\n\t" + "addxl %4,%0\n\t" + "dbra %3,3b\n\t" + "clrl %4\n\t" + "addxl %4,%0\n" /* add X bit */ + "4:\t" + /* now check for rest bytes that do not fit into longs */ + "andw #3,%1\n\t" + "jeq 7f\n\t" + "clrl %4\n\t" /* clear tmp2 for rest bytes */ + "subqw #2,%1\n\t" + "jlt 5f\n\t" + "movew %2@+,%4\n\t" /* have rest >= 2: get word */ + "swap %4\n\t" /* into bits 16..31 */ + "tstw %1\n\t" /* another byte? */ + "jeq 6f\n" + "5:\t" + "moveb %2@,%4\n\t" /* have odd rest: get byte */ + "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */ + "6:\t" + "addl %4,%0\n\t" /* now add rest long to sum */ + "clrl %4\n\t" + "addxl %4,%0\n" /* add X bit */ + "7:\t" + : "=d" (sum), "=d" (len), "=a" (buff), + "=&d" (tmp1), "=&d" (tmp2) + : "0" (sum), "1" (len), "2" (buff) + ); + return(sum); +} + +EXPORT_SYMBOL(csum_partial); + + +/* + * copy from user space while checksumming, with exception handling. + */ + +__wsum +csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *csum_err) +{ + /* + * GCC doesn't like more than 10 operands for the asm + * statements so we have to use tmp2 for the error + * code. + */ + unsigned long tmp1, tmp2; + + __asm__("movel %2,%4\n\t" + "btst #1,%4\n\t" /* Check alignment */ + "jeq 2f\n\t" + "subql #2,%1\n\t" /* buff%4==2: treat first word */ + "jgt 1f\n\t" + "addql #2,%1\n\t" /* len was == 2, treat only rest */ + "jra 4f\n" + "1:\n" + "10:\t" + "movesw %2@+,%4\n\t" /* add first word to sum */ + "addw %4,%0\n\t" + "movew %4,%3@+\n\t" + "clrl %4\n\t" + "addxl %4,%0\n" /* add X bit */ + "2:\t" + /* unrolled loop for the main part: do 8 longs at once */ + "movel %1,%4\n\t" /* save len in tmp1 */ + "lsrl #5,%1\n\t" /* len/32 */ + "jeq 2f\n\t" /* not enough... */ + "subql #1,%1\n" + "1:\n" + "11:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "12:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "13:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "14:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "15:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "16:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "17:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "18:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "dbra %1,1b\n\t" + "clrl %5\n\t" + "addxl %5,%0\n\t" /* add X bit */ + "clrw %1\n\t" + "subql #1,%1\n\t" + "jcc 1b\n" + "2:\t" + "movel %4,%1\n\t" /* restore len from tmp1 */ + "andw #0x1c,%4\n\t" /* number of rest longs */ + "jeq 4f\n\t" + "lsrw #2,%4\n\t" + "subqw #1,%4\n" + "3:\n" + /* loop for rest longs */ + "19:\t" + "movesl %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "dbra %4,3b\n\t" + "clrl %5\n\t" + "addxl %5,%0\n" /* add X bit */ + "4:\t" + /* now check for rest bytes that do not fit into longs */ + "andw #3,%1\n\t" + "jeq 7f\n\t" + "clrl %5\n\t" /* clear tmp2 for rest bytes */ + "subqw #2,%1\n\t" + "jlt 5f\n\t" + "20:\t" + "movesw %2@+,%5\n\t" /* have rest >= 2: get word */ + "movew %5,%3@+\n\t" + "swap %5\n\t" /* into bits 16..31 */ + "tstw %1\n\t" /* another byte? */ + "jeq 6f\n" + "5:\n" + "21:\t" + "movesb %2@,%5\n\t" /* have odd rest: get byte */ + "moveb %5,%3@+\n\t" + "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */ + "6:\t" + "addl %5,%0\n\t" /* now add rest long to sum */ + "clrl %5\n\t" + "addxl %5,%0\n\t" /* add X bit */ + "7:\t" + "clrl %5\n" /* no error - clear return value */ + "8:\n" + ".section .fixup,\"ax\"\n" + ".even\n" + /* If any exception occurs zero out the rest. + Similarities with the code above are intentional :-) */ + "90:\t" + "clrw %3@+\n\t" + "movel %1,%4\n\t" + "lsrl #5,%1\n\t" + "jeq 1f\n\t" + "subql #1,%1\n" + "91:\t" + "clrl %3@+\n" + "92:\t" + "clrl %3@+\n" + "93:\t" + "clrl %3@+\n" + "94:\t" + "clrl %3@+\n" + "95:\t" + "clrl %3@+\n" + "96:\t" + "clrl %3@+\n" + "97:\t" + "clrl %3@+\n" + "98:\t" + "clrl %3@+\n\t" + "dbra %1,91b\n\t" + "clrw %1\n\t" + "subql #1,%1\n\t" + "jcc 91b\n" + "1:\t" + "movel %4,%1\n\t" + "andw #0x1c,%4\n\t" + "jeq 1f\n\t" + "lsrw #2,%4\n\t" + "subqw #1,%4\n" + "99:\t" + "clrl %3@+\n\t" + "dbra %4,99b\n\t" + "1:\t" + "andw #3,%1\n\t" + "jeq 9f\n" + "100:\t" + "clrw %3@+\n\t" + "tstw %1\n\t" + "jeq 9f\n" + "101:\t" + "clrb %3@+\n" + "9:\t" +#define STR(X) STR1(X) +#define STR1(X) #X + "moveq #-" STR(EFAULT) ",%5\n\t" + "jra 8b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + ".long 10b,90b\n" + ".long 11b,91b\n" + ".long 12b,92b\n" + ".long 13b,93b\n" + ".long 14b,94b\n" + ".long 15b,95b\n" + ".long 16b,96b\n" + ".long 17b,97b\n" + ".long 18b,98b\n" + ".long 19b,99b\n" + ".long 20b,100b\n" + ".long 21b,101b\n" + ".previous" + : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), + "=&d" (tmp1), "=d" (tmp2) + : "0" (sum), "1" (len), "2" (src), "3" (dst) + ); + + *csum_err = tmp2; + + return(sum); +} + +EXPORT_SYMBOL(csum_partial_copy_from_user); + + +/* + * copy from kernel space while checksumming, otherwise like csum_partial + */ + +__wsum +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +{ + unsigned long tmp1, tmp2; + __asm__("movel %2,%4\n\t" + "btst #1,%4\n\t" /* Check alignment */ + "jeq 2f\n\t" + "subql #2,%1\n\t" /* buff%4==2: treat first word */ + "jgt 1f\n\t" + "addql #2,%1\n\t" /* len was == 2, treat only rest */ + "jra 4f\n" + "1:\t" + "movew %2@+,%4\n\t" /* add first word to sum */ + "addw %4,%0\n\t" + "movew %4,%3@+\n\t" + "clrl %4\n\t" + "addxl %4,%0\n" /* add X bit */ + "2:\t" + /* unrolled loop for the main part: do 8 longs at once */ + "movel %1,%4\n\t" /* save len in tmp1 */ + "lsrl #5,%1\n\t" /* len/32 */ + "jeq 2f\n\t" /* not enough... */ + "subql #1,%1\n" + "1:\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "dbra %1,1b\n\t" + "clrl %5\n\t" + "addxl %5,%0\n\t" /* add X bit */ + "clrw %1\n\t" + "subql #1,%1\n\t" + "jcc 1b\n" + "2:\t" + "movel %4,%1\n\t" /* restore len from tmp1 */ + "andw #0x1c,%4\n\t" /* number of rest longs */ + "jeq 4f\n\t" + "lsrw #2,%4\n\t" + "subqw #1,%4\n" + "3:\t" + /* loop for rest longs */ + "movel %2@+,%5\n\t" + "addxl %5,%0\n\t" + "movel %5,%3@+\n\t" + "dbra %4,3b\n\t" + "clrl %5\n\t" + "addxl %5,%0\n" /* add X bit */ + "4:\t" + /* now check for rest bytes that do not fit into longs */ + "andw #3,%1\n\t" + "jeq 7f\n\t" + "clrl %5\n\t" /* clear tmp2 for rest bytes */ + "subqw #2,%1\n\t" + "jlt 5f\n\t" + "movew %2@+,%5\n\t" /* have rest >= 2: get word */ + "movew %5,%3@+\n\t" + "swap %5\n\t" /* into bits 16..31 */ + "tstw %1\n\t" /* another byte? */ + "jeq 6f\n" + "5:\t" + "moveb %2@,%5\n\t" /* have odd rest: get byte */ + "moveb %5,%3@+\n\t" + "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */ + "6:\t" + "addl %5,%0\n\t" /* now add rest long to sum */ + "clrl %5\n\t" + "addxl %5,%0\n" /* add X bit */ + "7:\t" + : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), + "=&d" (tmp1), "=&d" (tmp2) + : "0" (sum), "1" (len), "2" (src), "3" (dst) + ); + return(sum); +} +EXPORT_SYMBOL(csum_partial_copy_nocheck); diff --git a/trunk/arch/m68knommu/lib/checksum.c b/trunk/arch/m68k/lib/checksum_no.c similarity index 100% rename from trunk/arch/m68knommu/lib/checksum.c rename to trunk/arch/m68k/lib/checksum_no.c diff --git a/trunk/arch/m68knommu/lib/delay.c b/trunk/arch/m68k/lib/delay.c similarity index 100% rename from trunk/arch/m68knommu/lib/delay.c rename to trunk/arch/m68k/lib/delay.c diff --git a/trunk/arch/m68knommu/lib/divsi3.S b/trunk/arch/m68k/lib/divsi3.S similarity index 100% rename from trunk/arch/m68knommu/lib/divsi3.S rename to trunk/arch/m68k/lib/divsi3.S diff --git a/trunk/arch/m68knommu/lib/memcpy.c b/trunk/arch/m68k/lib/memcpy.c similarity index 100% rename from trunk/arch/m68knommu/lib/memcpy.c rename to trunk/arch/m68k/lib/memcpy.c diff --git a/trunk/arch/m68knommu/lib/memmove.c b/trunk/arch/m68k/lib/memmove.c similarity index 100% rename from trunk/arch/m68knommu/lib/memmove.c rename to trunk/arch/m68k/lib/memmove.c diff --git a/trunk/arch/m68knommu/lib/memset.c b/trunk/arch/m68k/lib/memset.c similarity index 100% rename from trunk/arch/m68knommu/lib/memset.c rename to trunk/arch/m68k/lib/memset.c diff --git a/trunk/arch/m68knommu/lib/modsi3.S b/trunk/arch/m68k/lib/modsi3.S similarity index 100% rename from trunk/arch/m68knommu/lib/modsi3.S rename to trunk/arch/m68k/lib/modsi3.S diff --git a/trunk/arch/m68k/lib/muldi3.c b/trunk/arch/m68k/lib/muldi3.c index be4f275649e3..16e0eb338ee0 100644 --- a/trunk/arch/m68k/lib/muldi3.c +++ b/trunk/arch/m68k/lib/muldi3.c @@ -1,63 +1,5 @@ -/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and - gcc-2.7.2.3/longlong.h which is: */ -/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 - -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "dmi" ((USItype)(v))) - -#define __umulsidi3(u, v) \ - ({DIunion __w; \ - umul_ppmm (__w.s.high, __w.s.low, u, v); \ - __w.ll; }) - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__muldi3 (DItype u, DItype v) -{ - DIunion w; - DIunion uu, vv; - - uu.ll = u, - vv.ll = v; - - w.ll = __umulsidi3 (uu.s.low, vv.s.low); - w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high - + (USItype) uu.s.high * (USItype) vv.s.low); - - return w.ll; -} +#ifdef CONFIG_MMU +#include "muldi3_mm.c" +#else +#include "muldi3_no.c" +#endif diff --git a/trunk/arch/m68knommu/lib/ashrdi3.c b/trunk/arch/m68k/lib/muldi3_mm.c similarity index 60% rename from trunk/arch/m68knommu/lib/ashrdi3.c rename to trunk/arch/m68k/lib/muldi3_mm.c index 78efb65e315a..be4f275649e3 100644 --- a/trunk/arch/m68knommu/lib/ashrdi3.c +++ b/trunk/arch/m68k/lib/muldi3_mm.c @@ -1,4 +1,5 @@ -/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU CC. @@ -20,7 +21,19 @@ Boston, MA 02111-1307, USA. */ #define BITS_PER_UNIT 8 -typedef int SItype __attribute__ ((mode (SI))); +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) + +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +typedef int SItype __attribute__ ((mode (SI))); typedef unsigned int USItype __attribute__ ((mode (SI))); typedef int DItype __attribute__ ((mode (DI))); typedef int word_type __attribute__ ((mode (__word__))); @@ -34,30 +47,17 @@ typedef union } DIunion; DItype -__ashrdi3 (DItype u, word_type b) +__muldi3 (DItype u, DItype v) { DIunion w; - word_type bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof (SItype) * BITS_PER_UNIT) - b; - if (bm <= 0) - { - /* w.s.high = 1..1 or 0..0 */ - w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); - w.s.low = uu.s.high >> -bm; - } - else - { - USItype carries = (USItype)uu.s.high << bm; - w.s.high = uu.s.high >> b; - w.s.low = ((USItype)uu.s.low >> b) | carries; - } + DIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); return w.ll; } diff --git a/trunk/arch/m68knommu/lib/muldi3.c b/trunk/arch/m68k/lib/muldi3_no.c similarity index 100% rename from trunk/arch/m68knommu/lib/muldi3.c rename to trunk/arch/m68k/lib/muldi3_no.c diff --git a/trunk/arch/m68knommu/lib/mulsi3.S b/trunk/arch/m68k/lib/mulsi3.S similarity index 100% rename from trunk/arch/m68knommu/lib/mulsi3.S rename to trunk/arch/m68k/lib/mulsi3.S diff --git a/trunk/arch/m68knommu/lib/udivsi3.S b/trunk/arch/m68k/lib/udivsi3.S similarity index 100% rename from trunk/arch/m68knommu/lib/udivsi3.S rename to trunk/arch/m68k/lib/udivsi3.S diff --git a/trunk/arch/m68knommu/lib/umodsi3.S b/trunk/arch/m68k/lib/umodsi3.S similarity index 100% rename from trunk/arch/m68knommu/lib/umodsi3.S rename to trunk/arch/m68k/lib/umodsi3.S diff --git a/trunk/arch/m68k/mm/Makefile b/trunk/arch/m68k/mm/Makefile index 5eaa43c4cb3c..b60270e4954b 100644 --- a/trunk/arch/m68k/mm/Makefile +++ b/trunk/arch/m68k/mm/Makefile @@ -1,8 +1,5 @@ -# -# Makefile for the linux m68k-specific parts of the memory manager. -# - -obj-y := cache.o init.o fault.o hwtest.o - -obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o -obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o +ifdef CONFIG_MMU +include arch/m68k/mm/Makefile_mm +else +include arch/m68k/mm/Makefile_no +endif diff --git a/trunk/arch/m68k/mm/Makefile_mm b/trunk/arch/m68k/mm/Makefile_mm new file mode 100644 index 000000000000..5eaa43c4cb3c --- /dev/null +++ b/trunk/arch/m68k/mm/Makefile_mm @@ -0,0 +1,8 @@ +# +# Makefile for the linux m68k-specific parts of the memory manager. +# + +obj-y := cache.o init.o fault.o hwtest.o + +obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o +obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o diff --git a/trunk/arch/m68knommu/mm/Makefile b/trunk/arch/m68k/mm/Makefile_no similarity index 100% rename from trunk/arch/m68knommu/mm/Makefile rename to trunk/arch/m68k/mm/Makefile_no diff --git a/trunk/arch/m68k/mm/init.c b/trunk/arch/m68k/mm/init.c index 8bc842554e5b..27b5ce089a34 100644 --- a/trunk/arch/m68k/mm/init.c +++ b/trunk/arch/m68k/mm/init.c @@ -1,150 +1,5 @@ -/* - * linux/arch/m68k/mm/init.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * Contains common initialization routines, specific init code moved - * to motorola.c and sun3mmu.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_ATARI -#include -#endif -#include -#include - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -pg_data_t pg_data_map[MAX_NUMNODES]; -EXPORT_SYMBOL(pg_data_map); - -int m68k_virt_to_node_shift; - -#ifndef CONFIG_SINGLE_MEMORY_CHUNK -pg_data_t *pg_data_table[65]; -EXPORT_SYMBOL(pg_data_table); -#endif - -void __init m68k_setup_node(int node) -{ -#ifndef CONFIG_SINGLE_MEMORY_CHUNK - struct mem_info *info = m68k_memory + node; - int i, end; - - i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift(); - end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift(); - for (; i <= end; i++) { - if (pg_data_table[i]) - printk("overlap at %u for chunk %u\n", i, node); - pg_data_table[i] = pg_data_map + node; - } -#endif - pg_data_map[node].bdata = bootmem_node_data + node; - node_set_online(node); -} - - -/* - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ - -void *empty_zero_page; -EXPORT_SYMBOL(empty_zero_page); - -extern void init_pointer_table(unsigned long ptable); - -/* References to section boundaries */ - -extern pmd_t *zero_pgtable; - -void __init mem_init(void) -{ - pg_data_t *pgdat; - int codepages = 0; - int datapages = 0; - int initpages = 0; - int i; - -#ifdef CONFIG_ATARI - if (MACH_IS_ATARI) - atari_stram_mem_init_hook(); -#endif - - /* this will put all memory onto the freelists */ - totalram_pages = num_physpages = 0; - for_each_online_pgdat(pgdat) { - num_physpages += pgdat->node_present_pages; - - totalram_pages += free_all_bootmem_node(pgdat); - for (i = 0; i < pgdat->node_spanned_pages; i++) { - struct page *page = pgdat->node_mem_map + i; - char *addr = page_to_virt(page); - - if (!PageReserved(page)) - continue; - if (addr >= _text && - addr < _etext) - codepages++; - else if (addr >= __init_begin && - addr < __init_end) - initpages++; - else - datapages++; - } - } - -#ifndef CONFIG_SUN3 - /* insert pointer tables allocated so far into the tablelist */ - init_pointer_table((unsigned long)kernel_pg_dir); - for (i = 0; i < PTRS_PER_PGD; i++) { - if (pgd_present(kernel_pg_dir[i])) - init_pointer_table(__pgd_page(kernel_pg_dir[i])); - } - - /* insert also pointer table that we used to unmap the zero page */ - if (zero_pgtable) - init_pointer_table((unsigned long)zero_pgtable); -#endif - - printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n", - nr_free_pages() << (PAGE_SHIFT-10), - totalram_pages << (PAGE_SHIFT-10), - codepages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10)); -} - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - int pages = 0; - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - pages++; - } - printk ("Freeing initrd memory: %dk freed\n", pages); -} +#ifdef CONFIG_MMU +#include "init_mm.c" +#else +#include "init_no.c" #endif diff --git a/trunk/arch/m68k/mm/init_mm.c b/trunk/arch/m68k/mm/init_mm.c new file mode 100644 index 000000000000..8bc842554e5b --- /dev/null +++ b/trunk/arch/m68k/mm/init_mm.c @@ -0,0 +1,150 @@ +/* + * linux/arch/m68k/mm/init.c + * + * Copyright (C) 1995 Hamish Macdonald + * + * Contains common initialization routines, specific init code moved + * to motorola.c and sun3mmu.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ATARI +#include +#endif +#include +#include + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + +pg_data_t pg_data_map[MAX_NUMNODES]; +EXPORT_SYMBOL(pg_data_map); + +int m68k_virt_to_node_shift; + +#ifndef CONFIG_SINGLE_MEMORY_CHUNK +pg_data_t *pg_data_table[65]; +EXPORT_SYMBOL(pg_data_table); +#endif + +void __init m68k_setup_node(int node) +{ +#ifndef CONFIG_SINGLE_MEMORY_CHUNK + struct mem_info *info = m68k_memory + node; + int i, end; + + i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift(); + end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift(); + for (; i <= end; i++) { + if (pg_data_table[i]) + printk("overlap at %u for chunk %u\n", i, node); + pg_data_table[i] = pg_data_map + node; + } +#endif + pg_data_map[node].bdata = bootmem_node_data + node; + node_set_online(node); +} + + +/* + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ + +void *empty_zero_page; +EXPORT_SYMBOL(empty_zero_page); + +extern void init_pointer_table(unsigned long ptable); + +/* References to section boundaries */ + +extern pmd_t *zero_pgtable; + +void __init mem_init(void) +{ + pg_data_t *pgdat; + int codepages = 0; + int datapages = 0; + int initpages = 0; + int i; + +#ifdef CONFIG_ATARI + if (MACH_IS_ATARI) + atari_stram_mem_init_hook(); +#endif + + /* this will put all memory onto the freelists */ + totalram_pages = num_physpages = 0; + for_each_online_pgdat(pgdat) { + num_physpages += pgdat->node_present_pages; + + totalram_pages += free_all_bootmem_node(pgdat); + for (i = 0; i < pgdat->node_spanned_pages; i++) { + struct page *page = pgdat->node_mem_map + i; + char *addr = page_to_virt(page); + + if (!PageReserved(page)) + continue; + if (addr >= _text && + addr < _etext) + codepages++; + else if (addr >= __init_begin && + addr < __init_end) + initpages++; + else + datapages++; + } + } + +#ifndef CONFIG_SUN3 + /* insert pointer tables allocated so far into the tablelist */ + init_pointer_table((unsigned long)kernel_pg_dir); + for (i = 0; i < PTRS_PER_PGD; i++) { + if (pgd_present(kernel_pg_dir[i])) + init_pointer_table(__pgd_page(kernel_pg_dir[i])); + } + + /* insert also pointer table that we used to unmap the zero page */ + if (zero_pgtable) + init_pointer_table((unsigned long)zero_pgtable); +#endif + + printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n", + nr_free_pages() << (PAGE_SHIFT-10), + totalram_pages << (PAGE_SHIFT-10), + codepages << (PAGE_SHIFT-10), + datapages << (PAGE_SHIFT-10), + initpages << (PAGE_SHIFT-10)); +} + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + int pages = 0; + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + init_page_count(virt_to_page(start)); + free_page(start); + totalram_pages++; + pages++; + } + printk ("Freeing initrd memory: %dk freed\n", pages); +} +#endif diff --git a/trunk/arch/m68knommu/mm/init.c b/trunk/arch/m68k/mm/init_no.c similarity index 100% rename from trunk/arch/m68knommu/mm/init.c rename to trunk/arch/m68k/mm/init_no.c diff --git a/trunk/arch/m68k/mm/kmap.c b/trunk/arch/m68k/mm/kmap.c index 69345849454b..a373d136b2b2 100644 --- a/trunk/arch/m68k/mm/kmap.c +++ b/trunk/arch/m68k/mm/kmap.c @@ -1,367 +1,5 @@ -/* - * linux/arch/m68k/mm/kmap.c - * - * Copyright (C) 1997 Roman Hodek - * - * 10/01/99 cleaned up the code and changing to the same interface - * used by other architectures /Roman Zippel - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#define PTRTREESIZE (256*1024) - -/* - * For 040/060 we can use the virtual memory area like other architectures, - * but for 020/030 we want to use early termination page descriptor and we - * can't mix this with normal page descriptors, so we have to copy that code - * (mm/vmalloc.c) and return appriorate aligned addresses. - */ - -#ifdef CPU_M68040_OR_M68060_ONLY - -#define IO_SIZE PAGE_SIZE - -static inline struct vm_struct *get_io_area(unsigned long size) -{ - return get_vm_area(size, VM_IOREMAP); -} - - -static inline void free_io_area(void *addr) -{ - vfree((void *)(PAGE_MASK & (unsigned long)addr)); -} - +#ifdef CONFIG_MMU +#include "kmap_mm.c" #else - -#define IO_SIZE (256*1024) - -static struct vm_struct *iolist; - -static struct vm_struct *get_io_area(unsigned long size) -{ - unsigned long addr; - struct vm_struct **p, *tmp, *area; - - area = kmalloc(sizeof(*area), GFP_KERNEL); - if (!area) - return NULL; - addr = KMAP_START; - for (p = &iolist; (tmp = *p) ; p = &tmp->next) { - if (size + addr < (unsigned long)tmp->addr) - break; - if (addr > KMAP_END-size) { - kfree(area); - return NULL; - } - addr = tmp->size + (unsigned long)tmp->addr; - } - area->addr = (void *)addr; - area->size = size + IO_SIZE; - area->next = *p; - *p = area; - return area; -} - -static inline void free_io_area(void *addr) -{ - struct vm_struct **p, *tmp; - - if (!addr) - return; - addr = (void *)((unsigned long)addr & -IO_SIZE); - for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { - if (tmp->addr == addr) { - *p = tmp->next; - __iounmap(tmp->addr, tmp->size); - kfree(tmp); - return; - } - } -} - +#include "kmap_no.c" #endif - -/* - * Map some physical address range into the kernel address space. - */ -/* Rewritten by Andreas Schwab to remove all races. */ - -void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) -{ - struct vm_struct *area; - unsigned long virtaddr, retaddr; - long offset; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - /* - * Don't allow mappings that wrap.. - */ - if (!size || physaddr > (unsigned long)(-size)) - return NULL; - -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA) { - if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) - && (cacheflag == IOMAP_NOCACHE_SER)) - return (void __iomem *)physaddr; - } -#endif - -#ifdef DEBUG - printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); -#endif - /* - * Mappings have to be aligned - */ - offset = physaddr & (IO_SIZE - 1); - physaddr &= -IO_SIZE; - size = (size + offset + IO_SIZE - 1) & -IO_SIZE; - - /* - * Ok, go for it.. - */ - area = get_io_area(size); - if (!area) - return NULL; - - virtaddr = (unsigned long)area->addr; - retaddr = virtaddr + offset; -#ifdef DEBUG - printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr); -#endif - - /* - * add cache and table flags to physical address - */ - if (CPU_IS_040_OR_060) { - physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 | - _PAGE_ACCESSED | _PAGE_DIRTY); - switch (cacheflag) { - case IOMAP_FULL_CACHING: - physaddr |= _PAGE_CACHE040; - break; - case IOMAP_NOCACHE_SER: - default: - physaddr |= _PAGE_NOCACHE_S; - break; - case IOMAP_NOCACHE_NONSER: - physaddr |= _PAGE_NOCACHE; - break; - case IOMAP_WRITETHROUGH: - physaddr |= _PAGE_CACHE040W; - break; - } - } else { - physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); - switch (cacheflag) { - case IOMAP_NOCACHE_SER: - case IOMAP_NOCACHE_NONSER: - default: - physaddr |= _PAGE_NOCACHE030; - break; - case IOMAP_FULL_CACHING: - case IOMAP_WRITETHROUGH: - break; - } - } - - while ((long)size > 0) { -#ifdef DEBUG - if (!(virtaddr & (PTRTREESIZE-1))) - printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); -#endif - pgd_dir = pgd_offset_k(virtaddr); - pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr); - if (!pmd_dir) { - printk("ioremap: no mem for pmd_dir\n"); - return NULL; - } - - if (CPU_IS_020_OR_030) { - pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; - physaddr += PTRTREESIZE; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - } else { - pte_dir = pte_alloc_kernel(pmd_dir, virtaddr); - if (!pte_dir) { - printk("ioremap: no mem for pte_dir\n"); - return NULL; - } - - pte_val(*pte_dir) = physaddr; - virtaddr += PAGE_SIZE; - physaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - } -#ifdef DEBUG - printk("\n"); -#endif - flush_tlb_all(); - - return (void __iomem *)retaddr; -} -EXPORT_SYMBOL(__ioremap); - -/* - * Unmap a ioremap()ed region again - */ -void iounmap(void __iomem *addr) -{ -#ifdef CONFIG_AMIGA - if ((!MACH_IS_AMIGA) || - (((unsigned long)addr < 0x40000000) || - ((unsigned long)addr > 0x60000000))) - free_io_area((__force void *)addr); -#else - free_io_area((__force void *)addr); -#endif -} -EXPORT_SYMBOL(iounmap); - -/* - * __iounmap unmaps nearly everything, so be careful - * it doesn't free currently pointer/page tables anymore but it - * wans't used anyway and might be added later. - */ -void __iounmap(void *addr, unsigned long size) -{ - unsigned long virtaddr = (unsigned long)addr; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - while ((long)size > 0) { - pgd_dir = pgd_offset_k(virtaddr); - if (pgd_bad(*pgd_dir)) { - printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); - pgd_clear(pgd_dir); - return; - } - pmd_dir = pmd_offset(pgd_dir, virtaddr); - - if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & 15; - int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; - - if (pmd_type == _PAGE_PRESENT) { - pmd_dir->pmd[pmd_off] = 0; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - continue; - } else if (pmd_type == 0) - continue; - } - - if (pmd_bad(*pmd_dir)) { - printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); - pmd_clear(pmd_dir); - return; - } - pte_dir = pte_offset_kernel(pmd_dir, virtaddr); - - pte_val(*pte_dir) = 0; - virtaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - flush_tlb_all(); -} - -/* - * Set new cache mode for some kernel address space. - * The caller must push data for that range itself, if such data may already - * be in the cache. - */ -void kernel_set_cachemode(void *addr, unsigned long size, int cmode) -{ - unsigned long virtaddr = (unsigned long)addr; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - if (CPU_IS_040_OR_060) { - switch (cmode) { - case IOMAP_FULL_CACHING: - cmode = _PAGE_CACHE040; - break; - case IOMAP_NOCACHE_SER: - default: - cmode = _PAGE_NOCACHE_S; - break; - case IOMAP_NOCACHE_NONSER: - cmode = _PAGE_NOCACHE; - break; - case IOMAP_WRITETHROUGH: - cmode = _PAGE_CACHE040W; - break; - } - } else { - switch (cmode) { - case IOMAP_NOCACHE_SER: - case IOMAP_NOCACHE_NONSER: - default: - cmode = _PAGE_NOCACHE030; - break; - case IOMAP_FULL_CACHING: - case IOMAP_WRITETHROUGH: - cmode = 0; - } - } - - while ((long)size > 0) { - pgd_dir = pgd_offset_k(virtaddr); - if (pgd_bad(*pgd_dir)) { - printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); - pgd_clear(pgd_dir); - return; - } - pmd_dir = pmd_offset(pgd_dir, virtaddr); - - if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & 15; - - if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { - pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] & - _CACHEMASK040) | cmode; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - continue; - } - } - - if (pmd_bad(*pmd_dir)) { - printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); - pmd_clear(pmd_dir); - return; - } - pte_dir = pte_offset_kernel(pmd_dir, virtaddr); - - pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode; - virtaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - flush_tlb_all(); -} -EXPORT_SYMBOL(kernel_set_cachemode); diff --git a/trunk/arch/m68k/mm/kmap_mm.c b/trunk/arch/m68k/mm/kmap_mm.c new file mode 100644 index 000000000000..69345849454b --- /dev/null +++ b/trunk/arch/m68k/mm/kmap_mm.c @@ -0,0 +1,367 @@ +/* + * linux/arch/m68k/mm/kmap.c + * + * Copyright (C) 1997 Roman Hodek + * + * 10/01/99 cleaned up the code and changing to the same interface + * used by other architectures /Roman Zippel + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#define PTRTREESIZE (256*1024) + +/* + * For 040/060 we can use the virtual memory area like other architectures, + * but for 020/030 we want to use early termination page descriptor and we + * can't mix this with normal page descriptors, so we have to copy that code + * (mm/vmalloc.c) and return appriorate aligned addresses. + */ + +#ifdef CPU_M68040_OR_M68060_ONLY + +#define IO_SIZE PAGE_SIZE + +static inline struct vm_struct *get_io_area(unsigned long size) +{ + return get_vm_area(size, VM_IOREMAP); +} + + +static inline void free_io_area(void *addr) +{ + vfree((void *)(PAGE_MASK & (unsigned long)addr)); +} + +#else + +#define IO_SIZE (256*1024) + +static struct vm_struct *iolist; + +static struct vm_struct *get_io_area(unsigned long size) +{ + unsigned long addr; + struct vm_struct **p, *tmp, *area; + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; + addr = KMAP_START; + for (p = &iolist; (tmp = *p) ; p = &tmp->next) { + if (size + addr < (unsigned long)tmp->addr) + break; + if (addr > KMAP_END-size) { + kfree(area); + return NULL; + } + addr = tmp->size + (unsigned long)tmp->addr; + } + area->addr = (void *)addr; + area->size = size + IO_SIZE; + area->next = *p; + *p = area; + return area; +} + +static inline void free_io_area(void *addr) +{ + struct vm_struct **p, *tmp; + + if (!addr) + return; + addr = (void *)((unsigned long)addr & -IO_SIZE); + for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == addr) { + *p = tmp->next; + __iounmap(tmp->addr, tmp->size); + kfree(tmp); + return; + } + } +} + +#endif + +/* + * Map some physical address range into the kernel address space. + */ +/* Rewritten by Andreas Schwab to remove all races. */ + +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +{ + struct vm_struct *area; + unsigned long virtaddr, retaddr; + long offset; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + /* + * Don't allow mappings that wrap.. + */ + if (!size || physaddr > (unsigned long)(-size)) + return NULL; + +#ifdef CONFIG_AMIGA + if (MACH_IS_AMIGA) { + if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) + && (cacheflag == IOMAP_NOCACHE_SER)) + return (void __iomem *)physaddr; + } +#endif + +#ifdef DEBUG + printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); +#endif + /* + * Mappings have to be aligned + */ + offset = physaddr & (IO_SIZE - 1); + physaddr &= -IO_SIZE; + size = (size + offset + IO_SIZE - 1) & -IO_SIZE; + + /* + * Ok, go for it.. + */ + area = get_io_area(size); + if (!area) + return NULL; + + virtaddr = (unsigned long)area->addr; + retaddr = virtaddr + offset; +#ifdef DEBUG + printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr); +#endif + + /* + * add cache and table flags to physical address + */ + if (CPU_IS_040_OR_060) { + physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 | + _PAGE_ACCESSED | _PAGE_DIRTY); + switch (cacheflag) { + case IOMAP_FULL_CACHING: + physaddr |= _PAGE_CACHE040; + break; + case IOMAP_NOCACHE_SER: + default: + physaddr |= _PAGE_NOCACHE_S; + break; + case IOMAP_NOCACHE_NONSER: + physaddr |= _PAGE_NOCACHE; + break; + case IOMAP_WRITETHROUGH: + physaddr |= _PAGE_CACHE040W; + break; + } + } else { + physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + switch (cacheflag) { + case IOMAP_NOCACHE_SER: + case IOMAP_NOCACHE_NONSER: + default: + physaddr |= _PAGE_NOCACHE030; + break; + case IOMAP_FULL_CACHING: + case IOMAP_WRITETHROUGH: + break; + } + } + + while ((long)size > 0) { +#ifdef DEBUG + if (!(virtaddr & (PTRTREESIZE-1))) + printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); +#endif + pgd_dir = pgd_offset_k(virtaddr); + pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr); + if (!pmd_dir) { + printk("ioremap: no mem for pmd_dir\n"); + return NULL; + } + + if (CPU_IS_020_OR_030) { + pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; + physaddr += PTRTREESIZE; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + } else { + pte_dir = pte_alloc_kernel(pmd_dir, virtaddr); + if (!pte_dir) { + printk("ioremap: no mem for pte_dir\n"); + return NULL; + } + + pte_val(*pte_dir) = physaddr; + virtaddr += PAGE_SIZE; + physaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + } +#ifdef DEBUG + printk("\n"); +#endif + flush_tlb_all(); + + return (void __iomem *)retaddr; +} +EXPORT_SYMBOL(__ioremap); + +/* + * Unmap a ioremap()ed region again + */ +void iounmap(void __iomem *addr) +{ +#ifdef CONFIG_AMIGA + if ((!MACH_IS_AMIGA) || + (((unsigned long)addr < 0x40000000) || + ((unsigned long)addr > 0x60000000))) + free_io_area((__force void *)addr); +#else + free_io_area((__force void *)addr); +#endif +} +EXPORT_SYMBOL(iounmap); + +/* + * __iounmap unmaps nearly everything, so be careful + * it doesn't free currently pointer/page tables anymore but it + * wans't used anyway and might be added later. + */ +void __iounmap(void *addr, unsigned long size) +{ + unsigned long virtaddr = (unsigned long)addr; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + while ((long)size > 0) { + pgd_dir = pgd_offset_k(virtaddr); + if (pgd_bad(*pgd_dir)) { + printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); + pgd_clear(pgd_dir); + return; + } + pmd_dir = pmd_offset(pgd_dir, virtaddr); + + if (CPU_IS_020_OR_030) { + int pmd_off = (virtaddr/PTRTREESIZE) & 15; + int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; + + if (pmd_type == _PAGE_PRESENT) { + pmd_dir->pmd[pmd_off] = 0; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + continue; + } else if (pmd_type == 0) + continue; + } + + if (pmd_bad(*pmd_dir)) { + printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); + pmd_clear(pmd_dir); + return; + } + pte_dir = pte_offset_kernel(pmd_dir, virtaddr); + + pte_val(*pte_dir) = 0; + virtaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + flush_tlb_all(); +} + +/* + * Set new cache mode for some kernel address space. + * The caller must push data for that range itself, if such data may already + * be in the cache. + */ +void kernel_set_cachemode(void *addr, unsigned long size, int cmode) +{ + unsigned long virtaddr = (unsigned long)addr; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + if (CPU_IS_040_OR_060) { + switch (cmode) { + case IOMAP_FULL_CACHING: + cmode = _PAGE_CACHE040; + break; + case IOMAP_NOCACHE_SER: + default: + cmode = _PAGE_NOCACHE_S; + break; + case IOMAP_NOCACHE_NONSER: + cmode = _PAGE_NOCACHE; + break; + case IOMAP_WRITETHROUGH: + cmode = _PAGE_CACHE040W; + break; + } + } else { + switch (cmode) { + case IOMAP_NOCACHE_SER: + case IOMAP_NOCACHE_NONSER: + default: + cmode = _PAGE_NOCACHE030; + break; + case IOMAP_FULL_CACHING: + case IOMAP_WRITETHROUGH: + cmode = 0; + } + } + + while ((long)size > 0) { + pgd_dir = pgd_offset_k(virtaddr); + if (pgd_bad(*pgd_dir)) { + printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); + pgd_clear(pgd_dir); + return; + } + pmd_dir = pmd_offset(pgd_dir, virtaddr); + + if (CPU_IS_020_OR_030) { + int pmd_off = (virtaddr/PTRTREESIZE) & 15; + + if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { + pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] & + _CACHEMASK040) | cmode; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + continue; + } + } + + if (pmd_bad(*pmd_dir)) { + printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); + pmd_clear(pmd_dir); + return; + } + pte_dir = pte_offset_kernel(pmd_dir, virtaddr); + + pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode; + virtaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + flush_tlb_all(); +} +EXPORT_SYMBOL(kernel_set_cachemode); diff --git a/trunk/arch/m68knommu/mm/kmap.c b/trunk/arch/m68k/mm/kmap_no.c similarity index 100% rename from trunk/arch/m68knommu/mm/kmap.c rename to trunk/arch/m68k/mm/kmap_no.c diff --git a/trunk/arch/m68knommu/platform/5206/Makefile b/trunk/arch/m68k/platform/5206/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5206/Makefile rename to trunk/arch/m68k/platform/5206/Makefile diff --git a/trunk/arch/m68knommu/platform/5206/config.c b/trunk/arch/m68k/platform/5206/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5206/config.c rename to trunk/arch/m68k/platform/5206/config.c diff --git a/trunk/arch/m68knommu/platform/5206/gpio.c b/trunk/arch/m68k/platform/5206/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5206/gpio.c rename to trunk/arch/m68k/platform/5206/gpio.c diff --git a/trunk/arch/m68knommu/platform/5206e/Makefile b/trunk/arch/m68k/platform/5206e/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5206e/Makefile rename to trunk/arch/m68k/platform/5206e/Makefile diff --git a/trunk/arch/m68knommu/platform/5206e/config.c b/trunk/arch/m68k/platform/5206e/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5206e/config.c rename to trunk/arch/m68k/platform/5206e/config.c diff --git a/trunk/arch/m68knommu/platform/5206e/gpio.c b/trunk/arch/m68k/platform/5206e/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5206e/gpio.c rename to trunk/arch/m68k/platform/5206e/gpio.c diff --git a/trunk/arch/m68knommu/platform/520x/Makefile b/trunk/arch/m68k/platform/520x/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/520x/Makefile rename to trunk/arch/m68k/platform/520x/Makefile diff --git a/trunk/arch/m68knommu/platform/520x/config.c b/trunk/arch/m68k/platform/520x/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/520x/config.c rename to trunk/arch/m68k/platform/520x/config.c diff --git a/trunk/arch/m68knommu/platform/520x/gpio.c b/trunk/arch/m68k/platform/520x/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/520x/gpio.c rename to trunk/arch/m68k/platform/520x/gpio.c diff --git a/trunk/arch/m68knommu/platform/523x/Makefile b/trunk/arch/m68k/platform/523x/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/523x/Makefile rename to trunk/arch/m68k/platform/523x/Makefile diff --git a/trunk/arch/m68knommu/platform/523x/config.c b/trunk/arch/m68k/platform/523x/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/523x/config.c rename to trunk/arch/m68k/platform/523x/config.c diff --git a/trunk/arch/m68knommu/platform/523x/gpio.c b/trunk/arch/m68k/platform/523x/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/523x/gpio.c rename to trunk/arch/m68k/platform/523x/gpio.c diff --git a/trunk/arch/m68knommu/platform/5249/Makefile b/trunk/arch/m68k/platform/5249/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5249/Makefile rename to trunk/arch/m68k/platform/5249/Makefile diff --git a/trunk/arch/m68knommu/platform/5249/config.c b/trunk/arch/m68k/platform/5249/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5249/config.c rename to trunk/arch/m68k/platform/5249/config.c diff --git a/trunk/arch/m68knommu/platform/5249/gpio.c b/trunk/arch/m68k/platform/5249/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5249/gpio.c rename to trunk/arch/m68k/platform/5249/gpio.c diff --git a/trunk/arch/m68knommu/platform/5249/intc2.c b/trunk/arch/m68k/platform/5249/intc2.c similarity index 100% rename from trunk/arch/m68knommu/platform/5249/intc2.c rename to trunk/arch/m68k/platform/5249/intc2.c diff --git a/trunk/arch/m68knommu/platform/5272/Makefile b/trunk/arch/m68k/platform/5272/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5272/Makefile rename to trunk/arch/m68k/platform/5272/Makefile diff --git a/trunk/arch/m68knommu/platform/5272/config.c b/trunk/arch/m68k/platform/5272/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5272/config.c rename to trunk/arch/m68k/platform/5272/config.c diff --git a/trunk/arch/m68knommu/platform/5272/gpio.c b/trunk/arch/m68k/platform/5272/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5272/gpio.c rename to trunk/arch/m68k/platform/5272/gpio.c diff --git a/trunk/arch/m68knommu/platform/5272/intc.c b/trunk/arch/m68k/platform/5272/intc.c similarity index 100% rename from trunk/arch/m68knommu/platform/5272/intc.c rename to trunk/arch/m68k/platform/5272/intc.c diff --git a/trunk/arch/m68knommu/platform/527x/Makefile b/trunk/arch/m68k/platform/527x/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/527x/Makefile rename to trunk/arch/m68k/platform/527x/Makefile diff --git a/trunk/arch/m68knommu/platform/527x/config.c b/trunk/arch/m68k/platform/527x/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/527x/config.c rename to trunk/arch/m68k/platform/527x/config.c diff --git a/trunk/arch/m68knommu/platform/527x/gpio.c b/trunk/arch/m68k/platform/527x/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/527x/gpio.c rename to trunk/arch/m68k/platform/527x/gpio.c diff --git a/trunk/arch/m68knommu/platform/528x/Makefile b/trunk/arch/m68k/platform/528x/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/528x/Makefile rename to trunk/arch/m68k/platform/528x/Makefile diff --git a/trunk/arch/m68knommu/platform/528x/config.c b/trunk/arch/m68k/platform/528x/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/528x/config.c rename to trunk/arch/m68k/platform/528x/config.c diff --git a/trunk/arch/m68knommu/platform/528x/gpio.c b/trunk/arch/m68k/platform/528x/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/528x/gpio.c rename to trunk/arch/m68k/platform/528x/gpio.c diff --git a/trunk/arch/m68knommu/platform/5307/Makefile b/trunk/arch/m68k/platform/5307/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5307/Makefile rename to trunk/arch/m68k/platform/5307/Makefile diff --git a/trunk/arch/m68knommu/platform/5307/config.c b/trunk/arch/m68k/platform/5307/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5307/config.c rename to trunk/arch/m68k/platform/5307/config.c diff --git a/trunk/arch/m68knommu/platform/5307/gpio.c b/trunk/arch/m68k/platform/5307/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5307/gpio.c rename to trunk/arch/m68k/platform/5307/gpio.c diff --git a/trunk/arch/m68knommu/platform/5307/nettel.c b/trunk/arch/m68k/platform/5307/nettel.c similarity index 100% rename from trunk/arch/m68knommu/platform/5307/nettel.c rename to trunk/arch/m68k/platform/5307/nettel.c diff --git a/trunk/arch/m68knommu/platform/532x/Makefile b/trunk/arch/m68k/platform/532x/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/532x/Makefile rename to trunk/arch/m68k/platform/532x/Makefile diff --git a/trunk/arch/m68knommu/platform/532x/config.c b/trunk/arch/m68k/platform/532x/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/532x/config.c rename to trunk/arch/m68k/platform/532x/config.c diff --git a/trunk/arch/m68knommu/platform/532x/gpio.c b/trunk/arch/m68k/platform/532x/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/532x/gpio.c rename to trunk/arch/m68k/platform/532x/gpio.c diff --git a/trunk/arch/m68knommu/platform/5407/Makefile b/trunk/arch/m68k/platform/5407/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/5407/Makefile rename to trunk/arch/m68k/platform/5407/Makefile diff --git a/trunk/arch/m68knommu/platform/5407/config.c b/trunk/arch/m68k/platform/5407/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/5407/config.c rename to trunk/arch/m68k/platform/5407/config.c diff --git a/trunk/arch/m68knommu/platform/5407/gpio.c b/trunk/arch/m68k/platform/5407/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/5407/gpio.c rename to trunk/arch/m68k/platform/5407/gpio.c diff --git a/trunk/arch/m68knommu/platform/54xx/Makefile b/trunk/arch/m68k/platform/54xx/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/54xx/Makefile rename to trunk/arch/m68k/platform/54xx/Makefile diff --git a/trunk/arch/m68knommu/platform/54xx/config.c b/trunk/arch/m68k/platform/54xx/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/54xx/config.c rename to trunk/arch/m68k/platform/54xx/config.c diff --git a/trunk/arch/m68knommu/platform/54xx/firebee.c b/trunk/arch/m68k/platform/54xx/firebee.c similarity index 100% rename from trunk/arch/m68knommu/platform/54xx/firebee.c rename to trunk/arch/m68k/platform/54xx/firebee.c diff --git a/trunk/arch/m68knommu/platform/68328/Makefile b/trunk/arch/m68k/platform/68328/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/68328/Makefile rename to trunk/arch/m68k/platform/68328/Makefile diff --git a/trunk/arch/m68knommu/platform/68328/bootlogo.h b/trunk/arch/m68k/platform/68328/bootlogo.h similarity index 100% rename from trunk/arch/m68knommu/platform/68328/bootlogo.h rename to trunk/arch/m68k/platform/68328/bootlogo.h diff --git a/trunk/arch/m68knommu/platform/68328/bootlogo.pl b/trunk/arch/m68k/platform/68328/bootlogo.pl similarity index 100% rename from trunk/arch/m68knommu/platform/68328/bootlogo.pl rename to trunk/arch/m68k/platform/68328/bootlogo.pl diff --git a/trunk/arch/m68knommu/platform/68328/config.c b/trunk/arch/m68k/platform/68328/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/68328/config.c rename to trunk/arch/m68k/platform/68328/config.c diff --git a/trunk/arch/m68knommu/platform/68328/entry.S b/trunk/arch/m68k/platform/68328/entry.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/entry.S rename to trunk/arch/m68k/platform/68328/entry.S diff --git a/trunk/arch/m68knommu/platform/68328/head-de2.S b/trunk/arch/m68k/platform/68328/head-de2.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/head-de2.S rename to trunk/arch/m68k/platform/68328/head-de2.S diff --git a/trunk/arch/m68knommu/platform/68328/head-pilot.S b/trunk/arch/m68k/platform/68328/head-pilot.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/head-pilot.S rename to trunk/arch/m68k/platform/68328/head-pilot.S diff --git a/trunk/arch/m68knommu/platform/68328/head-ram.S b/trunk/arch/m68k/platform/68328/head-ram.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/head-ram.S rename to trunk/arch/m68k/platform/68328/head-ram.S diff --git a/trunk/arch/m68knommu/platform/68328/head-rom.S b/trunk/arch/m68k/platform/68328/head-rom.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/head-rom.S rename to trunk/arch/m68k/platform/68328/head-rom.S diff --git a/trunk/arch/m68knommu/platform/68328/ints.c b/trunk/arch/m68k/platform/68328/ints.c similarity index 100% rename from trunk/arch/m68knommu/platform/68328/ints.c rename to trunk/arch/m68k/platform/68328/ints.c diff --git a/trunk/arch/m68knommu/platform/68328/romvec.S b/trunk/arch/m68k/platform/68328/romvec.S similarity index 100% rename from trunk/arch/m68knommu/platform/68328/romvec.S rename to trunk/arch/m68k/platform/68328/romvec.S diff --git a/trunk/arch/m68knommu/platform/68328/timers.c b/trunk/arch/m68k/platform/68328/timers.c similarity index 100% rename from trunk/arch/m68knommu/platform/68328/timers.c rename to trunk/arch/m68k/platform/68328/timers.c diff --git a/trunk/arch/m68knommu/platform/68360/Makefile b/trunk/arch/m68k/platform/68360/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/68360/Makefile rename to trunk/arch/m68k/platform/68360/Makefile diff --git a/trunk/arch/m68knommu/platform/68360/commproc.c b/trunk/arch/m68k/platform/68360/commproc.c similarity index 100% rename from trunk/arch/m68knommu/platform/68360/commproc.c rename to trunk/arch/m68k/platform/68360/commproc.c diff --git a/trunk/arch/m68knommu/platform/68360/config.c b/trunk/arch/m68k/platform/68360/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/68360/config.c rename to trunk/arch/m68k/platform/68360/config.c diff --git a/trunk/arch/m68knommu/platform/68360/entry.S b/trunk/arch/m68k/platform/68360/entry.S similarity index 100% rename from trunk/arch/m68knommu/platform/68360/entry.S rename to trunk/arch/m68k/platform/68360/entry.S diff --git a/trunk/arch/m68knommu/platform/68360/head-ram.S b/trunk/arch/m68k/platform/68360/head-ram.S similarity index 100% rename from trunk/arch/m68knommu/platform/68360/head-ram.S rename to trunk/arch/m68k/platform/68360/head-ram.S diff --git a/trunk/arch/m68knommu/platform/68360/head-rom.S b/trunk/arch/m68k/platform/68360/head-rom.S similarity index 100% rename from trunk/arch/m68knommu/platform/68360/head-rom.S rename to trunk/arch/m68k/platform/68360/head-rom.S diff --git a/trunk/arch/m68knommu/platform/68360/ints.c b/trunk/arch/m68k/platform/68360/ints.c similarity index 100% rename from trunk/arch/m68knommu/platform/68360/ints.c rename to trunk/arch/m68k/platform/68360/ints.c diff --git a/trunk/arch/m68knommu/platform/68EZ328/Makefile b/trunk/arch/m68k/platform/68EZ328/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/68EZ328/Makefile rename to trunk/arch/m68k/platform/68EZ328/Makefile diff --git a/trunk/arch/m68knommu/platform/68EZ328/bootlogo.h b/trunk/arch/m68k/platform/68EZ328/bootlogo.h similarity index 100% rename from trunk/arch/m68knommu/platform/68EZ328/bootlogo.h rename to trunk/arch/m68k/platform/68EZ328/bootlogo.h diff --git a/trunk/arch/m68knommu/platform/68EZ328/config.c b/trunk/arch/m68k/platform/68EZ328/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/68EZ328/config.c rename to trunk/arch/m68k/platform/68EZ328/config.c diff --git a/trunk/arch/m68knommu/platform/68VZ328/Makefile b/trunk/arch/m68k/platform/68VZ328/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/68VZ328/Makefile rename to trunk/arch/m68k/platform/68VZ328/Makefile diff --git a/trunk/arch/m68knommu/platform/68VZ328/config.c b/trunk/arch/m68k/platform/68VZ328/config.c similarity index 100% rename from trunk/arch/m68knommu/platform/68VZ328/config.c rename to trunk/arch/m68k/platform/68VZ328/config.c diff --git a/trunk/arch/m68knommu/platform/Makefile b/trunk/arch/m68k/platform/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/Makefile rename to trunk/arch/m68k/platform/Makefile diff --git a/trunk/arch/m68knommu/platform/coldfire/Makefile b/trunk/arch/m68k/platform/coldfire/Makefile similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/Makefile rename to trunk/arch/m68k/platform/coldfire/Makefile diff --git a/trunk/arch/m68knommu/platform/coldfire/cache.c b/trunk/arch/m68k/platform/coldfire/cache.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/cache.c rename to trunk/arch/m68k/platform/coldfire/cache.c diff --git a/trunk/arch/m68knommu/platform/coldfire/clk.c b/trunk/arch/m68k/platform/coldfire/clk.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/clk.c rename to trunk/arch/m68k/platform/coldfire/clk.c diff --git a/trunk/arch/m68knommu/platform/coldfire/dma.c b/trunk/arch/m68k/platform/coldfire/dma.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/dma.c rename to trunk/arch/m68k/platform/coldfire/dma.c diff --git a/trunk/arch/m68knommu/platform/coldfire/dma_timer.c b/trunk/arch/m68k/platform/coldfire/dma_timer.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/dma_timer.c rename to trunk/arch/m68k/platform/coldfire/dma_timer.c diff --git a/trunk/arch/m68knommu/platform/coldfire/entry.S b/trunk/arch/m68k/platform/coldfire/entry.S similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/entry.S rename to trunk/arch/m68k/platform/coldfire/entry.S diff --git a/trunk/arch/m68knommu/platform/coldfire/gpio.c b/trunk/arch/m68k/platform/coldfire/gpio.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/gpio.c rename to trunk/arch/m68k/platform/coldfire/gpio.c diff --git a/trunk/arch/m68knommu/platform/coldfire/head.S b/trunk/arch/m68k/platform/coldfire/head.S similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/head.S rename to trunk/arch/m68k/platform/coldfire/head.S diff --git a/trunk/arch/m68knommu/platform/coldfire/intc-2.c b/trunk/arch/m68k/platform/coldfire/intc-2.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/intc-2.c rename to trunk/arch/m68k/platform/coldfire/intc-2.c diff --git a/trunk/arch/m68knommu/platform/coldfire/intc-simr.c b/trunk/arch/m68k/platform/coldfire/intc-simr.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/intc-simr.c rename to trunk/arch/m68k/platform/coldfire/intc-simr.c diff --git a/trunk/arch/m68knommu/platform/coldfire/intc.c b/trunk/arch/m68k/platform/coldfire/intc.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/intc.c rename to trunk/arch/m68k/platform/coldfire/intc.c diff --git a/trunk/arch/m68knommu/platform/coldfire/pinmux.c b/trunk/arch/m68k/platform/coldfire/pinmux.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/pinmux.c rename to trunk/arch/m68k/platform/coldfire/pinmux.c diff --git a/trunk/arch/m68knommu/platform/coldfire/pit.c b/trunk/arch/m68k/platform/coldfire/pit.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/pit.c rename to trunk/arch/m68k/platform/coldfire/pit.c diff --git a/trunk/arch/m68knommu/platform/coldfire/sltimers.c b/trunk/arch/m68k/platform/coldfire/sltimers.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/sltimers.c rename to trunk/arch/m68k/platform/coldfire/sltimers.c diff --git a/trunk/arch/m68knommu/platform/coldfire/timers.c b/trunk/arch/m68k/platform/coldfire/timers.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/timers.c rename to trunk/arch/m68k/platform/coldfire/timers.c diff --git a/trunk/arch/m68knommu/platform/coldfire/vectors.c b/trunk/arch/m68k/platform/coldfire/vectors.c similarity index 100% rename from trunk/arch/m68knommu/platform/coldfire/vectors.c rename to trunk/arch/m68k/platform/coldfire/vectors.c diff --git a/trunk/arch/m68knommu/Kconfig.debug b/trunk/arch/m68knommu/Kconfig.debug deleted file mode 100644 index ed6d9a83bfdb..000000000000 --- a/trunk/arch/m68knommu/Kconfig.debug +++ /dev/null @@ -1,35 +0,0 @@ -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config FULLDEBUG - bool "Full Symbolic/Source Debugging support" - help - Enable debugging symbols on kernel build. - -config HIGHPROFILE - bool "Use fast second timer for profiling" - depends on COLDFIRE - help - Use a fast secondary clock to produce profiling information. - -config BOOTPARAM - bool 'Compiled-in Kernel Boot Parameter' - -config BOOTPARAM_STRING - string 'Kernel Boot Parameter' - default 'console=ttyS0,19200' - depends on BOOTPARAM - -config NO_KERNEL_MSG - bool "Suppress Kernel BUG Messages" - help - Do not output any debug BUG messages within the kernel. - -config BDM_DISABLE - bool "Disable BDM signals" - depends on (EXPERIMENTAL && COLDFIRE) - help - Disable the ColdFire CPU's BDM signals. - -endmenu diff --git a/trunk/arch/m68knommu/defconfig b/trunk/arch/m68knommu/defconfig deleted file mode 100644 index 2f5655c577af..000000000000 --- a/trunk/arch/m68knommu/defconfig +++ /dev/null @@ -1,74 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EXPERT=y -# CONFIG_KALLSYMS is not set -# CONFIG_HOTPLUG is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set -# CONFIG_AIO is not set -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_M520x=y -CONFIG_CLOCK_SET=y -CONFIG_CLOCK_FREQ=166666666 -CONFIG_CLOCK_DIV=2 -CONFIG_M5208EVB=y -# CONFIG_4KSTACKS is not set -CONFIG_RAMBASE=0x40000000 -CONFIG_RAMSIZE=0x2000000 -CONFIG_VECTORBASE=0x40000000 -CONFIG_KERNELBASE=0x40020000 -CONFIG_RAM16BIT=y -CONFIG_BINFMT_FLAT=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_RAM=y -CONFIG_MTD_UCLINUX=y -CONFIG_BLK_DEV_RAM=y -# CONFIG_MISC_DEVICES is not set -CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_FEC=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_MCF=y -CONFIG_SERIAL_MCF_BAUDRATE=115200 -CONFIG_SERIAL_MCF_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set -CONFIG_EXT2_FS=y -# CONFIG_FILE_LOCKING is not set -# CONFIG_DNOTIFY is not set -# CONFIG_SYSFS is not set -CONFIG_ROMFS_FS=y -CONFIG_ROMFS_BACKED_BY_MTD=y -# CONFIG_NETWORK_FILESYSTEMS is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_FULLDEBUG=y -CONFIG_BOOTPARAM=y -CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0" diff --git a/trunk/arch/m68knommu/kernel/.gitignore b/trunk/arch/m68knommu/kernel/.gitignore deleted file mode 100644 index c5f676c3c224..000000000000 --- a/trunk/arch/m68knommu/kernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vmlinux.lds diff --git a/trunk/arch/m68knommu/lib/ashldi3.c b/trunk/arch/m68knommu/lib/ashldi3.c deleted file mode 100644 index 008403eb8ce2..000000000000 --- a/trunk/arch/m68knommu/lib/ashldi3.c +++ /dev/null @@ -1,62 +0,0 @@ -/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__ashldi3 (DItype u, word_type b) -{ - DIunion w; - word_type bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof (SItype) * BITS_PER_UNIT) - b; - if (bm <= 0) - { - w.s.low = 0; - w.s.high = (USItype)uu.s.low << -bm; - } - else - { - USItype carries = (USItype)uu.s.low >> bm; - w.s.low = (USItype)uu.s.low << b; - w.s.high = ((USItype)uu.s.high << b) | carries; - } - - return w.ll; -} diff --git a/trunk/arch/m68knommu/lib/lshrdi3.c b/trunk/arch/m68knommu/lib/lshrdi3.c deleted file mode 100644 index 93b1cb6fdee8..000000000000 --- a/trunk/arch/m68knommu/lib/lshrdi3.c +++ /dev/null @@ -1,62 +0,0 @@ -/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ -/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__lshrdi3 (DItype u, word_type b) -{ - DIunion w; - word_type bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof (SItype) * BITS_PER_UNIT) - b; - if (bm <= 0) - { - w.s.high = 0; - w.s.low = (USItype)uu.s.high >> -bm; - } - else - { - USItype carries = (USItype)uu.s.high << bm; - w.s.high = (USItype)uu.s.high >> b; - w.s.low = ((USItype)uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 83aa5fb8e8f1..9905e2e85de4 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -22,7 +22,6 @@ config MIPS select HAVE_DMA_API_DEBUG select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE - select GENERIC_IRQ_SHOW select HAVE_ARCH_JUMP_LABEL menu "Machine selection" @@ -863,9 +862,6 @@ config GPIO_TXX9 config CFE bool -config ARCH_DMA_ADDR_T_64BIT - def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT - config DMA_COHERENT bool diff --git a/trunk/arch/mips/alchemy/common/irq.c b/trunk/arch/mips/alchemy/common/irq.c index 55dd7c888517..9f78ada83b3c 100644 --- a/trunk/arch/mips/alchemy/common/irq.c +++ b/trunk/arch/mips/alchemy/common/irq.c @@ -39,7 +39,7 @@ #include #endif -static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); +static int au1x_ic_settype(unsigned int irq, unsigned int flow_type); /* NOTE on interrupt priorities: The original writers of this code said: * @@ -218,17 +218,17 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = { }; -static void au1x_ic0_unmask(struct irq_data *d) +static void au1x_ic0_unmask(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; au_writel(1 << bit, IC0_MASKSET); au_writel(1 << bit, IC0_WAKESET); au_sync(); } -static void au1x_ic1_unmask(struct irq_data *d) +static void au1x_ic1_unmask(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; au_writel(1 << bit, IC1_MASKSET); au_writel(1 << bit, IC1_WAKESET); @@ -236,31 +236,31 @@ static void au1x_ic1_unmask(struct irq_data *d) * nowhere in the current kernel sources is it disabled. --mlau */ #if defined(CONFIG_MIPS_PB1000) - if (d->irq == AU1000_GPIO15_INT) + if (irq_nr == AU1000_GPIO15_INT) au_writel(0x4000, PB1000_MDR); /* enable int */ #endif au_sync(); } -static void au1x_ic0_mask(struct irq_data *d) +static void au1x_ic0_mask(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; au_writel(1 << bit, IC0_MASKCLR); au_writel(1 << bit, IC0_WAKECLR); au_sync(); } -static void au1x_ic1_mask(struct irq_data *d) +static void au1x_ic1_mask(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; au_writel(1 << bit, IC1_MASKCLR); au_writel(1 << bit, IC1_WAKECLR); au_sync(); } -static void au1x_ic0_ack(struct irq_data *d) +static void au1x_ic0_ack(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; /* * This may assume that we don't get interrupts from @@ -271,9 +271,9 @@ static void au1x_ic0_ack(struct irq_data *d) au_sync(); } -static void au1x_ic1_ack(struct irq_data *d) +static void au1x_ic1_ack(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; /* * This may assume that we don't get interrupts from @@ -284,9 +284,9 @@ static void au1x_ic1_ack(struct irq_data *d) au_sync(); } -static void au1x_ic0_maskack(struct irq_data *d) +static void au1x_ic0_maskack(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; au_writel(1 << bit, IC0_WAKECLR); au_writel(1 << bit, IC0_MASKCLR); @@ -295,9 +295,9 @@ static void au1x_ic0_maskack(struct irq_data *d) au_sync(); } -static void au1x_ic1_maskack(struct irq_data *d) +static void au1x_ic1_maskack(unsigned int irq_nr) { - unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; + unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; au_writel(1 << bit, IC1_WAKECLR); au_writel(1 << bit, IC1_MASKCLR); @@ -306,9 +306,9 @@ static void au1x_ic1_maskack(struct irq_data *d) au_sync(); } -static int au1x_ic1_setwake(struct irq_data *d, unsigned int on) +static int au1x_ic1_setwake(unsigned int irq, unsigned int on) { - int bit = d->irq - AU1000_INTC1_INT_BASE; + int bit = irq - AU1000_INTC1_INT_BASE; unsigned long wakemsk, flags; /* only GPIO 0-7 can act as wakeup source. Fortunately these @@ -336,30 +336,28 @@ static int au1x_ic1_setwake(struct irq_data *d, unsigned int on) */ static struct irq_chip au1x_ic0_chip = { .name = "Alchemy-IC0", - .irq_ack = au1x_ic0_ack, - .irq_mask = au1x_ic0_mask, - .irq_mask_ack = au1x_ic0_maskack, - .irq_unmask = au1x_ic0_unmask, - .irq_set_type = au1x_ic_settype, + .ack = au1x_ic0_ack, + .mask = au1x_ic0_mask, + .mask_ack = au1x_ic0_maskack, + .unmask = au1x_ic0_unmask, + .set_type = au1x_ic_settype, }; static struct irq_chip au1x_ic1_chip = { .name = "Alchemy-IC1", - .irq_ack = au1x_ic1_ack, - .irq_mask = au1x_ic1_mask, - .irq_mask_ack = au1x_ic1_maskack, - .irq_unmask = au1x_ic1_unmask, - .irq_set_type = au1x_ic_settype, - .irq_set_wake = au1x_ic1_setwake, + .ack = au1x_ic1_ack, + .mask = au1x_ic1_mask, + .mask_ack = au1x_ic1_maskack, + .unmask = au1x_ic1_unmask, + .set_type = au1x_ic_settype, + .set_wake = au1x_ic1_setwake, }; -static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) +static int au1x_ic_settype(unsigned int irq, unsigned int flow_type) { struct irq_chip *chip; unsigned long icr[6]; - unsigned int bit, ic, irq = d->irq; - irq_flow_handler_t handler = NULL; - unsigned char *name = NULL; + unsigned int bit, ic; int ret; if (irq >= AU1000_INTC1_INT_BASE) { @@ -389,47 +387,47 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) au_writel(1 << bit, icr[5]); au_writel(1 << bit, icr[4]); au_writel(1 << bit, icr[0]); - handler = handle_edge_irq; - name = "riseedge"; + set_irq_chip_and_handler_name(irq, chip, + handle_edge_irq, "riseedge"); break; case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */ au_writel(1 << bit, icr[5]); au_writel(1 << bit, icr[1]); au_writel(1 << bit, icr[3]); - handler = handle_edge_irq; - name = "falledge"; + set_irq_chip_and_handler_name(irq, chip, + handle_edge_irq, "falledge"); break; case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */ au_writel(1 << bit, icr[5]); au_writel(1 << bit, icr[1]); au_writel(1 << bit, icr[0]); - handler = handle_edge_irq; - name = "bothedge"; + set_irq_chip_and_handler_name(irq, chip, + handle_edge_irq, "bothedge"); break; case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */ au_writel(1 << bit, icr[2]); au_writel(1 << bit, icr[4]); au_writel(1 << bit, icr[0]); - handler = handle_level_irq; - name = "hilevel"; + set_irq_chip_and_handler_name(irq, chip, + handle_level_irq, "hilevel"); break; case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */ au_writel(1 << bit, icr[2]); au_writel(1 << bit, icr[1]); au_writel(1 << bit, icr[3]); - handler = handle_level_irq; - name = "lowlevel"; + set_irq_chip_and_handler_name(irq, chip, + handle_level_irq, "lowlevel"); break; case IRQ_TYPE_NONE: /* 0:0:0 */ au_writel(1 << bit, icr[5]); au_writel(1 << bit, icr[4]); au_writel(1 << bit, icr[3]); + /* set at least chip so we can call set_irq_type() on it */ + set_irq_chip(irq, chip); break; default: ret = -EINVAL; } - __irq_set_chip_handler_name_locked(d->irq, chip, handler, name); - au_sync(); return ret; @@ -506,11 +504,11 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) */ for (i = AU1000_INTC0_INT_BASE; (i < AU1000_INTC0_INT_BASE + 32); i++) - au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); + au1x_ic_settype(i, IRQ_TYPE_NONE); for (i = AU1000_INTC1_INT_BASE; (i < AU1000_INTC1_INT_BASE + 32); i++) - au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); + au1x_ic_settype(i, IRQ_TYPE_NONE); /* * Initialize IC0, which is fixed per processor. @@ -528,7 +526,7 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) au_writel(1 << bit, IC0_ASSIGNSET); } - au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type); + au1x_ic_settype(irq_nr, map->im_type); ++map; } diff --git a/trunk/arch/mips/alchemy/devboards/bcsr.c b/trunk/arch/mips/alchemy/devboards/bcsr.c index f91c43a7d5dc..c52af8821da0 100644 --- a/trunk/arch/mips/alchemy/devboards/bcsr.c +++ b/trunk/arch/mips/alchemy/devboards/bcsr.c @@ -97,26 +97,26 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) * CPLD generates tons of spurious interrupts (at least on my DB1200). * -- mlau */ -static void bcsr_irq_mask(struct irq_data *d) +static void bcsr_irq_mask(unsigned int irq_nr) { - unsigned short v = 1 << (d->irq - bcsr_csc_base); + unsigned short v = 1 << (irq_nr - bcsr_csc_base); __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); wmb(); } -static void bcsr_irq_maskack(struct irq_data *d) +static void bcsr_irq_maskack(unsigned int irq_nr) { - unsigned short v = 1 << (d->irq - bcsr_csc_base); + unsigned short v = 1 << (irq_nr - bcsr_csc_base); __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT); /* ack */ wmb(); } -static void bcsr_irq_unmask(struct irq_data *d) +static void bcsr_irq_unmask(unsigned int irq_nr) { - unsigned short v = 1 << (d->irq - bcsr_csc_base); + unsigned short v = 1 << (irq_nr - bcsr_csc_base); __raw_writew(v, bcsr_virt + BCSR_REG_INTSET); __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET); wmb(); @@ -124,9 +124,9 @@ static void bcsr_irq_unmask(struct irq_data *d) static struct irq_chip bcsr_irq_type = { .name = "CPLD", - .irq_mask = bcsr_irq_mask, - .irq_mask_ack = bcsr_irq_maskack, - .irq_unmask = bcsr_irq_unmask, + .mask = bcsr_irq_mask, + .mask_ack = bcsr_irq_maskack, + .unmask = bcsr_irq_unmask, }; void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq) diff --git a/trunk/arch/mips/ar7/irq.c b/trunk/arch/mips/ar7/irq.c index a6484b60642f..4ec2642c568f 100644 --- a/trunk/arch/mips/ar7/irq.c +++ b/trunk/arch/mips/ar7/irq.c @@ -49,51 +49,51 @@ static int ar7_irq_base; -static void ar7_unmask_irq(struct irq_data *d) +static void ar7_unmask_irq(unsigned int irq) { - writel(1 << ((d->irq - ar7_irq_base) % 32), - REG(ESR_OFFSET(d->irq - ar7_irq_base))); + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ESR_OFFSET(irq - ar7_irq_base))); } -static void ar7_mask_irq(struct irq_data *d) +static void ar7_mask_irq(unsigned int irq) { - writel(1 << ((d->irq - ar7_irq_base) % 32), - REG(ECR_OFFSET(d->irq - ar7_irq_base))); + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ECR_OFFSET(irq - ar7_irq_base))); } -static void ar7_ack_irq(struct irq_data *d) +static void ar7_ack_irq(unsigned int irq) { - writel(1 << ((d->irq - ar7_irq_base) % 32), - REG(CR_OFFSET(d->irq - ar7_irq_base))); + writel(1 << ((irq - ar7_irq_base) % 32), + REG(CR_OFFSET(irq - ar7_irq_base))); } -static void ar7_unmask_sec_irq(struct irq_data *d) +static void ar7_unmask_sec_irq(unsigned int irq) { - writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); } -static void ar7_mask_sec_irq(struct irq_data *d) +static void ar7_mask_sec_irq(unsigned int irq) { - writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); } -static void ar7_ack_sec_irq(struct irq_data *d) +static void ar7_ack_sec_irq(unsigned int irq) { - writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); } static struct irq_chip ar7_irq_type = { .name = "AR7", - .irq_unmask = ar7_unmask_irq, - .irq_mask = ar7_mask_irq, - .irq_ack = ar7_ack_irq + .unmask = ar7_unmask_irq, + .mask = ar7_mask_irq, + .ack = ar7_ack_irq }; static struct irq_chip ar7_sec_irq_type = { .name = "AR7", - .irq_unmask = ar7_unmask_sec_irq, - .irq_mask = ar7_mask_sec_irq, - .irq_ack = ar7_ack_sec_irq, + .unmask = ar7_unmask_sec_irq, + .mask = ar7_mask_sec_irq, + .ack = ar7_ack_sec_irq, }; static struct irqaction ar7_cascade_action = { diff --git a/trunk/arch/mips/ath79/irq.c b/trunk/arch/mips/ath79/irq.c index 7c02bc948a31..1bf7f719ba53 100644 --- a/trunk/arch/mips/ath79/irq.c +++ b/trunk/arch/mips/ath79/irq.c @@ -62,12 +62,13 @@ static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) spurious_interrupt(); } -static void ar71xx_misc_irq_unmask(struct irq_data *d) +static void ar71xx_misc_irq_unmask(unsigned int irq) { - unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; void __iomem *base = ath79_reset_base; u32 t; + irq -= ATH79_MISC_IRQ_BASE; + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); @@ -75,12 +76,13 @@ static void ar71xx_misc_irq_unmask(struct irq_data *d) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); } -static void ar71xx_misc_irq_mask(struct irq_data *d) +static void ar71xx_misc_irq_mask(unsigned int irq) { - unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; void __iomem *base = ath79_reset_base; u32 t; + irq -= ATH79_MISC_IRQ_BASE; + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); @@ -88,12 +90,13 @@ static void ar71xx_misc_irq_mask(struct irq_data *d) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); } -static void ar724x_misc_irq_ack(struct irq_data *d) +static void ar724x_misc_irq_ack(unsigned int irq) { - unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; void __iomem *base = ath79_reset_base; u32 t; + irq -= ATH79_MISC_IRQ_BASE; + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); @@ -103,8 +106,8 @@ static void ar724x_misc_irq_ack(struct irq_data *d) static struct irq_chip ath79_misc_irq_chip = { .name = "MISC", - .irq_unmask = ar71xx_misc_irq_unmask, - .irq_mask = ar71xx_misc_irq_mask, + .unmask = ar71xx_misc_irq_unmask, + .mask = ar71xx_misc_irq_mask, }; static void __init ath79_misc_irq_init(void) @@ -116,14 +119,15 @@ static void __init ath79_misc_irq_init(void) __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); if (soc_is_ar71xx() || soc_is_ar913x()) - ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; + ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask; else if (soc_is_ar724x()) - ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; + ath79_misc_irq_chip.ack = ar724x_misc_irq_ack; else BUG(); for (i = ATH79_MISC_IRQ_BASE; i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) { + irq_desc[i].status = IRQ_DISABLED; set_irq_chip_and_handler(i, &ath79_misc_irq_chip, handle_level_irq); } diff --git a/trunk/arch/mips/bcm63xx/irq.c b/trunk/arch/mips/bcm63xx/irq.c index 1691531aa34d..3be87f2422f0 100644 --- a/trunk/arch/mips/bcm63xx/irq.c +++ b/trunk/arch/mips/bcm63xx/irq.c @@ -76,80 +76,88 @@ asmlinkage void plat_irq_dispatch(void) * internal IRQs operations: only mask/unmask on PERF irq mask * register. */ -static inline void bcm63xx_internal_irq_mask(struct irq_data *d) +static inline void bcm63xx_internal_irq_mask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; + irq -= IRQ_INTERNAL_BASE; mask = bcm_perf_readl(PERF_IRQMASK_REG); mask &= ~(1 << irq); bcm_perf_writel(mask, PERF_IRQMASK_REG); } -static void bcm63xx_internal_irq_unmask(struct irq_data *d) +static void bcm63xx_internal_irq_unmask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; + irq -= IRQ_INTERNAL_BASE; mask = bcm_perf_readl(PERF_IRQMASK_REG); mask |= (1 << irq); bcm_perf_writel(mask, PERF_IRQMASK_REG); } +static unsigned int bcm63xx_internal_irq_startup(unsigned int irq) +{ + bcm63xx_internal_irq_unmask(irq); + return 0; +} + /* * external IRQs operations: mask/unmask and clear on PERF external * irq control register. */ -static void bcm63xx_external_irq_mask(struct irq_data *d) +static void bcm63xx_external_irq_mask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_EXT_BASE; u32 reg; + irq -= IRQ_EXT_BASE; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg &= ~EXTIRQ_CFG_MASK(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); } -static void bcm63xx_external_irq_unmask(struct irq_data *d) +static void bcm63xx_external_irq_unmask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_EXT_BASE; u32 reg; + irq -= IRQ_EXT_BASE; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg |= EXTIRQ_CFG_MASK(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); } -static void bcm63xx_external_irq_clear(struct irq_data *d) +static void bcm63xx_external_irq_clear(unsigned int irq) { - unsigned int irq = d->irq - IRQ_EXT_BASE; u32 reg; + irq -= IRQ_EXT_BASE; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg |= EXTIRQ_CFG_CLEAR(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); } -static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) +static unsigned int bcm63xx_external_irq_startup(unsigned int irq) { - set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); + set_c0_status(0x100 << (irq - IRQ_MIPS_BASE)); irq_enable_hazard(); - bcm63xx_external_irq_unmask(d); + bcm63xx_external_irq_unmask(irq); return 0; } -static void bcm63xx_external_irq_shutdown(struct irq_data *d) +static void bcm63xx_external_irq_shutdown(unsigned int irq) { - bcm63xx_external_irq_mask(d); - clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); + bcm63xx_external_irq_mask(irq); + clear_c0_status(0x100 << (irq - IRQ_MIPS_BASE)); irq_disable_hazard(); } -static int bcm63xx_external_irq_set_type(struct irq_data *d, +static int bcm63xx_external_irq_set_type(unsigned int irq, unsigned int flow_type) { - unsigned int irq = d->irq - IRQ_EXT_BASE; u32 reg; + struct irq_desc *desc = irq_desc + irq; + + irq -= IRQ_EXT_BASE; flow_type &= IRQ_TYPE_SENSE_MASK; @@ -191,32 +199,37 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, } bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); - irqd_set_trigger_type(d, flow_type); - if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __irq_set_handler_locked(d->irq, handle_level_irq); - else - __irq_set_handler_locked(d->irq, handle_edge_irq); + if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) { + desc->status |= IRQ_LEVEL; + desc->handle_irq = handle_level_irq; + } else { + desc->handle_irq = handle_edge_irq; + } - return IRQ_SET_MASK_OK_NOCOPY; + return 0; } static struct irq_chip bcm63xx_internal_irq_chip = { .name = "bcm63xx_ipic", - .irq_mask = bcm63xx_internal_irq_mask, - .irq_unmask = bcm63xx_internal_irq_unmask, + .startup = bcm63xx_internal_irq_startup, + .shutdown = bcm63xx_internal_irq_mask, + + .mask = bcm63xx_internal_irq_mask, + .mask_ack = bcm63xx_internal_irq_mask, + .unmask = bcm63xx_internal_irq_unmask, }; static struct irq_chip bcm63xx_external_irq_chip = { .name = "bcm63xx_epic", - .irq_startup = bcm63xx_external_irq_startup, - .irq_shutdown = bcm63xx_external_irq_shutdown, + .startup = bcm63xx_external_irq_startup, + .shutdown = bcm63xx_external_irq_shutdown, - .irq_ack = bcm63xx_external_irq_clear, + .ack = bcm63xx_external_irq_clear, - .irq_mask = bcm63xx_external_irq_mask, - .irq_unmask = bcm63xx_external_irq_unmask, + .mask = bcm63xx_external_irq_mask, + .unmask = bcm63xx_external_irq_unmask, - .irq_set_type = bcm63xx_external_irq_set_type, + .set_type = bcm63xx_external_irq_set_type, }; static struct irqaction cpu_ip2_cascade_action = { diff --git a/trunk/arch/mips/dec/ioasic-irq.c b/trunk/arch/mips/dec/ioasic-irq.c index 8d9a5fc607e4..cb41954fc321 100644 --- a/trunk/arch/mips/dec/ioasic-irq.c +++ b/trunk/arch/mips/dec/ioasic-irq.c @@ -17,48 +17,80 @@ #include #include + static int ioasic_irq_base; -static void unmask_ioasic_irq(struct irq_data *d) + +static inline void unmask_ioasic_irq(unsigned int irq) { u32 simr; simr = ioasic_read(IO_REG_SIMR); - simr |= (1 << (d->irq - ioasic_irq_base)); + simr |= (1 << (irq - ioasic_irq_base)); ioasic_write(IO_REG_SIMR, simr); } -static void mask_ioasic_irq(struct irq_data *d) +static inline void mask_ioasic_irq(unsigned int irq) { u32 simr; simr = ioasic_read(IO_REG_SIMR); - simr &= ~(1 << (d->irq - ioasic_irq_base)); + simr &= ~(1 << (irq - ioasic_irq_base)); ioasic_write(IO_REG_SIMR, simr); } -static void ack_ioasic_irq(struct irq_data *d) +static inline void clear_ioasic_irq(unsigned int irq) { - mask_ioasic_irq(d); + u32 sir; + + sir = ~(1 << (irq - ioasic_irq_base)); + ioasic_write(IO_REG_SIR, sir); +} + +static inline void ack_ioasic_irq(unsigned int irq) +{ + mask_ioasic_irq(irq); fast_iob(); } +static inline void end_ioasic_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + unmask_ioasic_irq(irq); +} + static struct irq_chip ioasic_irq_type = { .name = "IO-ASIC", - .irq_ack = ack_ioasic_irq, - .irq_mask = mask_ioasic_irq, - .irq_mask_ack = ack_ioasic_irq, - .irq_unmask = unmask_ioasic_irq, + .ack = ack_ioasic_irq, + .mask = mask_ioasic_irq, + .mask_ack = ack_ioasic_irq, + .unmask = unmask_ioasic_irq, }; + +#define unmask_ioasic_dma_irq unmask_ioasic_irq + +#define mask_ioasic_dma_irq mask_ioasic_irq + +#define ack_ioasic_dma_irq ack_ioasic_irq + +static inline void end_ioasic_dma_irq(unsigned int irq) +{ + clear_ioasic_irq(irq); + fast_iob(); + end_ioasic_irq(irq); +} + static struct irq_chip ioasic_dma_irq_type = { .name = "IO-ASIC-DMA", - .irq_ack = ack_ioasic_irq, - .irq_mask = mask_ioasic_irq, - .irq_mask_ack = ack_ioasic_irq, - .irq_unmask = unmask_ioasic_irq, + .ack = ack_ioasic_dma_irq, + .mask = mask_ioasic_dma_irq, + .mask_ack = ack_ioasic_dma_irq, + .unmask = unmask_ioasic_dma_irq, + .end = end_ioasic_dma_irq, }; + void __init init_ioasic_irqs(int base) { int i; diff --git a/trunk/arch/mips/dec/kn02-irq.c b/trunk/arch/mips/dec/kn02-irq.c index ef31d98c4fb8..ed90a8deabcc 100644 --- a/trunk/arch/mips/dec/kn02-irq.c +++ b/trunk/arch/mips/dec/kn02-irq.c @@ -27,40 +27,43 @@ */ u32 cached_kn02_csr; + static int kn02_irq_base; -static void unmask_kn02_irq(struct irq_data *d) + +static inline void unmask_kn02_irq(unsigned int irq) { volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR); - cached_kn02_csr |= (1 << (d->irq - kn02_irq_base + 16)); + cached_kn02_csr |= (1 << (irq - kn02_irq_base + 16)); *csr = cached_kn02_csr; } -static void mask_kn02_irq(struct irq_data *d) +static inline void mask_kn02_irq(unsigned int irq) { volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR); - cached_kn02_csr &= ~(1 << (d->irq - kn02_irq_base + 16)); + cached_kn02_csr &= ~(1 << (irq - kn02_irq_base + 16)); *csr = cached_kn02_csr; } -static void ack_kn02_irq(struct irq_data *d) +static void ack_kn02_irq(unsigned int irq) { - mask_kn02_irq(d); + mask_kn02_irq(irq); iob(); } static struct irq_chip kn02_irq_type = { .name = "KN02-CSR", - .irq_ack = ack_kn02_irq, - .irq_mask = mask_kn02_irq, - .irq_mask_ack = ack_kn02_irq, - .irq_unmask = unmask_kn02_irq, + .ack = ack_kn02_irq, + .mask = mask_kn02_irq, + .mask_ack = ack_kn02_irq, + .unmask = unmask_kn02_irq, }; + void __init init_kn02_irqs(int base) { volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + diff --git a/trunk/arch/mips/emma/markeins/irq.c b/trunk/arch/mips/emma/markeins/irq.c index 9b1207ae2256..3a96799eb65f 100644 --- a/trunk/arch/mips/emma/markeins/irq.c +++ b/trunk/arch/mips/emma/markeins/irq.c @@ -34,10 +34,13 @@ #include -static void emma2rh_irq_enable(struct irq_data *d) +static void emma2rh_irq_enable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_IRQ_BASE; - u32 reg_value, reg_bitmask, reg_index; + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + irq -= EMMA2RH_IRQ_BASE; reg_index = EMMA2RH_BHIF_INT_EN_0 + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32); @@ -46,10 +49,13 @@ static void emma2rh_irq_enable(struct irq_data *d) emma2rh_out32(reg_index, reg_value | reg_bitmask); } -static void emma2rh_irq_disable(struct irq_data *d) +static void emma2rh_irq_disable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_IRQ_BASE; - u32 reg_value, reg_bitmask, reg_index; + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + irq -= EMMA2RH_IRQ_BASE; reg_index = EMMA2RH_BHIF_INT_EN_0 + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32); @@ -60,8 +66,10 @@ static void emma2rh_irq_disable(struct irq_data *d) struct irq_chip emma2rh_irq_controller = { .name = "emma2rh_irq", - .irq_mask = emma2rh_irq_disable, - .irq_unmask = emma2rh_irq_enable, + .ack = emma2rh_irq_disable, + .mask = emma2rh_irq_disable, + .mask_ack = emma2rh_irq_disable, + .unmask = emma2rh_irq_enable, }; void emma2rh_irq_init(void) @@ -74,21 +82,23 @@ void emma2rh_irq_init(void) handle_level_irq, "level"); } -static void emma2rh_sw_irq_enable(struct irq_data *d) +static void emma2rh_sw_irq_enable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE; u32 reg; + irq -= EMMA2RH_SW_IRQ_BASE; + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); reg |= 1 << irq; emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); } -static void emma2rh_sw_irq_disable(struct irq_data *d) +static void emma2rh_sw_irq_disable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE; u32 reg; + irq -= EMMA2RH_SW_IRQ_BASE; + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); reg &= ~(1 << irq); emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); @@ -96,8 +106,10 @@ static void emma2rh_sw_irq_disable(struct irq_data *d) struct irq_chip emma2rh_sw_irq_controller = { .name = "emma2rh_sw_irq", - .irq_mask = emma2rh_sw_irq_disable, - .irq_unmask = emma2rh_sw_irq_enable, + .ack = emma2rh_sw_irq_disable, + .mask = emma2rh_sw_irq_disable, + .mask_ack = emma2rh_sw_irq_disable, + .unmask = emma2rh_sw_irq_enable, }; void emma2rh_sw_irq_init(void) @@ -110,38 +122,39 @@ void emma2rh_sw_irq_init(void) handle_level_irq, "level"); } -static void emma2rh_gpio_irq_enable(struct irq_data *d) +static void emma2rh_gpio_irq_enable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE; u32 reg; + irq -= EMMA2RH_GPIO_IRQ_BASE; + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); reg |= 1 << irq; emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); } -static void emma2rh_gpio_irq_disable(struct irq_data *d) +static void emma2rh_gpio_irq_disable(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE; u32 reg; + irq -= EMMA2RH_GPIO_IRQ_BASE; + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); reg &= ~(1 << irq); emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); } -static void emma2rh_gpio_irq_ack(struct irq_data *d) +static void emma2rh_gpio_irq_ack(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE; - + irq -= EMMA2RH_GPIO_IRQ_BASE; emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); } -static void emma2rh_gpio_irq_mask_ack(struct irq_data *d) +static void emma2rh_gpio_irq_mask_ack(unsigned int irq) { - unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE; u32 reg; + irq -= EMMA2RH_GPIO_IRQ_BASE; emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); @@ -151,10 +164,10 @@ static void emma2rh_gpio_irq_mask_ack(struct irq_data *d) struct irq_chip emma2rh_gpio_irq_controller = { .name = "emma2rh_gpio_irq", - .irq_ack = emma2rh_gpio_irq_ack, - .irq_mask = emma2rh_gpio_irq_disable, - .irq_mask_ack = emma2rh_gpio_irq_mask_ack, - .irq_unmask = emma2rh_gpio_irq_enable, + .ack = emma2rh_gpio_irq_ack, + .mask = emma2rh_gpio_irq_disable, + .mask_ack = emma2rh_gpio_irq_mask_ack, + .unmask = emma2rh_gpio_irq_enable, }; void emma2rh_gpio_irq_init(void) diff --git a/trunk/arch/mips/include/asm/irq.h b/trunk/arch/mips/include/asm/irq.h index 0ec01294b063..b003ed52ed17 100644 --- a/trunk/arch/mips/include/asm/irq.h +++ b/trunk/arch/mips/include/asm/irq.h @@ -55,9 +55,9 @@ static inline void smtc_im_ack_irq(unsigned int irq) #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF #include -extern int plat_set_irq_affinity(struct irq_data *d, - const struct cpumask *affinity, bool force); -extern void smtc_forward_irq(struct irq_data *d); +extern int plat_set_irq_affinity(unsigned int irq, + const struct cpumask *affinity); +extern void smtc_forward_irq(unsigned int irq); /* * IRQ affinity hook invoked at the beginning of interrupt dispatch @@ -70,53 +70,51 @@ extern void smtc_forward_irq(struct irq_data *d); * cpumask implementations, this version is optimistically assuming * that cpumask.h macro overhead is reasonable during interrupt dispatch. */ -static inline int handle_on_other_cpu(unsigned int irq) -{ - struct irq_data *d = irq_get_irq_data(irq); - - if (cpumask_test_cpu(smp_processor_id(), d->affinity)) - return 0; - smtc_forward_irq(d); - return 1; -} +#define IRQ_AFFINITY_HOOK(irq) \ +do { \ + if (!cpumask_test_cpu(smp_processor_id(), irq_desc[irq].affinity)) {\ + smtc_forward_irq(irq); \ + irq_exit(); \ + return; \ + } \ +} while (0) #else /* Not doing SMTC affinity */ -static inline int handle_on_other_cpu(unsigned int irq) { return 0; } +#define IRQ_AFFINITY_HOOK(irq) do { } while (0) #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP -static inline void smtc_im_backstop(unsigned int irq) -{ - if (irq_hwmask[irq] & 0x0000ff00) - write_c0_tccontext(read_c0_tccontext() & - ~(irq_hwmask[irq] & 0x0000ff00)); -} - /* * Clear interrupt mask handling "backstop" if irq_hwmask * entry so indicates. This implies that the ack() or end() * functions will take over re-enabling the low-level mask. * Otherwise it will be done on return from exception. */ -static inline int smtc_handle_on_other_cpu(unsigned int irq) -{ - int ret = handle_on_other_cpu(irq); - - if (!ret) - smtc_im_backstop(irq); - return ret; -} +#define __DO_IRQ_SMTC_HOOK(irq) \ +do { \ + IRQ_AFFINITY_HOOK(irq); \ + if (irq_hwmask[irq] & 0x0000ff00) \ + write_c0_tccontext(read_c0_tccontext() & \ + ~(irq_hwmask[irq] & 0x0000ff00)); \ +} while (0) + +#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) \ +do { \ + if (irq_hwmask[irq] & 0x0000ff00) \ + write_c0_tccontext(read_c0_tccontext() & \ + ~(irq_hwmask[irq] & 0x0000ff00)); \ +} while (0) #else -static inline void smtc_im_backstop(unsigned int irq) { } -static inline int smtc_handle_on_other_cpu(unsigned int irq) -{ - return handle_on_other_cpu(irq); -} +#define __DO_IRQ_SMTC_HOOK(irq) \ +do { \ + IRQ_AFFINITY_HOOK(irq); \ +} while (0) +#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) do { } while (0) #endif diff --git a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h b/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h deleted file mode 100644 index a80801b094bd..000000000000 --- a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org) - */ -#ifndef __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H -#define __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H - -#define cpu_has_mips16 1 -#define cpu_has_dsp 1 -#define cpu_has_mipsmt 1 -#define cpu_has_fpu 0 - -#define cpu_has_mips32r1 0 -#define cpu_has_mips32r2 1 -#define cpu_has_mips64r1 0 -#define cpu_has_mips64r2 0 - -#endif /* __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H */ diff --git a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h b/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h deleted file mode 100644 index 156f320c69e7..000000000000 --- a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * - * Macros for external SMP-safe access to the PMC MSP71xx reference - * board GPIO pins - * - * Copyright 2010 PMC-Sierra, 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. - * - * 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. - */ - -#ifndef __MSP_GPIO_MACROS_H__ -#define __MSP_GPIO_MACROS_H__ - -#include -#include - -#ifdef CONFIG_PMC_MSP7120_GW -#define MSP_NUM_GPIOS 20 -#else -#define MSP_NUM_GPIOS 28 -#endif - -/* -- GPIO Enumerations -- */ -enum msp_gpio_data { - MSP_GPIO_LO = 0, - MSP_GPIO_HI = 1, - MSP_GPIO_NONE, /* Special - Means pin is out of range */ - MSP_GPIO_TOGGLE, /* Special - Sets pin to opposite */ -}; - -enum msp_gpio_mode { - MSP_GPIO_INPUT = 0x0, - /* MSP_GPIO_ INTERRUPT = 0x1, Not supported yet */ - MSP_GPIO_UART_INPUT = 0x2, /* Only GPIO 4 or 5 */ - MSP_GPIO_OUTPUT = 0x8, - MSP_GPIO_UART_OUTPUT = 0x9, /* Only GPIO 2 or 3 */ - MSP_GPIO_PERIF_TIMERA = 0x9, /* Only GPIO 0 or 1 */ - MSP_GPIO_PERIF_TIMERB = 0xa, /* Only GPIO 0 or 1 */ - MSP_GPIO_UNKNOWN = 0xb, /* No such GPIO or mode */ -}; - -/* -- Static Tables -- */ - -/* Maps pins to data register */ -static volatile u32 * const MSP_GPIO_DATA_REGISTER[] = { - /* GPIO 0 and 1 on the first register */ - GPIO_DATA1_REG, GPIO_DATA1_REG, - /* GPIO 2, 3, 4, and 5 on the second register */ - GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, - /* GPIO 6, 7, 8, and 9 on the third register */ - GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, - /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ - GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, - GPIO_DATA4_REG, GPIO_DATA4_REG, - /* GPIO 16 - 23 on the first strange EXTENDED register */ - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - /* GPIO 24 - 27 on the second strange EXTENDED register */ - EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, - EXTENDED_GPIO2_REG, -}; - -/* Maps pins to mode register */ -static volatile u32 * const MSP_GPIO_MODE_REGISTER[] = { - /* GPIO 0 and 1 on the first register */ - GPIO_CFG1_REG, GPIO_CFG1_REG, - /* GPIO 2, 3, 4, and 5 on the second register */ - GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, - /* GPIO 6, 7, 8, and 9 on the third register */ - GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, - /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ - GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, - GPIO_CFG4_REG, GPIO_CFG4_REG, - /* GPIO 16 - 23 on the first strange EXTENDED register */ - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, - /* GPIO 24 - 27 on the second strange EXTENDED register */ - EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, - EXTENDED_GPIO2_REG, -}; - -/* Maps 'basic' pins to relative offset from 0 per register */ -static int MSP_GPIO_OFFSET[] = { - /* GPIO 0 and 1 on the first register */ - 0, 0, - /* GPIO 2, 3, 4, and 5 on the second register */ - 2, 2, 2, 2, - /* GPIO 6, 7, 8, and 9 on the third register */ - 6, 6, 6, 6, - /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ - 10, 10, 10, 10, 10, 10, -}; - -/* Maps MODE to allowed pin mask */ -static unsigned int MSP_GPIO_MODE_ALLOWED[] = { - 0xffffffff, /* Mode 0 - INPUT */ - 0x00000, /* Mode 1 - INTERRUPT */ - 0x00030, /* Mode 2 - UART_INPUT (GPIO 4, 5)*/ - 0, 0, 0, 0, 0, /* Modes 3, 4, 5, 6, and 7 are reserved */ - 0xffffffff, /* Mode 8 - OUTPUT */ - 0x0000f, /* Mode 9 - UART_OUTPUT/ - PERF_TIMERA (GPIO 0, 1, 2, 3) */ - 0x00003, /* Mode a - PERF_TIMERB (GPIO 0, 1) */ - 0x00000, /* Mode b - Not really a mode! */ -}; - -/* -- Bit masks -- */ - -/* This gives you the 'register relative offset gpio' number */ -#define OFFSET_GPIO_NUMBER(gpio) (gpio - MSP_GPIO_OFFSET[gpio]) - -/* These take the 'register relative offset gpio' number */ -#define BASIC_DATA_REG_MASK(ogpio) (1 << ogpio) -#define BASIC_MODE_REG_VALUE(mode, ogpio) \ - (mode << BASIC_MODE_REG_SHIFT(ogpio)) -#define BASIC_MODE_REG_MASK(ogpio) \ - BASIC_MODE_REG_VALUE(0xf, ogpio) -#define BASIC_MODE_REG_SHIFT(ogpio) (ogpio * 4) -#define BASIC_MODE_REG_FROM_REG(data, ogpio) \ - ((data & BASIC_MODE_REG_MASK(ogpio)) >> BASIC_MODE_REG_SHIFT(ogpio)) - -/* These take the actual GPIO number (0 through 15) */ -#define BASIC_DATA_MASK(gpio) \ - BASIC_DATA_REG_MASK(OFFSET_GPIO_NUMBER(gpio)) -#define BASIC_MODE_MASK(gpio) \ - BASIC_MODE_REG_MASK(OFFSET_GPIO_NUMBER(gpio)) -#define BASIC_MODE(mode, gpio) \ - BASIC_MODE_REG_VALUE(mode, OFFSET_GPIO_NUMBER(gpio)) -#define BASIC_MODE_SHIFT(gpio) \ - BASIC_MODE_REG_SHIFT(OFFSET_GPIO_NUMBER(gpio)) -#define BASIC_MODE_FROM_REG(data, gpio) \ - BASIC_MODE_REG_FROM_REG(data, OFFSET_GPIO_NUMBER(gpio)) - -/* - * Each extended GPIO register is 32 bits long and is responsible for up to - * eight GPIOs. The least significant 16 bits contain the set and clear bit - * pair for each of the GPIOs. The most significant 16 bits contain the - * disable and enable bit pair for each of the GPIOs. For example, the - * extended GPIO reg for GPIOs 16-23 is as follows: - * - * 31: GPIO23_DISABLE - * ... - * 19: GPIO17_DISABLE - * 18: GPIO17_ENABLE - * 17: GPIO16_DISABLE - * 16: GPIO16_ENABLE - * ... - * 3: GPIO17_SET - * 2: GPIO17_CLEAR - * 1: GPIO16_SET - * 0: GPIO16_CLEAR - */ - -/* This gives the 'register relative offset gpio' number */ -#define EXTENDED_OFFSET_GPIO(gpio) (gpio < 24 ? gpio - 16 : gpio - 24) - -/* These take the 'register relative offset gpio' number */ -#define EXTENDED_REG_DISABLE(ogpio) (0x2 << ((ogpio * 2) + 16)) -#define EXTENDED_REG_ENABLE(ogpio) (0x1 << ((ogpio * 2) + 16)) -#define EXTENDED_REG_SET(ogpio) (0x2 << (ogpio * 2)) -#define EXTENDED_REG_CLR(ogpio) (0x1 << (ogpio * 2)) - -/* These take the actual GPIO number (16 through 27) */ -#define EXTENDED_DISABLE(gpio) \ - EXTENDED_REG_DISABLE(EXTENDED_OFFSET_GPIO(gpio)) -#define EXTENDED_ENABLE(gpio) \ - EXTENDED_REG_ENABLE(EXTENDED_OFFSET_GPIO(gpio)) -#define EXTENDED_SET(gpio) \ - EXTENDED_REG_SET(EXTENDED_OFFSET_GPIO(gpio)) -#define EXTENDED_CLR(gpio) \ - EXTENDED_REG_CLR(EXTENDED_OFFSET_GPIO(gpio)) - -#define EXTENDED_FULL_MASK (0xffffffff) - -/* -- API inline-functions -- */ - -/* - * Gets the current value of the specified pin - */ -static inline enum msp_gpio_data msp_gpio_pin_get(unsigned int gpio) -{ - u32 pinhi_mask = 0, pinhi_mask2 = 0; - - if (gpio >= MSP_NUM_GPIOS) - return MSP_GPIO_NONE; - - if (gpio < 16) { - pinhi_mask = BASIC_DATA_MASK(gpio); - } else { - /* - * Two cases are possible with the EXTENDED register: - * - In output mode (ENABLED flag set), check the CLR bit - * - In input mode (ENABLED flag not set), check the SET bit - */ - pinhi_mask = EXTENDED_ENABLE(gpio) | EXTENDED_CLR(gpio); - pinhi_mask2 = EXTENDED_SET(gpio); - } - if (((*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask) == pinhi_mask) || - (*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask2)) - return MSP_GPIO_HI; - else - return MSP_GPIO_LO; -} - -/* Sets the specified pin to the specified value */ -static inline void msp_gpio_pin_set(enum msp_gpio_data data, unsigned int gpio) -{ - if (gpio >= MSP_NUM_GPIOS) - return; - - if (gpio < 16) { - if (data == MSP_GPIO_TOGGLE) - toggle_reg32(MSP_GPIO_DATA_REGISTER[gpio], - BASIC_DATA_MASK(gpio)); - else if (data == MSP_GPIO_HI) - set_reg32(MSP_GPIO_DATA_REGISTER[gpio], - BASIC_DATA_MASK(gpio)); - else - clear_reg32(MSP_GPIO_DATA_REGISTER[gpio], - BASIC_DATA_MASK(gpio)); - } else { - if (data == MSP_GPIO_TOGGLE) { - /* Special ugly case: - * We have to read the CLR bit. - * If set, we write the CLR bit. - * If not, we write the SET bit. - */ - u32 tmpdata; - - custom_read_reg32(MSP_GPIO_DATA_REGISTER[gpio], - tmpdata); - if (tmpdata & EXTENDED_CLR(gpio)) - tmpdata = EXTENDED_CLR(gpio); - else - tmpdata = EXTENDED_SET(gpio); - custom_write_reg32(MSP_GPIO_DATA_REGISTER[gpio], - tmpdata); - } else { - u32 newdata; - - if (data == MSP_GPIO_HI) - newdata = EXTENDED_SET(gpio); - else - newdata = EXTENDED_CLR(gpio); - set_value_reg32(MSP_GPIO_DATA_REGISTER[gpio], - EXTENDED_FULL_MASK, newdata); - } - } -} - -/* Sets the specified pin to the specified value */ -static inline void msp_gpio_pin_hi(unsigned int gpio) -{ - msp_gpio_pin_set(MSP_GPIO_HI, gpio); -} - -/* Sets the specified pin to the specified value */ -static inline void msp_gpio_pin_lo(unsigned int gpio) -{ - msp_gpio_pin_set(MSP_GPIO_LO, gpio); -} - -/* Sets the specified pin to the opposite value */ -static inline void msp_gpio_pin_toggle(unsigned int gpio) -{ - msp_gpio_pin_set(MSP_GPIO_TOGGLE, gpio); -} - -/* Gets the mode of the specified pin */ -static inline enum msp_gpio_mode msp_gpio_pin_get_mode(unsigned int gpio) -{ - enum msp_gpio_mode retval = MSP_GPIO_UNKNOWN; - uint32_t data; - - if (gpio >= MSP_NUM_GPIOS) - return retval; - - data = *MSP_GPIO_MODE_REGISTER[gpio]; - - if (gpio < 16) { - retval = BASIC_MODE_FROM_REG(data, gpio); - } else { - /* Extended pins can only be either INPUT or OUTPUT */ - if (data & EXTENDED_ENABLE(gpio)) - retval = MSP_GPIO_OUTPUT; - else - retval = MSP_GPIO_INPUT; - } - - return retval; -} - -/* - * Sets the specified mode on the requested pin - * Returns 0 on success, or -1 if that mode is not allowed on this pin - */ -static inline int msp_gpio_pin_mode(enum msp_gpio_mode mode, unsigned int gpio) -{ - u32 modemask, newmode; - - if ((1 << gpio) & ~MSP_GPIO_MODE_ALLOWED[mode]) - return -1; - - if (gpio >= MSP_NUM_GPIOS) - return -1; - - if (gpio < 16) { - modemask = BASIC_MODE_MASK(gpio); - newmode = BASIC_MODE(mode, gpio); - } else { - modemask = EXTENDED_FULL_MASK; - if (mode == MSP_GPIO_INPUT) - newmode = EXTENDED_DISABLE(gpio); - else - newmode = EXTENDED_ENABLE(gpio); - } - /* Do the set atomically */ - set_value_reg32(MSP_GPIO_MODE_REGISTER[gpio], modemask, newmode); - - return 0; -} - -#endif /* __MSP_GPIO_MACROS_H__ */ diff --git a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h b/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h index 692c1b658b92..603eb737b4a8 100644 --- a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h +++ b/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h @@ -91,10 +91,12 @@ /* MAC C device registers */ #define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000) /* ADSL2 device registers */ -#define MSP_USB0_BASE (MSP_MSB_BASE + 0xB00000) - /* USB0 device registers */ -#define MSP_USB1_BASE (MSP_MSB_BASE + 0x300000) - /* USB1 device registers */ +#define MSP_USB_BASE (MSP_MSB_BASE + 0xB40000) + /* USB device registers */ +#define MSP_USB_BASE_START (MSP_MSB_BASE + 0xB40100) + /* USB device registers */ +#define MSP_USB_BASE_END (MSP_MSB_BASE + 0xB401FF) + /* USB device registers */ #define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000) /* CPU interface registers */ @@ -317,11 +319,8 @@ #define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184) /* CPU/SLP Error status 1 */ -/* Extended GPIO registers */ -#define EXTENDED_GPIO1_REG regptr(MSP_SLP_BASE + 0x188) -#define EXTENDED_GPIO2_REG regptr(MSP_SLP_BASE + 0x18c) -#define EXTENDED_GPIO_REG EXTENDED_GPIO1_REG - /* Backward-compatibility */ +#define EXTENDED_GPIO_REG regptr(MSP_SLP_BASE + 0x188) + /* Extended GPIO register */ /* System Error registers */ #define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190) diff --git a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h b/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h deleted file mode 100644 index 4c9348df9df2..000000000000 --- a/trunk/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h +++ /dev/null @@ -1,144 +0,0 @@ -/****************************************************************** - * Copyright (c) 2000-2007 PMC-Sierra 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. - * - * This program 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., 675 Mass Ave, Cambridge, MA - * 02139, USA. - * - * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS - * SOFTWARE. - */ -#ifndef MSP_USB_H_ -#define MSP_USB_H_ - -#ifdef CONFIG_MSP_HAS_DUAL_USB -#define NUM_USB_DEVS 2 -#else -#define NUM_USB_DEVS 1 -#endif - -/* Register spaces for USB host 0 */ -#define MSP_USB0_MAB_START (MSP_USB0_BASE + 0x0) -#define MSP_USB0_MAB_END (MSP_USB0_BASE + 0x17) -#define MSP_USB0_ID_START (MSP_USB0_BASE + 0x40000) -#define MSP_USB0_ID_END (MSP_USB0_BASE + 0x4008f) -#define MSP_USB0_HS_START (MSP_USB0_BASE + 0x40100) -#define MSP_USB0_HS_END (MSP_USB0_BASE + 0x401FF) - -/* Register spaces for USB host 1 */ -#define MSP_USB1_MAB_START (MSP_USB1_BASE + 0x0) -#define MSP_USB1_MAB_END (MSP_USB1_BASE + 0x17) -#define MSP_USB1_ID_START (MSP_USB1_BASE + 0x40000) -#define MSP_USB1_ID_END (MSP_USB1_BASE + 0x4008f) -#define MSP_USB1_HS_START (MSP_USB1_BASE + 0x40100) -#define MSP_USB1_HS_END (MSP_USB1_BASE + 0x401ff) - -/* USB Identification registers */ -struct msp_usbid_regs { - u32 id; /* 0x0: Identification register */ - u32 hwgen; /* 0x4: General HW params */ - u32 hwhost; /* 0x8: Host HW params */ - u32 hwdev; /* 0xc: Device HW params */ - u32 hwtxbuf; /* 0x10: Tx buffer HW params */ - u32 hwrxbuf; /* 0x14: Rx buffer HW params */ - u32 reserved[26]; - u32 timer0_load; /* 0x80: General-purpose timer 0 load*/ - u32 timer0_ctrl; /* 0x84: General-purpose timer 0 control */ - u32 timer1_load; /* 0x88: General-purpose timer 1 load*/ - u32 timer1_ctrl; /* 0x8c: General-purpose timer 1 control */ -}; - -/* MSBus to AMBA registers */ -struct msp_mab_regs { - u32 isr; /* 0x0: Interrupt status */ - u32 imr; /* 0x4: Interrupt mask */ - u32 thcr0; /* 0x8: Transaction header capture 0 */ - u32 thcr1; /* 0xc: Transaction header capture 1 */ - u32 int_stat; /* 0x10: Interrupt status summary */ - u32 phy_cfg; /* 0x14: USB phy config */ -}; - -/* EHCI registers */ -struct msp_usbhs_regs { - u32 hciver; /* 0x0: Version and offset to operational regs */ - u32 hcsparams; /* 0x4: Host control structural parameters */ - u32 hccparams; /* 0x8: Host control capability parameters */ - u32 reserved0[5]; - u32 dciver; /* 0x20: Device interface version */ - u32 dccparams; /* 0x24: Device control capability parameters */ - u32 reserved1[6]; - u32 cmd; /* 0x40: USB command */ - u32 sts; /* 0x44: USB status */ - u32 int_ena; /* 0x48: USB interrupt enable */ - u32 frindex; /* 0x4c: Frame index */ - u32 reserved3; - union { - struct { - u32 flb_addr; /* 0x54: Frame list base address */ - u32 next_async_addr; /* 0x58: next asynchronous addr */ - u32 ttctrl; /* 0x5c: embedded transaction translator - async buffer status */ - u32 burst_size; /* 0x60: Controller burst size */ - u32 tx_fifo_ctrl; /* 0x64: Tx latency FIFO tuning */ - u32 reserved0[4]; - u32 endpt_nak; /* 0x78: Endpoint NAK */ - u32 endpt_nak_ena; /* 0x7c: Endpoint NAK enable */ - u32 cfg_flag; /* 0x80: Config flag */ - u32 port_sc1; /* 0x84: Port status & control 1 */ - u32 reserved1[7]; - u32 otgsc; /* 0xa4: OTG status & control */ - u32 mode; /* 0xa8: USB controller mode */ - } host; - - struct { - u32 dev_addr; /* 0x54: Device address */ - u32 endpt_list_addr; /* 0x58: Endpoint list address */ - u32 reserved0[7]; - u32 endpt_nak; /* 0x74 */ - u32 endpt_nak_ctrl; /* 0x78 */ - u32 cfg_flag; /* 0x80 */ - u32 port_sc1; /* 0x84: Port status & control 1 */ - u32 reserved[7]; - u32 otgsc; /* 0xa4: OTG status & control */ - u32 mode; /* 0xa8: USB controller mode */ - u32 endpt_setup_stat; /* 0xac */ - u32 endpt_prime; /* 0xb0 */ - u32 endpt_flush; /* 0xb4 */ - u32 endpt_stat; /* 0xb8 */ - u32 endpt_complete; /* 0xbc */ - u32 endpt_ctrl0; /* 0xc0 */ - u32 endpt_ctrl1; /* 0xc4 */ - u32 endpt_ctrl2; /* 0xc8 */ - u32 endpt_ctrl3; /* 0xcc */ - } device; - } u; -}; -/* - * Container for the more-generic platform_device. - * This exists mainly as a way to map the non-standard register - * spaces and make them accessible to the USB ISR. - */ -struct mspusb_device { - struct msp_mab_regs __iomem *mab_regs; - struct msp_usbid_regs __iomem *usbid_regs; - struct msp_usbhs_regs __iomem *usbhs_regs; - struct platform_device dev; -}; - -#define to_mspusb_device(x) container_of((x), struct mspusb_device, dev) -#define TO_HOST_ID(x) ((x) & 0x3) -#endif /*MSP_USB_H_*/ diff --git a/trunk/arch/mips/include/asm/spinlock.h b/trunk/arch/mips/include/asm/spinlock.h index ca61e846ab0f..396e402fbe2c 100644 --- a/trunk/arch/mips/include/asm/spinlock.h +++ b/trunk/arch/mips/include/asm/spinlock.h @@ -245,16 +245,16 @@ static inline void arch_read_lock(arch_rwlock_t *rw) __asm__ __volatile__( " .set noreorder # arch_read_lock \n" "1: ll %1, %2 \n" - " bltz %1, 3f \n" + " bltz %1, 2f \n" " addu %1, 1 \n" - "2: sc %1, %0 \n" + " sc %1, %0 \n" " beqz %1, 1b \n" " nop \n" " .subsection 2 \n" - "3: ll %1, %2 \n" - " bltz %1, 3b \n" + "2: ll %1, %2 \n" + " bltz %1, 2b \n" " addu %1, 1 \n" - " b 2b \n" + " b 1b \n" " nop \n" " .previous \n" " .set reorder \n" @@ -324,16 +324,16 @@ static inline void arch_write_lock(arch_rwlock_t *rw) __asm__ __volatile__( " .set noreorder # arch_write_lock \n" "1: ll %1, %2 \n" - " bnez %1, 3f \n" + " bnez %1, 2f \n" " lui %1, 0x8000 \n" - "2: sc %1, %0 \n" - " beqz %1, 3f \n" + " sc %1, %0 \n" + " beqz %1, 2f \n" " nop \n" " .subsection 2 \n" - "3: ll %1, %2 \n" - " bnez %1, 3b \n" + "2: ll %1, %2 \n" + " bnez %1, 2b \n" " lui %1, 0x8000 \n" - " b 2b \n" + " b 1b \n" " nop \n" " .previous \n" " .set reorder \n" diff --git a/trunk/arch/mips/include/asm/unistd.h b/trunk/arch/mips/include/asm/unistd.h index dae22c1d2c82..550725b881d5 100644 --- a/trunk/arch/mips/include/asm/unistd.h +++ b/trunk/arch/mips/include/asm/unistd.h @@ -359,20 +359,16 @@ #define __NR_fanotify_init (__NR_Linux + 336) #define __NR_fanotify_mark (__NR_Linux + 337) #define __NR_prlimit64 (__NR_Linux + 338) -#define __NR_name_to_handle_at (__NR_Linux + 339) -#define __NR_open_by_handle_at (__NR_Linux + 340) -#define __NR_clock_adjtime (__NR_Linux + 341) -#define __NR_syncfs (__NR_Linux + 342) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 342 +#define __NR_Linux_syscalls 338 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 342 +#define __NR_O32_Linux_syscalls 338 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -678,20 +674,16 @@ #define __NR_fanotify_init (__NR_Linux + 295) #define __NR_fanotify_mark (__NR_Linux + 296) #define __NR_prlimit64 (__NR_Linux + 297) -#define __NR_name_to_handle_at (__NR_Linux + 298) -#define __NR_open_by_handle_at (__NR_Linux + 299) -#define __NR_clock_adjtime (__NR_Linux + 300) -#define __NR_syncfs (__NR_Linux + 301) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 301 +#define __NR_Linux_syscalls 297 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 301 +#define __NR_64_Linux_syscalls 297 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -1002,20 +994,16 @@ #define __NR_fanotify_init (__NR_Linux + 300) #define __NR_fanotify_mark (__NR_Linux + 301) #define __NR_prlimit64 (__NR_Linux + 302) -#define __NR_name_to_handle_at (__NR_Linux + 303) -#define __NR_open_by_handle_at (__NR_Linux + 304) -#define __NR_clock_adjtime (__NR_Linux + 305) -#define __NR_clock_adjtime (__NR_Linux + 306) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 306 +#define __NR_Linux_syscalls 302 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 306 +#define __NR_N32_Linux_syscalls 302 #ifdef __KERNEL__ diff --git a/trunk/arch/mips/jazz/irq.c b/trunk/arch/mips/jazz/irq.c index 40f7c6b1e260..35b3e2f0af04 100644 --- a/trunk/arch/mips/jazz/irq.c +++ b/trunk/arch/mips/jazz/irq.c @@ -23,9 +23,9 @@ static DEFINE_RAW_SPINLOCK(r4030_lock); -static void enable_r4030_irq(struct irq_data *d) +static void enable_r4030_irq(unsigned int irq) { - unsigned int mask = 1 << (d->irq - JAZZ_IRQ_START); + unsigned int mask = 1 << (irq - JAZZ_IRQ_START); unsigned long flags; raw_spin_lock_irqsave(&r4030_lock, flags); @@ -34,9 +34,9 @@ static void enable_r4030_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&r4030_lock, flags); } -void disable_r4030_irq(struct irq_data *d) +void disable_r4030_irq(unsigned int irq) { - unsigned int mask = ~(1 << (d->irq - JAZZ_IRQ_START)); + unsigned int mask = ~(1 << (irq - JAZZ_IRQ_START)); unsigned long flags; raw_spin_lock_irqsave(&r4030_lock, flags); @@ -47,8 +47,10 @@ void disable_r4030_irq(struct irq_data *d) static struct irq_chip r4030_irq_type = { .name = "R4030", - .irq_mask = disable_r4030_irq, - .irq_unmask = enable_r4030_irq, + .ack = disable_r4030_irq, + .mask = disable_r4030_irq, + .mask_ack = disable_r4030_irq, + .unmask = enable_r4030_irq, }; void __init init_r4030_ints(void) diff --git a/trunk/arch/mips/jz4740/board-qi_lb60.c b/trunk/arch/mips/jz4740/board-qi_lb60.c index bc18daaa8f84..2c0e107966ad 100644 --- a/trunk/arch/mips/jz4740/board-qi_lb60.c +++ b/trunk/arch/mips/jz4740/board-qi_lb60.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -50,14 +49,14 @@ static bool is_avt2; /* NAND */ static struct nand_ecclayout qi_lb60_ecclayout_1gb = { - .eccbytes = 36, +/* .eccbytes = 36, .eccpos = { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41 - }, + },*/ .oobfree = { { .offset = 2, .length = 4 }, { .offset = 42, .length = 22 } @@ -86,7 +85,7 @@ static struct mtd_partition qi_lb60_partitions_1gb[] = { }; static struct nand_ecclayout qi_lb60_ecclayout_2gb = { - .eccbytes = 72, +/* .eccbytes = 72, .eccpos = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, @@ -97,7 +96,7 @@ static struct nand_ecclayout qi_lb60_ecclayout_2gb = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83 - }, + },*/ .oobfree = { { .offset = 2, .length = 10 }, { .offset = 84, .length = 44 }, @@ -397,28 +396,6 @@ static struct platform_device qi_lb60_pwm_beeper = { }, }; -/* charger */ -static char *qi_lb60_batteries[] = { - "battery", -}; - -static struct gpio_charger_platform_data qi_lb60_charger_pdata = { - .name = "usb", - .type = POWER_SUPPLY_TYPE_USB, - .gpio = JZ_GPIO_PORTD(28), - .gpio_active_low = 1, - .supplied_to = qi_lb60_batteries, - .num_supplicants = ARRAY_SIZE(qi_lb60_batteries), -}; - -static struct platform_device qi_lb60_charger_device = { - .name = "gpio-charger", - .dev = { - .platform_data = &qi_lb60_charger_pdata, - }, -}; - - static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_udc_device, &jz4740_mmc_device, @@ -433,7 +410,6 @@ static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_adc_device, &qi_lb60_gpio_keys, &qi_lb60_pwm_beeper, - &qi_lb60_charger_device, }; static void __init board_gpio_setup(void) diff --git a/trunk/arch/mips/jz4740/gpio.c b/trunk/arch/mips/jz4740/gpio.c index bd2fc29b95e0..88e6aeda5bf1 100644 --- a/trunk/arch/mips/jz4740/gpio.c +++ b/trunk/arch/mips/jz4740/gpio.c @@ -86,6 +86,7 @@ struct jz_gpio_chip { spinlock_t lock; struct gpio_chip gpio_chip; + struct irq_chip irq_chip; struct sys_device sysdev; }; @@ -101,9 +102,9 @@ static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *g return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip); } -static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data) +static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq) { - return irq_data_get_irq_chip_data(data); + return get_irq_chip_data(irq); } static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) @@ -324,52 +325,62 @@ static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) generic_handle_irq(gpio_irq); }; -static inline void jz_gpio_set_irq_bit(struct irq_data *data, unsigned int reg) +static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg) { - struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); - writel(IRQ_TO_BIT(data->irq), chip->base + reg); + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + writel(IRQ_TO_BIT(irq), chip->base + reg); } -static void jz_gpio_irq_mask(struct irq_data *data) +static void jz_gpio_irq_mask(unsigned int irq) { - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET); }; -static void jz_gpio_irq_unmask(struct irq_data *data) +static void jz_gpio_irq_unmask(unsigned int irq) { - struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); - jz_gpio_check_trigger_both(chip, data->irq); + jz_gpio_check_trigger_both(chip, irq); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR); }; /* TODO: Check if function is gpio */ -static unsigned int jz_gpio_irq_startup(struct irq_data *data) +static unsigned int jz_gpio_irq_startup(unsigned int irq) { - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_SET); - jz_gpio_irq_unmask(data); + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET); + + desc->status &= ~IRQ_MASKED; + jz_gpio_irq_unmask(irq); + return 0; } -static void jz_gpio_irq_shutdown(struct irq_data *data) +static void jz_gpio_irq_shutdown(unsigned int irq) { - jz_gpio_irq_mask(data); + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_irq_mask(irq); + desc->status |= IRQ_MASKED; /* Set direction to input */ - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR); } -static void jz_gpio_irq_ack(struct irq_data *data) +static void jz_gpio_irq_ack(unsigned int irq) { - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR); }; -static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) +static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) { - struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); - unsigned int irq = data->irq; + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_irq_mask(irq); if (flow_type == IRQ_TYPE_EDGE_BOTH) { uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN); @@ -384,54 +395,45 @@ static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) switch (flow_type) { case IRQ_TYPE_EDGE_RISING: - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_SET); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); break; case IRQ_TYPE_EDGE_FALLING: - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); break; case IRQ_TYPE_LEVEL_HIGH: - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_SET); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); break; case IRQ_TYPE_LEVEL_LOW: - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); break; default: return -EINVAL; } + if (!(desc->status & IRQ_MASKED)) + jz_gpio_irq_unmask(irq); + return 0; } -static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) +static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on) { - struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); spin_lock(&chip->lock); if (on) - chip->wakeup |= IRQ_TO_BIT(data->irq); + chip->wakeup |= IRQ_TO_BIT(irq); else - chip->wakeup &= ~IRQ_TO_BIT(data->irq); + chip->wakeup &= ~IRQ_TO_BIT(irq); spin_unlock(&chip->lock); set_irq_wake(chip->irq, on); return 0; } -static struct irq_chip jz_gpio_irq_chip = { - .name = "GPIO", - .irq_mask = jz_gpio_irq_mask, - .irq_unmask = jz_gpio_irq_unmask, - .irq_ack = jz_gpio_irq_ack, - .irq_startup = jz_gpio_irq_startup, - .irq_shutdown = jz_gpio_irq_shutdown, - .irq_set_type = jz_gpio_irq_set_type, - .irq_set_wake = jz_gpio_irq_set_wake, - .flags = IRQCHIP_SET_TYPE_MASKED, -}; - /* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. @@ -450,6 +452,16 @@ static struct lock_class_key gpio_lock_class; .base = JZ4740_GPIO_BASE_ ## _bank, \ .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ }, \ + .irq_chip = { \ + .name = "GPIO Bank " # _bank, \ + .mask = jz_gpio_irq_mask, \ + .unmask = jz_gpio_irq_unmask, \ + .ack = jz_gpio_irq_ack, \ + .startup = jz_gpio_irq_startup, \ + .shutdown = jz_gpio_irq_shutdown, \ + .set_type = jz_gpio_irq_set_type, \ + .set_wake = jz_gpio_irq_set_wake, \ + }, \ } static struct jz_gpio_chip jz4740_gpio_chips[] = { @@ -514,10 +526,9 @@ static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler); for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { - irq_set_lockdep_class(irq, &gpio_lock_class); + lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class); set_irq_chip_data(irq, chip); - set_irq_chip_and_handler(irq, &jz_gpio_irq_chip, - handle_level_irq); + set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); } return 0; diff --git a/trunk/arch/mips/jz4740/irq.c b/trunk/arch/mips/jz4740/irq.c index dcc5593a9389..7d33ff83580f 100644 --- a/trunk/arch/mips/jz4740/irq.c +++ b/trunk/arch/mips/jz4740/irq.c @@ -43,37 +43,32 @@ static uint32_t jz_intc_saved; #define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE) -static inline unsigned long intc_irq_bit(struct irq_data *data) +static void intc_irq_unmask(unsigned int irq) { - return (unsigned long)irq_data_get_irq_chip_data(data); + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK); } -static void intc_irq_unmask(struct irq_data *data) +static void intc_irq_mask(unsigned int irq) { - writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_CLEAR_MASK); + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK); } -static void intc_irq_mask(struct irq_data *data) -{ - writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_SET_MASK); -} - -static int intc_irq_set_wake(struct irq_data *data, unsigned int on) +static int intc_irq_set_wake(unsigned int irq, unsigned int on) { if (on) - jz_intc_wakeup |= intc_irq_bit(data); + jz_intc_wakeup |= IRQ_BIT(irq); else - jz_intc_wakeup &= ~intc_irq_bit(data); + jz_intc_wakeup &= ~IRQ_BIT(irq); return 0; } static struct irq_chip intc_irq_type = { .name = "INTC", - .irq_mask = intc_irq_mask, - .irq_mask_ack = intc_irq_mask, - .irq_unmask = intc_irq_unmask, - .irq_set_wake = intc_irq_set_wake, + .mask = intc_irq_mask, + .mask_ack = intc_irq_mask, + .unmask = intc_irq_unmask, + .set_wake = intc_irq_set_wake, }; static irqreturn_t jz4740_cascade(int irq, void *data) @@ -100,11 +95,8 @@ void __init arch_init_irq(void) jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14); - /* Mask all irqs */ - writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK); - for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) { - set_irq_chip_data(i, (void *)IRQ_BIT(i)); + intc_irq_mask(i); set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq); } diff --git a/trunk/arch/mips/kernel/i8259.c b/trunk/arch/mips/kernel/i8259.c index e221662bb80c..c58176cc796b 100644 --- a/trunk/arch/mips/kernel/i8259.c +++ b/trunk/arch/mips/kernel/i8259.c @@ -31,19 +31,19 @@ static int i8259A_auto_eoi = -1; DEFINE_RAW_SPINLOCK(i8259A_lock); -static void disable_8259A_irq(struct irq_data *d); -static void enable_8259A_irq(struct irq_data *d); -static void mask_and_ack_8259A(struct irq_data *d); +static void disable_8259A_irq(unsigned int irq); +static void enable_8259A_irq(unsigned int irq); +static void mask_and_ack_8259A(unsigned int irq); static void init_8259A(int auto_eoi); static struct irq_chip i8259A_chip = { - .name = "XT-PIC", - .irq_mask = disable_8259A_irq, - .irq_disable = disable_8259A_irq, - .irq_unmask = enable_8259A_irq, - .irq_mask_ack = mask_and_ack_8259A, + .name = "XT-PIC", + .mask = disable_8259A_irq, + .disable = disable_8259A_irq, + .unmask = enable_8259A_irq, + .mask_ack = mask_and_ack_8259A, #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF - .irq_set_affinity = plat_set_irq_affinity, + .set_affinity = plat_set_irq_affinity, #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ }; @@ -59,11 +59,12 @@ static unsigned int cached_irq_mask = 0xffff; #define cached_master_mask (cached_irq_mask) #define cached_slave_mask (cached_irq_mask >> 8) -static void disable_8259A_irq(struct irq_data *d) +static void disable_8259A_irq(unsigned int irq) { - unsigned int mask, irq = d->irq - I8259A_IRQ_BASE; + unsigned int mask; unsigned long flags; + irq -= I8259A_IRQ_BASE; mask = 1 << irq; raw_spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; @@ -74,11 +75,12 @@ static void disable_8259A_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&i8259A_lock, flags); } -static void enable_8259A_irq(struct irq_data *d) +static void enable_8259A_irq(unsigned int irq) { - unsigned int mask, irq = d->irq - I8259A_IRQ_BASE; + unsigned int mask; unsigned long flags; + irq -= I8259A_IRQ_BASE; mask = ~(1 << irq); raw_spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; @@ -143,11 +145,12 @@ static inline int i8259A_irq_real(unsigned int irq) * first, _then_ send the EOI, and the order of EOI * to the two 8259s is important! */ -static void mask_and_ack_8259A(struct irq_data *d) +static void mask_and_ack_8259A(unsigned int irq) { - unsigned int irqmask, irq = d->irq - I8259A_IRQ_BASE; + unsigned int irqmask; unsigned long flags; + irq -= I8259A_IRQ_BASE; irqmask = 1 << irq; raw_spin_lock_irqsave(&i8259A_lock, flags); /* @@ -287,9 +290,9 @@ static void init_8259A(int auto_eoi) * In AEOI mode we just have to mask the interrupt * when acking. */ - i8259A_chip.irq_mask_ack = disable_8259A_irq; + i8259A_chip.mask_ack = disable_8259A_irq; else - i8259A_chip.irq_mask_ack = mask_and_ack_8259A; + i8259A_chip.mask_ack = mask_and_ack_8259A; udelay(100); /* wait for 8259A to initialize */ diff --git a/trunk/arch/mips/kernel/irq-gic.c b/trunk/arch/mips/kernel/irq-gic.c index 43cd9628251a..1774271af848 100644 --- a/trunk/arch/mips/kernel/irq-gic.c +++ b/trunk/arch/mips/kernel/irq-gic.c @@ -87,10 +87,17 @@ unsigned int gic_get_int(void) return i; } -static void gic_irq_ack(struct irq_data *d) +static unsigned int gic_irq_startup(unsigned int irq) { - unsigned int irq = d->irq - _irqbase; + irq -= _irqbase; + pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); + GIC_SET_INTR_MASK(irq); + return 0; +} +static void gic_irq_ack(unsigned int irq) +{ + irq -= _irqbase; pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); GIC_CLR_INTR_MASK(irq); @@ -98,16 +105,16 @@ static void gic_irq_ack(struct irq_data *d) GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); } -static void gic_mask_irq(struct irq_data *d) +static void gic_mask_irq(unsigned int irq) { - unsigned int irq = d->irq - _irqbase; + irq -= _irqbase; pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); GIC_CLR_INTR_MASK(irq); } -static void gic_unmask_irq(struct irq_data *d) +static void gic_unmask_irq(unsigned int irq) { - unsigned int irq = d->irq - _irqbase; + irq -= _irqbase; pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); GIC_SET_INTR_MASK(irq); } @@ -116,14 +123,13 @@ static void gic_unmask_irq(struct irq_data *d) static DEFINE_SPINLOCK(gic_lock); -static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, - bool force) +static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask) { - unsigned int irq = d->irq - _irqbase; cpumask_t tmp = CPU_MASK_NONE; unsigned long flags; int i; + irq -= _irqbase; pr_debug("%s(%d) called\n", __func__, irq); cpumask_and(&tmp, cpumask, cpu_online_mask); if (cpus_empty(tmp)) @@ -141,22 +147,23 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); } - cpumask_copy(d->affinity, cpumask); + cpumask_copy(irq_desc[irq].affinity, cpumask); spin_unlock_irqrestore(&gic_lock, flags); - return IRQ_SET_MASK_OK_NOCOPY; + return 0; } #endif static struct irq_chip gic_irq_controller = { - .name = "MIPS GIC", - .irq_ack = gic_irq_ack, - .irq_mask = gic_mask_irq, - .irq_mask_ack = gic_mask_irq, - .irq_unmask = gic_unmask_irq, - .irq_eoi = gic_unmask_irq, + .name = "MIPS GIC", + .startup = gic_irq_startup, + .ack = gic_irq_ack, + .mask = gic_mask_irq, + .mask_ack = gic_mask_irq, + .unmask = gic_unmask_irq, + .eoi = gic_unmask_irq, #ifdef CONFIG_SMP - .irq_set_affinity = gic_set_affinity, + .set_affinity = gic_set_affinity, #endif }; diff --git a/trunk/arch/mips/kernel/irq-gt641xx.c b/trunk/arch/mips/kernel/irq-gt641xx.c index 7fd176fa367a..42ef81461bfc 100644 --- a/trunk/arch/mips/kernel/irq-gt641xx.c +++ b/trunk/arch/mips/kernel/irq-gt641xx.c @@ -29,64 +29,64 @@ static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock); -static void ack_gt641xx_irq(struct irq_data *d) +static void ack_gt641xx_irq(unsigned int irq) { unsigned long flags; u32 cause; raw_spin_lock_irqsave(>641xx_irq_lock, flags); cause = GT_READ(GT_INTRCAUSE_OFS); - cause &= ~GT641XX_IRQ_TO_BIT(d->irq); + cause &= ~GT641XX_IRQ_TO_BIT(irq); GT_WRITE(GT_INTRCAUSE_OFS, cause); raw_spin_unlock_irqrestore(>641xx_irq_lock, flags); } -static void mask_gt641xx_irq(struct irq_data *d) +static void mask_gt641xx_irq(unsigned int irq) { unsigned long flags; u32 mask; raw_spin_lock_irqsave(>641xx_irq_lock, flags); mask = GT_READ(GT_INTRMASK_OFS); - mask &= ~GT641XX_IRQ_TO_BIT(d->irq); + mask &= ~GT641XX_IRQ_TO_BIT(irq); GT_WRITE(GT_INTRMASK_OFS, mask); raw_spin_unlock_irqrestore(>641xx_irq_lock, flags); } -static void mask_ack_gt641xx_irq(struct irq_data *d) +static void mask_ack_gt641xx_irq(unsigned int irq) { unsigned long flags; u32 cause, mask; raw_spin_lock_irqsave(>641xx_irq_lock, flags); mask = GT_READ(GT_INTRMASK_OFS); - mask &= ~GT641XX_IRQ_TO_BIT(d->irq); + mask &= ~GT641XX_IRQ_TO_BIT(irq); GT_WRITE(GT_INTRMASK_OFS, mask); cause = GT_READ(GT_INTRCAUSE_OFS); - cause &= ~GT641XX_IRQ_TO_BIT(d->irq); + cause &= ~GT641XX_IRQ_TO_BIT(irq); GT_WRITE(GT_INTRCAUSE_OFS, cause); raw_spin_unlock_irqrestore(>641xx_irq_lock, flags); } -static void unmask_gt641xx_irq(struct irq_data *d) +static void unmask_gt641xx_irq(unsigned int irq) { unsigned long flags; u32 mask; raw_spin_lock_irqsave(>641xx_irq_lock, flags); mask = GT_READ(GT_INTRMASK_OFS); - mask |= GT641XX_IRQ_TO_BIT(d->irq); + mask |= GT641XX_IRQ_TO_BIT(irq); GT_WRITE(GT_INTRMASK_OFS, mask); raw_spin_unlock_irqrestore(>641xx_irq_lock, flags); } static struct irq_chip gt641xx_irq_chip = { .name = "GT641xx", - .irq_ack = ack_gt641xx_irq, - .irq_mask = mask_gt641xx_irq, - .irq_mask_ack = mask_ack_gt641xx_irq, - .irq_unmask = unmask_gt641xx_irq, + .ack = ack_gt641xx_irq, + .mask = mask_gt641xx_irq, + .mask_ack = mask_ack_gt641xx_irq, + .unmask = unmask_gt641xx_irq, }; void gt641xx_irq_dispatch(void) diff --git a/trunk/arch/mips/kernel/irq-msc01.c b/trunk/arch/mips/kernel/irq-msc01.c index fc800cd9947e..6a8cd28133d5 100644 --- a/trunk/arch/mips/kernel/irq-msc01.c +++ b/trunk/arch/mips/kernel/irq-msc01.c @@ -28,10 +28,8 @@ static unsigned long _icctrl_msc; static unsigned int irq_base; /* mask off an interrupt */ -static inline void mask_msc_irq(struct irq_data *d) +static inline void mask_msc_irq(unsigned int irq) { - unsigned int irq = d->irq; - if (irq < (irq_base + 32)) MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base)); else @@ -39,10 +37,8 @@ static inline void mask_msc_irq(struct irq_data *d) } /* unmask an interrupt */ -static inline void unmask_msc_irq(struct irq_data *d) +static inline void unmask_msc_irq(unsigned int irq) { - unsigned int irq = d->irq; - if (irq < (irq_base + 32)) MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base)); else @@ -52,11 +48,9 @@ static inline void unmask_msc_irq(struct irq_data *d) /* * Masks and ACKs an IRQ */ -static void level_mask_and_ack_msc_irq(struct irq_data *d) +static void level_mask_and_ack_msc_irq(unsigned int irq) { - unsigned int irq = d->irq; - - mask_msc_irq(d); + mask_msc_irq(irq); if (!cpu_has_veic) MSCIC_WRITE(MSC01_IC_EOI, 0); /* This actually needs to be a call into platform code */ @@ -66,11 +60,9 @@ static void level_mask_and_ack_msc_irq(struct irq_data *d) /* * Masks and ACKs an IRQ */ -static void edge_mask_and_ack_msc_irq(struct irq_data *d) +static void edge_mask_and_ack_msc_irq(unsigned int irq) { - unsigned int irq = d->irq; - - mask_msc_irq(d); + mask_msc_irq(irq); if (!cpu_has_veic) MSCIC_WRITE(MSC01_IC_EOI, 0); else { @@ -82,6 +74,15 @@ static void edge_mask_and_ack_msc_irq(struct irq_data *d) smtc_im_ack_irq(irq); } +/* + * End IRQ processing + */ +static void end_msc_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_msc_irq(irq); +} + /* * Interrupt handler for interrupts coming from SOC-it. */ @@ -106,20 +107,22 @@ static void msc_bind_eic_interrupt(int irq, int set) static struct irq_chip msc_levelirq_type = { .name = "SOC-it-Level", - .irq_ack = level_mask_and_ack_msc_irq, - .irq_mask = mask_msc_irq, - .irq_mask_ack = level_mask_and_ack_msc_irq, - .irq_unmask = unmask_msc_irq, - .irq_eoi = unmask_msc_irq, + .ack = level_mask_and_ack_msc_irq, + .mask = mask_msc_irq, + .mask_ack = level_mask_and_ack_msc_irq, + .unmask = unmask_msc_irq, + .eoi = unmask_msc_irq, + .end = end_msc_irq, }; static struct irq_chip msc_edgeirq_type = { .name = "SOC-it-Edge", - .irq_ack = edge_mask_and_ack_msc_irq, - .irq_mask = mask_msc_irq, - .irq_mask_ack = edge_mask_and_ack_msc_irq, - .irq_unmask = unmask_msc_irq, - .irq_eoi = unmask_msc_irq, + .ack = edge_mask_and_ack_msc_irq, + .mask = mask_msc_irq, + .mask_ack = edge_mask_and_ack_msc_irq, + .unmask = unmask_msc_irq, + .eoi = unmask_msc_irq, + .end = end_msc_irq, }; diff --git a/trunk/arch/mips/kernel/irq-rm7000.c b/trunk/arch/mips/kernel/irq-rm7000.c index fd24fd98b041..9731e8b47862 100644 --- a/trunk/arch/mips/kernel/irq-rm7000.c +++ b/trunk/arch/mips/kernel/irq-rm7000.c @@ -18,23 +18,23 @@ #include #include -static inline void unmask_rm7k_irq(struct irq_data *d) +static inline void unmask_rm7k_irq(unsigned int irq) { - set_c0_intcontrol(0x100 << (d->irq - RM7K_CPU_IRQ_BASE)); + set_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE)); } -static inline void mask_rm7k_irq(struct irq_data *d) +static inline void mask_rm7k_irq(unsigned int irq) { - clear_c0_intcontrol(0x100 << (d->irq - RM7K_CPU_IRQ_BASE)); + clear_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE)); } static struct irq_chip rm7k_irq_controller = { .name = "RM7000", - .irq_ack = mask_rm7k_irq, - .irq_mask = mask_rm7k_irq, - .irq_mask_ack = mask_rm7k_irq, - .irq_unmask = unmask_rm7k_irq, - .irq_eoi = unmask_rm7k_irq + .ack = mask_rm7k_irq, + .mask = mask_rm7k_irq, + .mask_ack = mask_rm7k_irq, + .unmask = unmask_rm7k_irq, + .eoi = unmask_rm7k_irq }; void __init rm7k_cpu_irq_init(void) diff --git a/trunk/arch/mips/kernel/irq-rm9000.c b/trunk/arch/mips/kernel/irq-rm9000.c index ca463ec9bad5..b7e4025b58a8 100644 --- a/trunk/arch/mips/kernel/irq-rm9000.c +++ b/trunk/arch/mips/kernel/irq-rm9000.c @@ -19,22 +19,22 @@ #include #include -static inline void unmask_rm9k_irq(struct irq_data *d) +static inline void unmask_rm9k_irq(unsigned int irq) { - set_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE)); + set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE)); } -static inline void mask_rm9k_irq(struct irq_data *d) +static inline void mask_rm9k_irq(unsigned int irq) { - clear_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE)); + clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE)); } -static inline void rm9k_cpu_irq_enable(struct irq_data *d) +static inline void rm9k_cpu_irq_enable(unsigned int irq) { unsigned long flags; local_irq_save(flags); - unmask_rm9k_irq(d); + unmask_rm9k_irq(irq); local_irq_restore(flags); } @@ -43,47 +43,50 @@ static inline void rm9k_cpu_irq_enable(struct irq_data *d) */ static void local_rm9k_perfcounter_irq_startup(void *args) { - rm9k_cpu_irq_enable(args); + unsigned int irq = (unsigned int) args; + + rm9k_cpu_irq_enable(irq); } -static unsigned int rm9k_perfcounter_irq_startup(struct irq_data *d) +static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq) { - on_each_cpu(local_rm9k_perfcounter_irq_startup, d, 1); + on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 1); return 0; } static void local_rm9k_perfcounter_irq_shutdown(void *args) { + unsigned int irq = (unsigned int) args; unsigned long flags; local_irq_save(flags); - mask_rm9k_irq(args); + mask_rm9k_irq(irq); local_irq_restore(flags); } -static void rm9k_perfcounter_irq_shutdown(struct irq_data *d) +static void rm9k_perfcounter_irq_shutdown(unsigned int irq) { - on_each_cpu(local_rm9k_perfcounter_irq_shutdown, d, 1); + on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 1); } static struct irq_chip rm9k_irq_controller = { .name = "RM9000", - .irq_ack = mask_rm9k_irq, - .irq_mask = mask_rm9k_irq, - .irq_mask_ack = mask_rm9k_irq, - .irq_unmask = unmask_rm9k_irq, - .irq_eoi = unmask_rm9k_irq + .ack = mask_rm9k_irq, + .mask = mask_rm9k_irq, + .mask_ack = mask_rm9k_irq, + .unmask = unmask_rm9k_irq, + .eoi = unmask_rm9k_irq }; static struct irq_chip rm9k_perfcounter_irq = { .name = "RM9000", - .irq_startup = rm9k_perfcounter_irq_startup, - .irq_shutdown = rm9k_perfcounter_irq_shutdown, - .irq_ack = mask_rm9k_irq, - .irq_mask = mask_rm9k_irq, - .irq_mask_ack = mask_rm9k_irq, - .irq_unmask = unmask_rm9k_irq, + .startup = rm9k_perfcounter_irq_startup, + .shutdown = rm9k_perfcounter_irq_shutdown, + .ack = mask_rm9k_irq, + .mask = mask_rm9k_irq, + .mask_ack = mask_rm9k_irq, + .unmask = unmask_rm9k_irq, }; unsigned int rm9000_perfcount_irq; diff --git a/trunk/arch/mips/kernel/irq.c b/trunk/arch/mips/kernel/irq.c index 1b68ebe1b458..4f93db58a79e 100644 --- a/trunk/arch/mips/kernel/irq.c +++ b/trunk/arch/mips/kernel/irq.c @@ -81,9 +81,48 @@ void ack_bad_irq(unsigned int irq) atomic_t irq_err_count; -int arch_show_interrupts(struct seq_file *p, int prec) +/* + * Generic, controller-independent functions: + */ + +int show_interrupts(struct seq_file *p, void *v) { - seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); + int i = *(loff_t *) v, j; + struct irqaction * action; + unsigned long flags; + + if (i == 0) { + seq_printf(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ", j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + raw_spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ", i); +#ifndef CONFIG_SMP + seq_printf(p, "%10u ", kstat_irqs(i)); +#else + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); +#endif + seq_printf(p, " %14s", 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'); +skip: + raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_putc(p, '\n'); + seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); + } return 0; } @@ -144,8 +183,8 @@ void __irq_entry do_IRQ(unsigned int irq) { irq_enter(); check_stack_overflow(); - if (!smtc_handle_on_other_cpu(irq)) - generic_handle_irq(irq); + __DO_IRQ_SMTC_HOOK(irq); + generic_handle_irq(irq); irq_exit(); } @@ -158,7 +197,7 @@ void __irq_entry do_IRQ(unsigned int irq) void __irq_entry do_IRQ_no_affinity(unsigned int irq) { irq_enter(); - smtc_im_backstop(irq); + __NO_AFFINITY_IRQ_SMTC_HOOK(irq); generic_handle_irq(irq); irq_exit(); } diff --git a/trunk/arch/mips/kernel/irq_cpu.c b/trunk/arch/mips/kernel/irq_cpu.c index fd945c56bc33..0262abe09121 100644 --- a/trunk/arch/mips/kernel/irq_cpu.c +++ b/trunk/arch/mips/kernel/irq_cpu.c @@ -37,38 +37,42 @@ #include #include -static inline void unmask_mips_irq(struct irq_data *d) +static inline void unmask_mips_irq(unsigned int irq) { - set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); + set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); irq_enable_hazard(); } -static inline void mask_mips_irq(struct irq_data *d) +static inline void mask_mips_irq(unsigned int irq) { - clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); + clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); irq_disable_hazard(); } static struct irq_chip mips_cpu_irq_controller = { .name = "MIPS", - .irq_ack = mask_mips_irq, - .irq_mask = mask_mips_irq, - .irq_mask_ack = mask_mips_irq, - .irq_unmask = unmask_mips_irq, - .irq_eoi = unmask_mips_irq, + .ack = mask_mips_irq, + .mask = mask_mips_irq, + .mask_ack = mask_mips_irq, + .unmask = unmask_mips_irq, + .eoi = unmask_mips_irq, }; /* * Basically the same as above but taking care of all the MT stuff */ -static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d) +#define unmask_mips_mt_irq unmask_mips_irq +#define mask_mips_mt_irq mask_mips_irq + +static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) { unsigned int vpflags = dvpe(); - clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); + clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE)); evpe(vpflags); - unmask_mips_irq(d); + unmask_mips_mt_irq(irq); + return 0; } @@ -76,22 +80,22 @@ static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d) * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for mips_cpu_irq_end. */ -static void mips_mt_cpu_irq_ack(struct irq_data *d) +static void mips_mt_cpu_irq_ack(unsigned int irq) { unsigned int vpflags = dvpe(); - clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); + clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE)); evpe(vpflags); - mask_mips_irq(d); + mask_mips_mt_irq(irq); } static struct irq_chip mips_mt_cpu_irq_controller = { .name = "MIPS", - .irq_startup = mips_mt_cpu_irq_startup, - .irq_ack = mips_mt_cpu_irq_ack, - .irq_mask = mask_mips_irq, - .irq_mask_ack = mips_mt_cpu_irq_ack, - .irq_unmask = unmask_mips_irq, - .irq_eoi = unmask_mips_irq, + .startup = mips_mt_cpu_irq_startup, + .ack = mips_mt_cpu_irq_ack, + .mask = mask_mips_mt_irq, + .mask_ack = mips_mt_cpu_irq_ack, + .unmask = unmask_mips_mt_irq, + .eoi = unmask_mips_mt_irq, }; void __init mips_cpu_irq_init(void) diff --git a/trunk/arch/mips/kernel/irq_txx9.c b/trunk/arch/mips/kernel/irq_txx9.c index 526e1581549a..95a96f69172d 100644 --- a/trunk/arch/mips/kernel/irq_txx9.c +++ b/trunk/arch/mips/kernel/irq_txx9.c @@ -63,9 +63,9 @@ static struct { unsigned char mode; } txx9irq[TXx9_MAX_IR] __read_mostly; -static void txx9_irq_unmask(struct irq_data *d) +static void txx9_irq_unmask(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16 ) / 2]; int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8; @@ -79,9 +79,9 @@ static void txx9_irq_unmask(struct irq_data *d) #endif } -static inline void txx9_irq_mask(struct irq_data *d) +static inline void txx9_irq_mask(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16) / 2]; int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8; @@ -99,19 +99,19 @@ static inline void txx9_irq_mask(struct irq_data *d) #endif } -static void txx9_irq_mask_ack(struct irq_data *d) +static void txx9_irq_mask_ack(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; - txx9_irq_mask(d); + txx9_irq_mask(irq); /* clear edge detection */ if (unlikely(TXx9_IRCR_EDGE(txx9irq[irq_nr].mode))) __raw_writel(TXx9_IRSCR_EIClrE | irq_nr, &txx9_ircptr->scr); } -static int txx9_irq_set_type(struct irq_data *d, unsigned int flow_type) +static int txx9_irq_set_type(unsigned int irq, unsigned int flow_type) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 cr; u32 __iomem *crp; int ofs; @@ -139,11 +139,11 @@ static int txx9_irq_set_type(struct irq_data *d, unsigned int flow_type) static struct irq_chip txx9_irq_chip = { .name = "TXX9", - .irq_ack = txx9_irq_mask_ack, - .irq_mask = txx9_irq_mask, - .irq_mask_ack = txx9_irq_mask_ack, - .irq_unmask = txx9_irq_unmask, - .irq_set_type = txx9_irq_set_type, + .ack = txx9_irq_mask_ack, + .mask = txx9_irq_mask, + .mask_ack = txx9_irq_mask_ack, + .unmask = txx9_irq_unmask, + .set_type = txx9_irq_set_type, }; void __init txx9_irq_init(unsigned long baseaddr) diff --git a/trunk/arch/mips/kernel/scall32-o32.S b/trunk/arch/mips/kernel/scall32-o32.S index 7f5468b38d4c..fbaabad0e6e2 100644 --- a/trunk/arch/mips/kernel/scall32-o32.S +++ b/trunk/arch/mips/kernel/scall32-o32.S @@ -586,10 +586,6 @@ einval: li v0, -ENOSYS sys sys_fanotify_init 2 sys sys_fanotify_mark 6 sys sys_prlimit64 4 - sys sys_name_to_handle_at 5 - sys sys_open_by_handle_at 3 /* 4340 */ - sys sys_clock_adjtime 2 - sys sys_syncfs 1 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/trunk/arch/mips/kernel/scall64-64.S b/trunk/arch/mips/kernel/scall64-64.S index a2e1fcbc41dc..3f4179283207 100644 --- a/trunk/arch/mips/kernel/scall64-64.S +++ b/trunk/arch/mips/kernel/scall64-64.S @@ -425,8 +425,4 @@ sys_call_table: PTR sys_fanotify_init /* 5295 */ PTR sys_fanotify_mark PTR sys_prlimit64 - PTR sys_name_to_handle_at - PTR sys_open_by_handle_at - PTR sys_clock_adjtime /* 5300 */ - PTR sys_syncfs .size sys_call_table,.-sys_call_table diff --git a/trunk/arch/mips/kernel/scall64-n32.S b/trunk/arch/mips/kernel/scall64-n32.S index b2c7624995b8..f08ece6d8acc 100644 --- a/trunk/arch/mips/kernel/scall64-n32.S +++ b/trunk/arch/mips/kernel/scall64-n32.S @@ -425,8 +425,4 @@ EXPORT(sysn32_call_table) PTR sys_fanotify_init /* 6300 */ PTR sys_fanotify_mark PTR sys_prlimit64 - PTR sys_name_to_handle_at - PTR sys_open_by_handle_at - PTR compat_sys_clock_adjtime /* 6305 */ - PTR sys_syncfs .size sysn32_call_table,.-sysn32_call_table diff --git a/trunk/arch/mips/kernel/scall64-o32.S b/trunk/arch/mips/kernel/scall64-o32.S index 049a9c8c49a0..78d768a3e19d 100644 --- a/trunk/arch/mips/kernel/scall64-o32.S +++ b/trunk/arch/mips/kernel/scall64-o32.S @@ -543,8 +543,4 @@ sys_call_table: PTR sys_fanotify_init PTR sys_32_fanotify_mark PTR sys_prlimit64 - PTR sys_name_to_handle_at - PTR compat_sys_open_by_handle_at /* 4340 */ - PTR compat_sys_clock_adjtime - PTR sys_syncfs .size sys_call_table,.-sys_call_table diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index f7e2c7807d7b..39c08254b0f1 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/arch/mips/kernel/smtc.c @@ -677,9 +677,8 @@ void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity) */ } -void smtc_forward_irq(struct irq_data *d) +void smtc_forward_irq(unsigned int irq) { - unsigned int irq = d->irq; int target; /* @@ -693,7 +692,7 @@ void smtc_forward_irq(struct irq_data *d) * and efficiency, we just pick the easiest one to find. */ - target = cpumask_first(d->affinity); + target = cpumask_first(irq_desc[irq].affinity); /* * We depend on the platform code to have correctly processed @@ -708,10 +707,12 @@ void smtc_forward_irq(struct irq_data *d) */ /* If no one is eligible, service locally */ - if (target >= NR_CPUS) + if (target >= NR_CPUS) { do_IRQ_no_affinity(irq); - else - smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq); + return; + } + + smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq); } #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ diff --git a/trunk/arch/mips/lasat/interrupt.c b/trunk/arch/mips/lasat/interrupt.c index 670e3e70d198..1353fb135ed3 100644 --- a/trunk/arch/mips/lasat/interrupt.c +++ b/trunk/arch/mips/lasat/interrupt.c @@ -32,24 +32,24 @@ static volatile int *lasat_int_status; static volatile int *lasat_int_mask; static volatile int lasat_int_mask_shift; -void disable_lasat_irq(struct irq_data *d) +void disable_lasat_irq(unsigned int irq_nr) { - unsigned int irq_nr = d->irq - LASAT_IRQ_BASE; - + irq_nr -= LASAT_IRQ_BASE; *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; } -void enable_lasat_irq(struct irq_data *d) +void enable_lasat_irq(unsigned int irq_nr) { - unsigned int irq_nr = d->irq - LASAT_IRQ_BASE; - + irq_nr -= LASAT_IRQ_BASE; *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; } static struct irq_chip lasat_irq_type = { .name = "Lasat", - .irq_mask = disable_lasat_irq, - .irq_unmask = enable_lasat_irq, + .ack = disable_lasat_irq, + .mask = disable_lasat_irq, + .mask_ack = disable_lasat_irq, + .unmask = enable_lasat_irq, }; static inline int ls1bit32(unsigned int x) diff --git a/trunk/arch/mips/loongson/common/bonito-irq.c b/trunk/arch/mips/loongson/common/bonito-irq.c index 1549361696ad..2dc2a4cc632a 100644 --- a/trunk/arch/mips/loongson/common/bonito-irq.c +++ b/trunk/arch/mips/loongson/common/bonito-irq.c @@ -16,22 +16,24 @@ #include -static inline void bonito_irq_enable(struct irq_data *d) +static inline void bonito_irq_enable(unsigned int irq) { - LOONGSON_INTENSET = (1 << (d->irq - LOONGSON_IRQ_BASE)); + LOONGSON_INTENSET = (1 << (irq - LOONGSON_IRQ_BASE)); mmiowb(); } -static inline void bonito_irq_disable(struct irq_data *d) +static inline void bonito_irq_disable(unsigned int irq) { - LOONGSON_INTENCLR = (1 << (d->irq - LOONGSON_IRQ_BASE)); + LOONGSON_INTENCLR = (1 << (irq - LOONGSON_IRQ_BASE)); mmiowb(); } static struct irq_chip bonito_irq_type = { - .name = "bonito_irq", - .irq_mask = bonito_irq_disable, - .irq_unmask = bonito_irq_enable, + .name = "bonito_irq", + .ack = bonito_irq_disable, + .mask = bonito_irq_disable, + .mask_ack = bonito_irq_disable, + .unmask = bonito_irq_enable, }; static struct irqaction __maybe_unused dma_timeout_irqaction = { diff --git a/trunk/arch/mips/mipssim/sim_smtc.c b/trunk/arch/mips/mipssim/sim_smtc.c index 30df47258c2c..5da30b6a65b7 100644 --- a/trunk/arch/mips/mipssim/sim_smtc.c +++ b/trunk/arch/mips/mipssim/sim_smtc.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -58,6 +57,8 @@ static inline void ssmtc_send_ipi_mask(const struct cpumask *mask, */ static void __cpuinit ssmtc_init_secondary(void) { + void smtc_init_secondary(void); + smtc_init_secondary(); } diff --git a/trunk/arch/mips/mti-malta/malta-smtc.c b/trunk/arch/mips/mti-malta/malta-smtc.c index e67891521ac1..192cfd2a539c 100644 --- a/trunk/arch/mips/mti-malta/malta-smtc.c +++ b/trunk/arch/mips/mti-malta/malta-smtc.c @@ -34,6 +34,7 @@ static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action) */ static void __cpuinit msmtc_init_secondary(void) { + void smtc_init_secondary(void); int myvpe; /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ @@ -113,8 +114,7 @@ struct plat_smp_ops msmtc_smp_ops = { */ -int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, - bool force) +int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity) { cpumask_t tmask; int cpu = 0; @@ -144,7 +144,7 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu)) cpu_clear(cpu, tmask); } - cpumask_copy(d->affinity, &tmask); + cpumask_copy(irq_desc[irq].affinity, &tmask); if (cpus_empty(tmask)) /* @@ -155,8 +155,8 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, "IRQ affinity leaves no legal CPU for IRQ %d\n", irq); /* Do any generic SMTC IRQ affinity setup */ - smtc_set_irq_affinity(d->irq, tmask); + smtc_set_irq_affinity(irq, tmask); - return IRQ_SET_MASK_OK_NOCOPY; + return 0; } #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ diff --git a/trunk/arch/mips/pmc-sierra/Kconfig b/trunk/arch/mips/pmc-sierra/Kconfig index bbd76082fa8c..8d798497c614 100644 --- a/trunk/arch/mips/pmc-sierra/Kconfig +++ b/trunk/arch/mips/pmc-sierra/Kconfig @@ -23,8 +23,6 @@ config PMC_MSP7120_GW select SYS_SUPPORTS_MULTITHREADING select IRQ_MSP_CIC select HW_HAS_PCI - select MSP_HAS_USB - select MSP_ETH config PMC_MSP7120_FPGA bool "PMC-Sierra MSP7120 FPGA" @@ -37,16 +35,3 @@ endchoice config HYPERTRANSPORT bool "Hypertransport Support for PMC-Sierra Yosemite" depends on PMC_YOSEMITE - -config MSP_HAS_USB - boolean - depends on PMC_MSP - -config MSP_ETH - boolean - select MSP_HAS_MAC - depends on PMC_MSP - -config MSP_HAS_MAC - boolean - depends on PMC_MSP diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/Makefile b/trunk/arch/mips/pmc-sierra/msp71xx/Makefile index cefba7733b73..e107f79b1491 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/Makefile +++ b/trunk/arch/mips/pmc-sierra/msp71xx/Makefile @@ -6,9 +6,7 @@ obj-y += msp_prom.o msp_setup.o msp_irq.o \ obj-$(CONFIG_HAVE_GPIO_LIB) += gpio.o gpio_extended.o obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o -obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o msp_irq_per.o +obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o obj-$(CONFIG_PCI) += msp_pci.o -obj-$(CONFIG_MSP_HAS_MAC) += msp_eth.o -obj-$(CONFIG_MSP_HAS_USB) += msp_usb.o -obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o -obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o +obj-$(CONFIG_MSPETH) += msp_eth.o +obj-$(CONFIG_USB_MSP71XX) += msp_usb.o diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_eth.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_eth.c deleted file mode 100644 index c584df393de2..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_eth.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * The setup file for ethernet related hardware on PMC-Sierra MSP processors. - * - * Copyright 2010 PMC-Sierra, 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. - * - * 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 -#include -#include -#include -#include -#include -#include -#include - - -#define MSP_ETHERNET_GPIO0 14 -#define MSP_ETHERNET_GPIO1 15 -#define MSP_ETHERNET_GPIO2 16 - -#ifdef CONFIG_MSP_HAS_TSMAC -#define MSP_TSMAC_SIZE 0x10020 -#define MSP_TSMAC_ID "pmc_tsmac" - -static struct resource msp_tsmac0_resources[] = { - [0] = { - .start = MSP_MAC0_BASE, - .end = MSP_MAC0_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC0, - .end = MSP_INT_MAC0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource msp_tsmac1_resources[] = { - [0] = { - .start = MSP_MAC1_BASE, - .end = MSP_MAC1_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC1, - .end = MSP_INT_MAC1, - .flags = IORESOURCE_IRQ, - }, -}; -static struct resource msp_tsmac2_resources[] = { - [0] = { - .start = MSP_MAC2_BASE, - .end = MSP_MAC2_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_SAR, - .end = MSP_INT_SAR, - .flags = IORESOURCE_IRQ, - }, -}; - - -static struct platform_device tsmac_device[] = { - [0] = { - .name = MSP_TSMAC_ID, - .id = 0, - .num_resources = ARRAY_SIZE(msp_tsmac0_resources), - .resource = msp_tsmac0_resources, - }, - [1] = { - .name = MSP_TSMAC_ID, - .id = 1, - .num_resources = ARRAY_SIZE(msp_tsmac1_resources), - .resource = msp_tsmac1_resources, - }, - [2] = { - .name = MSP_TSMAC_ID, - .id = 2, - .num_resources = ARRAY_SIZE(msp_tsmac2_resources), - .resource = msp_tsmac2_resources, - }, -}; -#define msp_eth_devs tsmac_device - -#else -/* If it is not TSMAC assume MSP_ETH (100Mbps) */ -#define MSP_ETH_ID "pmc_mspeth" -#define MSP_ETH_SIZE 0xE0 -static struct resource msp_eth0_resources[] = { - [0] = { - .start = MSP_MAC0_BASE, - .end = MSP_MAC0_BASE + MSP_ETH_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC0, - .end = MSP_INT_MAC0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource msp_eth1_resources[] = { - [0] = { - .start = MSP_MAC1_BASE, - .end = MSP_MAC1_BASE + MSP_ETH_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC1, - .end = MSP_INT_MAC1, - .flags = IORESOURCE_IRQ, - }, -}; - - - -static struct platform_device mspeth_device[] = { - [0] = { - .name = MSP_ETH_ID, - .id = 0, - .num_resources = ARRAY_SIZE(msp_eth0_resources), - .resource = msp_eth0_resources, - }, - [1] = { - .name = MSP_ETH_ID, - .id = 1, - .num_resources = ARRAY_SIZE(msp_eth1_resources), - .resource = msp_eth1_resources, - }, - -}; -#define msp_eth_devs mspeth_device - -#endif -int __init msp_eth_setup(void) -{ - int i, ret = 0; - - /* Configure the GPIO and take the ethernet PHY out of reset */ - msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO0); - msp_gpio_pin_hi(MSP_ETHERNET_GPIO0); - -#ifdef CONFIG_MSP_HAS_TSMAC - /* 3 phys on boards with TSMAC */ - msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO1); - msp_gpio_pin_hi(MSP_ETHERNET_GPIO1); - - msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO2); - msp_gpio_pin_hi(MSP_ETHERNET_GPIO2); -#endif - for (i = 0; i < ARRAY_SIZE(msp_eth_devs); i++) { - ret = platform_device_register(&msp_eth_devs[i]); - printk(KERN_INFO "device: %d, return value = %d\n", i, ret); - if (ret) { - platform_device_unregister(&msp_eth_devs[i]); - break; - } - } - - if (ret) - printk(KERN_WARNING "Could not initialize " - "MSPETH device structures.\n"); - - return ret; -} -subsys_initcall(msp_eth_setup); diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c index 4531c4a514bc..734d598a2e3a 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c @@ -19,6 +19,8 @@ #include +extern void msp_int_handle(void); + /* SLP bases systems */ extern void msp_slp_irq_init(void); extern void msp_slp_irq_dispatch(void); @@ -27,18 +29,6 @@ extern void msp_slp_irq_dispatch(void); extern void msp_cic_irq_init(void); extern void msp_cic_irq_dispatch(void); -/* VSMP support init */ -extern void msp_vsmp_int_init(void); - -/* vectored interrupt implementation */ - -/* SW0/1 interrupts are used for SMP/SMTC */ -static inline void mac0_int_dispatch(void) { do_IRQ(MSP_INT_MAC0); } -static inline void mac1_int_dispatch(void) { do_IRQ(MSP_INT_MAC1); } -static inline void mac2_int_dispatch(void) { do_IRQ(MSP_INT_SAR); } -static inline void usb_int_dispatch(void) { do_IRQ(MSP_INT_USB); } -static inline void sec_int_dispatch(void) { do_IRQ(MSP_INT_SEC); } - /* * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded * hierarchical system. The first level are the direct MIPS interrupts @@ -106,57 +96,29 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) do_IRQ(MSP_INT_SW1); } -static struct irqaction cic_cascade_msp = { +static struct irqaction cascade_msp = { .handler = no_action, - .name = "MSP CIC cascade" + .name = "MSP cascade" }; -static struct irqaction per_cascade_msp = { - .handler = no_action, - .name = "MSP PER cascade" -}; void __init arch_init_irq(void) { - /* assume we'll be using vectored interrupt mode except in UP mode*/ -#ifdef CONFIG_MIPS_MT - BUG_ON(!cpu_has_vint); -#endif /* initialize the 1st-level CPU based interrupt controller */ mips_cpu_irq_init(); #ifdef CONFIG_IRQ_MSP_CIC msp_cic_irq_init(); -#ifdef CONFIG_MIPS_MT - set_vi_handler(MSP_INT_CIC, msp_cic_irq_dispatch); - set_vi_handler(MSP_INT_MAC0, mac0_int_dispatch); - set_vi_handler(MSP_INT_MAC1, mac1_int_dispatch); - set_vi_handler(MSP_INT_SAR, mac2_int_dispatch); - set_vi_handler(MSP_INT_USB, usb_int_dispatch); - set_vi_handler(MSP_INT_SEC, sec_int_dispatch); -#ifdef CONFIG_MIPS_MT_SMP - msp_vsmp_int_init(); -#elif defined CONFIG_MIPS_MT_SMTC - /*Set hwmask for all platform devices */ - irq_hwmask[MSP_INT_MAC0] = C_IRQ0; - irq_hwmask[MSP_INT_MAC1] = C_IRQ1; - irq_hwmask[MSP_INT_USB] = C_IRQ2; - irq_hwmask[MSP_INT_SAR] = C_IRQ3; - irq_hwmask[MSP_INT_SEC] = C_IRQ5; - -#endif /* CONFIG_MIPS_MT_SMP */ -#endif /* CONFIG_MIPS_MT */ - /* setup the cascaded interrupts */ - setup_irq(MSP_INT_CIC, &cic_cascade_msp); - setup_irq(MSP_INT_PER, &per_cascade_msp); + /* setup the cascaded interrupts */ + setup_irq(MSP_INT_CIC, &cascade_msp); + setup_irq(MSP_INT_PER, &cascade_msp); #else /* setup the 2nd-level SLP register based interrupt controller */ - /* VSMP /SMTC support support is not enabled for SLP */ msp_slp_irq_init(); /* setup the cascaded SLP/PER interrupts */ - setup_irq(MSP_INT_SLP, &cic_cascade_msp); - setup_irq(MSP_INT_PER, &per_cascade_msp); + setup_irq(MSP_INT_SLP, &cascade_msp); + setup_irq(MSP_INT_PER, &cascade_msp); #endif } diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c index 352f29d9226f..07e71ff2433f 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c @@ -1,7 +1,8 @@ /* - * Copyright 2010 PMC-Sierra, Inc, derived from irq_cpu.c + * This file define the irq handler for MSP SLM subsystem interrupts. * - * This file define the irq handler for MSP CIC subsystem interrupts. + * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c + * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.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 @@ -15,203 +16,119 @@ #include #include -#include #include #include #include /* - * External API + * NOTE: We are only enabling support for VPE0 right now. */ -extern void msp_per_irq_init(void); -extern void msp_per_irq_dispatch(void); - -/* - * Convenience Macro. Should be somewhere generic. - */ -#define get_current_vpe() \ - ((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE) - -#ifdef CONFIG_SMP - -#define LOCK_VPE(flags, mtflags) \ -do { \ - local_irq_save(flags); \ - mtflags = dmt(); \ -} while (0) - -#define UNLOCK_VPE(flags, mtflags) \ -do { \ - emt(mtflags); \ - local_irq_restore(flags);\ -} while (0) - -#define LOCK_CORE(flags, mtflags) \ -do { \ - local_irq_save(flags); \ - mtflags = dvpe(); \ -} while (0) - -#define UNLOCK_CORE(flags, mtflags) \ -do { \ - evpe(mtflags); \ - local_irq_restore(flags);\ -} while (0) - -#else - -#define LOCK_VPE(flags, mtflags) -#define UNLOCK_VPE(flags, mtflags) -#endif - -/* ensure writes to cic are completed */ -static inline void cic_wmb(void) +static inline void unmask_msp_cic_irq(unsigned int irq) { - const volatile void __iomem *cic_mem = CIC_VPE0_MSK_REG; - volatile u32 dummy_read; - wmb(); - dummy_read = __raw_readl(cic_mem); - dummy_read++; + /* check for PER interrupt range */ + if (irq < MSP_PER_INTBASE) + *CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE)); + else + *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE)); } -static void unmask_cic_irq(struct irq_data *d) +static inline void mask_msp_cic_irq(unsigned int irq) { - volatile u32 *cic_msk_reg = CIC_VPE0_MSK_REG; - int vpe; -#ifdef CONFIG_SMP - unsigned int mtflags; - unsigned long flags; - - /* - * Make sure we have IRQ affinity. It may have changed while - * we were processing the IRQ. - */ - if (!cpumask_test_cpu(smp_processor_id(), d->affinity)) - return; -#endif - - vpe = get_current_vpe(); - LOCK_VPE(flags, mtflags); - cic_msk_reg[vpe] |= (1 << (d->irq - MSP_CIC_INTBASE)); - UNLOCK_VPE(flags, mtflags); - cic_wmb(); + /* check for PER interrupt range */ + if (irq < MSP_PER_INTBASE) + *CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE)); + else + *PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE)); } -static void mask_cic_irq(struct irq_data *d) -{ - volatile u32 *cic_msk_reg = CIC_VPE0_MSK_REG; - int vpe = get_current_vpe(); -#ifdef CONFIG_SMP - unsigned long flags, mtflags; -#endif - LOCK_VPE(flags, mtflags); - cic_msk_reg[vpe] &= ~(1 << (d->irq - MSP_CIC_INTBASE)); - UNLOCK_VPE(flags, mtflags); - cic_wmb(); -} -static void msp_cic_irq_ack(struct irq_data *d) -{ - mask_cic_irq(d); - /* - * Only really necessary for 18, 16-14 and sometimes 3:0 - * (since these can be edge sensitive) but it doesn't - * hurt for the others - */ - *CIC_STS_REG = (1 << (d->irq - MSP_CIC_INTBASE)); - smtc_im_ack_irq(d->irq); -} - -/*Note: Limiting to VSMP . Not tested in SMTC */ - -#ifdef CONFIG_MIPS_MT_SMP -static int msp_cic_irq_set_affinity(struct irq_data *d, - const struct cpumask *cpumask, bool force) +/* + * While we ack the interrupt interrupts are disabled and thus we don't need + * to deal with concurrency issues. Same for msp_cic_irq_end. + */ +static inline void ack_msp_cic_irq(unsigned int irq) { - int cpu; - unsigned long flags; - unsigned int mtflags; - unsigned long imask = (1 << (irq - MSP_CIC_INTBASE)); - volatile u32 *cic_mask = (volatile u32 *)CIC_VPE0_MSK_REG; - - /* timer balancing should be disabled in kernel code */ - BUG_ON(irq == MSP_INT_VPE0_TIMER || irq == MSP_INT_VPE1_TIMER); - - LOCK_CORE(flags, mtflags); - /* enable if any of each VPE's TCs require this IRQ */ - for_each_online_cpu(cpu) { - if (cpumask_test_cpu(cpu, cpumask)) - cic_mask[cpu] |= imask; - else - cic_mask[cpu] &= ~imask; - - } - - UNLOCK_CORE(flags, mtflags); - return 0; + mask_msp_cic_irq(irq); + /* + * only really necessary for 18, 16-14 and sometimes 3:0 (since + * these can be edge sensitive) but it doesn't hurt for the others. + */ + + /* check for PER interrupt range */ + if (irq < MSP_PER_INTBASE) + *CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE)); + else + *PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE)); } -#endif static struct irq_chip msp_cic_irq_controller = { .name = "MSP_CIC", - .irq_mask = mask_cic_irq, - .irq_mask_ack = msp_cic_irq_ack, - .irq_unmask = unmask_cic_irq, - .irq_ack = msp_cic_irq_ack, -#ifdef CONFIG_MIPS_MT_SMP - .irq_set_affinity = msp_cic_irq_set_affinity, -#endif + .ack = ack_msp_cic_irq, + .mask = ack_msp_cic_irq, + .mask_ack = ack_msp_cic_irq, + .unmask = unmask_msp_cic_irq, }; + void __init msp_cic_irq_init(void) { int i; + /* Mask/clear interrupts. */ *CIC_VPE0_MSK_REG = 0x00000000; - *CIC_VPE1_MSK_REG = 0x00000000; + *PER_INT_MSK_REG = 0x00000000; *CIC_STS_REG = 0xFFFFFFFF; + *PER_INT_STS_REG = 0xFFFFFFFF; + +#if defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_EVAL) /* - * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI. - * These inputs map to EXT_INT_POL[6:4] inside the CIC. - * They are to be active low, level sensitive. - */ + * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI. + * These inputs map to EXT_INT_POL[6:4] inside the CIC. + * They are to be active low, level sensitive. + */ *CIC_EXT_CFG_REG &= 0xFFFF8F8F; +#endif /* initialize all the IRQ descriptors */ - for (i = MSP_CIC_INTBASE ; i < MSP_CIC_INTBASE + 32 ; i++) { + for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++) set_irq_chip_and_handler(i, &msp_cic_irq_controller, handle_level_irq); -#ifdef CONFIG_MIPS_MT_SMTC - /* Mask of CIC interrupt */ - irq_hwmask[i] = C_IRQ4; -#endif - } - - /* Initialize the PER interrupt sub-system */ - msp_per_irq_init(); } -/* CIC masked by CIC vector processing before dispatch called */ void msp_cic_irq_dispatch(void) { - volatile u32 *cic_msk_reg = (volatile u32 *)CIC_VPE0_MSK_REG; - u32 cic_mask; - u32 pending; - int cic_status = *CIC_STS_REG; - cic_mask = cic_msk_reg[get_current_vpe()]; - pending = cic_status & cic_mask; - if (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))) { - do_IRQ(MSP_INT_VPE0_TIMER); - } else if (pending & (1 << (MSP_INT_VPE1_TIMER - MSP_CIC_INTBASE))) { - do_IRQ(MSP_INT_VPE1_TIMER); - } else if (pending & (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) { - msp_per_irq_dispatch(); - } else if (pending) { - do_IRQ(ffs(pending) + MSP_CIC_INTBASE - 1); - } else{ - spurious_interrupt(); + u32 pending; + int intbase; + + intbase = MSP_CIC_INTBASE; + pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG; + + /* check for PER interrupt */ + if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) { + intbase = MSP_PER_INTBASE; + pending = *PER_INT_STS_REG & *PER_INT_MSK_REG; } + + /* check for spurious interrupt */ + if (pending == 0x00000000) { + printk(KERN_ERR + "Spurious %s interrupt? status %08x, mask %08x\n", + (intbase == MSP_CIC_INTBASE) ? "CIC" : "PER", + (intbase == MSP_CIC_INTBASE) ? + *CIC_STS_REG : *PER_INT_STS_REG, + (intbase == MSP_CIC_INTBASE) ? + *CIC_VPE0_MSK_REG : *PER_INT_MSK_REG); + return; + } + + /* check for the timer and dispatch it first */ + if ((intbase == MSP_CIC_INTBASE) && + (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE)))) + do_IRQ(MSP_INT_VPE0_TIMER); + else + do_IRQ(ffs(pending) + intbase - 1); } diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c deleted file mode 100644 index f9b9dcdfa9dd..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2010 PMC-Sierra, Inc, derived from irq_cpu.c - * - * This file define the irq handler for MSP PER subsystem interrupts. - * - * 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 -#include -#include -#include -#include - -#include -#include - -#include -#include - - -/* - * Convenience Macro. Should be somewhere generic. - */ -#define get_current_vpe() \ - ((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE) - -#ifdef CONFIG_SMP -/* - * The PER registers must be protected from concurrent access. - */ - -static DEFINE_SPINLOCK(per_lock); -#endif - -/* ensure writes to per are completed */ - -static inline void per_wmb(void) -{ - const volatile void __iomem *per_mem = PER_INT_MSK_REG; - volatile u32 dummy_read; - - wmb(); - dummy_read = __raw_readl(per_mem); - dummy_read++; -} - -static inline void unmask_per_irq(struct irq_data *d) -{ -#ifdef CONFIG_SMP - unsigned long flags; - spin_lock_irqsave(&per_lock, flags); - *PER_INT_MSK_REG |= (1 << (d->irq - MSP_PER_INTBASE)); - spin_unlock_irqrestore(&per_lock, flags); -#else - *PER_INT_MSK_REG |= (1 << (d->irq - MSP_PER_INTBASE)); -#endif - per_wmb(); -} - -static inline void mask_per_irq(struct irq_data *d) -{ -#ifdef CONFIG_SMP - unsigned long flags; - spin_lock_irqsave(&per_lock, flags); - *PER_INT_MSK_REG &= ~(1 << (d->irq - MSP_PER_INTBASE)); - spin_unlock_irqrestore(&per_lock, flags); -#else - *PER_INT_MSK_REG &= ~(1 << (d->irq - MSP_PER_INTBASE)); -#endif - per_wmb(); -} - -static inline void msp_per_irq_ack(struct irq_data *d) -{ - mask_per_irq(d); - /* - * In the PER interrupt controller, only bits 11 and 10 - * are write-to-clear, (SPI TX complete, SPI RX complete). - * It does nothing for any others. - */ - *PER_INT_STS_REG = (1 << (d->irq - MSP_PER_INTBASE)); -} - -#ifdef CONFIG_SMP -static int msp_per_irq_set_affinity(struct irq_data *d, - const struct cpumask *affinity, bool force) -{ - /* WTF is this doing ????? */ - unmask_per_irq(d); - return 0; -} -#endif - -static struct irq_chip msp_per_irq_controller = { - .name = "MSP_PER", - .irq_enable = unmask_per_irq. - .irq_disable = mask_per_irq, - .irq_ack = msp_per_irq_ack, -#ifdef CONFIG_SMP - .irq_set_affinity = msp_per_irq_set_affinity, -#endif -}; - -void __init msp_per_irq_init(void) -{ - int i; - /* Mask/clear interrupts. */ - *PER_INT_MSK_REG = 0x00000000; - *PER_INT_STS_REG = 0xFFFFFFFF; - /* initialize all the IRQ descriptors */ - for (i = MSP_PER_INTBASE; i < MSP_PER_INTBASE + 32; i++) { - irq_set_chip(i, &msp_per_irq_controller); -#ifdef CONFIG_MIPS_MT_SMTC - irq_hwmask[i] = C_IRQ4; -#endif - } -} - -void msp_per_irq_dispatch(void) -{ - u32 per_mask = *PER_INT_MSK_REG; - u32 per_status = *PER_INT_STS_REG; - u32 pending; - - pending = per_status & per_mask; - if (pending) { - do_IRQ(ffs(pending) + MSP_PER_INTBASE - 1); - } else { - spurious_interrupt(); - } -} diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c index 8f51e4adc438..61f390232346 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c @@ -21,10 +21,8 @@ #include #include -static inline void unmask_msp_slp_irq(struct irq_data *d) +static inline void unmask_msp_slp_irq(unsigned int irq) { - unsigned int irq = d->irq; - /* check for PER interrupt range */ if (irq < MSP_PER_INTBASE) *SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE)); @@ -32,10 +30,8 @@ static inline void unmask_msp_slp_irq(struct irq_data *d) *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE)); } -static inline void mask_msp_slp_irq(struct irq_data *d) +static inline void mask_msp_slp_irq(unsigned int irq) { - unsigned int irq = d->irq; - /* check for PER interrupt range */ if (irq < MSP_PER_INTBASE) *SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE)); @@ -47,10 +43,8 @@ static inline void mask_msp_slp_irq(struct irq_data *d) * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for msp_slp_irq_end. */ -static inline void ack_msp_slp_irq(struct irq_data *d) +static inline void ack_msp_slp_irq(unsigned int irq) { - unsigned int irq = d->irq; - /* check for PER interrupt range */ if (irq < MSP_PER_INTBASE) *SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE)); @@ -60,9 +54,9 @@ static inline void ack_msp_slp_irq(struct irq_data *d) static struct irq_chip msp_slp_irq_controller = { .name = "MSP_SLP", - .irq_ack = ack_msp_slp_irq, - .irq_mask = mask_msp_slp_irq, - .irq_unmask = unmask_msp_slp_irq, + .ack = ack_msp_slp_irq, + .mask = mask_msp_slp_irq, + .unmask = unmask_msp_slp_irq, }; void __init msp_slp_irq_init(void) diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c index fb37a10e0309..a54e85b3cf29 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c @@ -146,8 +146,6 @@ void __init plat_mem_setup(void) pm_power_off = msp_power_off; } -extern struct plat_smp_ops msp_smtc_smp_ops; - void __init prom_init(void) { unsigned long family; @@ -228,14 +226,6 @@ void __init prom_init(void) */ msp_serial_setup(); -#ifdef CONFIG_MIPS_MT_SMP - register_smp_ops(&vsmp_smp_ops); -#endif - -#ifdef CONFIG_MIPS_MT_SMTC - register_smp_ops(&msp_smtc_smp_ops); -#endif - #ifdef CONFIG_PMCTWILED /* * Setup LED states before the subsys_initcall loads other diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_smp.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_smp.c deleted file mode 100644 index 43a9e26e1c69..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_smp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc. - * Copyright (C) 2001 Ralf Baechle - * Copyright (C) 2010 PMC-Sierra, Inc. - * - * VSMP support for MSP platforms . Derived from malta vsmp support. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ -#include -#include - -#ifdef CONFIG_MIPS_MT_SMP -#define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */ -#define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for call */ - - -static void ipi_resched_dispatch(void) -{ - do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ); -} - -static void ipi_call_dispatch(void) -{ - do_IRQ(MIPS_CPU_IPI_CALL_IRQ); -} - -static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) -{ - return IRQ_HANDLED; -} - -static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) -{ - smp_call_function_interrupt(); - - return IRQ_HANDLED; -} - -static struct irqaction irq_resched = { - .handler = ipi_resched_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "IPI_resched" -}; - -static struct irqaction irq_call = { - .handler = ipi_call_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "IPI_call" -}; - -void __init arch_init_ipiirq(int irq, struct irqaction *action) -{ - setup_irq(irq, action); - set_irq_handler(irq, handle_percpu_irq); -} - -void __init msp_vsmp_int_init(void) -{ - set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); - set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); - arch_init_ipiirq(MIPS_CPU_IPI_RESCHED_IRQ, &irq_resched); - arch_init_ipiirq(MIPS_CPU_IPI_CALL_IRQ, &irq_call); -} -#endif /* CONFIG_MIPS_MT_SMP */ diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_smtc.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_smtc.c deleted file mode 100644 index c8dcc1c01e18..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_smtc.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * MSP71xx Platform-specific hooks for SMP operation - */ -#include -#include - -#include -#include -#include -#include - -/* VPE/SMP Prototype implements platform interfaces directly */ - -/* - * Cause the specified action to be performed on a targeted "CPU" - */ - -static void msp_smtc_send_ipi_single(int cpu, unsigned int action) -{ - /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ - smtc_send_ipi(cpu, LINUX_SMP_IPI, action); -} - -static void msp_smtc_send_ipi_mask(const struct cpumask *mask, - unsigned int action) -{ - unsigned int i; - - for_each_cpu(i, mask) - msp_smtc_send_ipi_single(i, action); -} - -/* - * Post-config but pre-boot cleanup entry point - */ -static void __cpuinit msp_smtc_init_secondary(void) -{ - int myvpe; - - /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ - myvpe = read_c0_tcbind() & TCBIND_CURVPE; - if (myvpe > 0) - change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 | - STATUSF_IP6 | STATUSF_IP7); - smtc_init_secondary(); -} - -/* - * Platform "CPU" startup hook - */ -static void __cpuinit msp_smtc_boot_secondary(int cpu, - struct task_struct *idle) -{ - smtc_boot_secondary(cpu, idle); -} - -/* - * SMP initialization finalization entry point - */ -static void __cpuinit msp_smtc_smp_finish(void) -{ - smtc_smp_finish(); -} - -/* - * Hook for after all CPUs are online - */ - -static void msp_smtc_cpus_done(void) -{ -} - -/* - * Platform SMP pre-initialization - * - * As noted above, we can assume a single CPU for now - * but it may be multithreaded. - */ - -static void __init msp_smtc_smp_setup(void) -{ - /* - * we won't get the definitive value until - * we've run smtc_prepare_cpus later, but - */ - - if (read_c0_config3() & (1 << 2)) - smp_num_siblings = smtc_build_cpu_map(0); -} - -static void __init msp_smtc_prepare_cpus(unsigned int max_cpus) -{ - smtc_prepare_cpus(max_cpus); -} - -struct plat_smp_ops msp_smtc_smp_ops = { - .send_ipi_single = msp_smtc_send_ipi_single, - .send_ipi_mask = msp_smtc_send_ipi_mask, - .init_secondary = msp_smtc_init_secondary, - .smp_finish = msp_smtc_smp_finish, - .cpus_done = msp_smtc_cpus_done, - .boot_secondary = msp_smtc_boot_secondary, - .smp_setup = msp_smtc_smp_setup, - .prepare_cpus = msp_smtc_prepare_cpus, -}; diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c index 8b42f307a7a7..01df84ce31e2 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -37,12 +36,6 @@ #include #include -#define get_current_vpe() \ - ((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE) - -static struct irqaction timer_vpe1; -static int tim_installed; - void __init plat_time_init(void) { char *endp, *s; @@ -90,12 +83,5 @@ void __init plat_time_init(void) unsigned int __cpuinit get_c0_compare_int(void) { - /* MIPS_MT modes may want timer for second VPE */ - if ((get_current_vpe()) && !tim_installed) { - memcpy(&timer_vpe1, &c0_compare_irqaction, sizeof(timer_vpe1)); - setup_irq(MSP_INT_VPE1_TIMER, &timer_vpe1); - tim_installed++; - } - - return get_current_vpe() ? MSP_INT_VPE1_TIMER : MSP_INT_VPE0_TIMER; + return MSP_INT_VPE0_TIMER; } diff --git a/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c index 9a1aef89bd4c..0ee01e359dd8 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c +++ b/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c @@ -1,7 +1,7 @@ /* * The setup file for USB related hardware on PMC-Sierra MSP processors. * - * Copyright 2006 PMC-Sierra, Inc. + * Copyright 2006-2007 PMC-Sierra, 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 @@ -23,8 +23,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET) +#include #include #include #include @@ -34,230 +34,117 @@ #include #include #include -#include - #if defined(CONFIG_USB_EHCI_HCD) -static struct resource msp_usbhost0_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB0_HS_START, - .end = MSP_USB0_HS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_USB, - .end = MSP_INT_USB, - .flags = IORESOURCE_IRQ, - }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB0_MAB_START, - .end = MSP_USB0_MAB_END, - .flags = IORESOURCE_MEM, - }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB0_ID_START, - .end = MSP_USB0_ID_END, - .flags = IORESOURCE_MEM, - }, -}; - -static u64 msp_usbhost0_dma_mask = 0xffffffffUL; - -static struct mspusb_device msp_usbhost0_device = { - .dev = { - .name = "pmcmsp-ehci", - .id = 0, - .dev = { - .dma_mask = &msp_usbhost0_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbhost0_resources), - .resource = msp_usbhost0_resources, - }, -}; - -/* MSP7140/MSP82XX has two USB2 hosts. */ -#ifdef CONFIG_MSP_HAS_DUAL_USB -static u64 msp_usbhost1_dma_mask = 0xffffffffUL; - -static struct resource msp_usbhost1_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB1_HS_START, - .end = MSP_USB1_HS_END, - .flags = IORESOURCE_MEM, +static struct resource msp_usbhost_resources [] = { + [0] = { + .start = MSP_USB_BASE_START, + .end = MSP_USB_BASE_END, + .flags = IORESOURCE_MEM, }, [1] = { .start = MSP_INT_USB, .end = MSP_INT_USB, .flags = IORESOURCE_IRQ, }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB1_MAB_START, - .end = MSP_USB1_MAB_END, - .flags = IORESOURCE_MEM, - }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB1_ID_START, - .end = MSP_USB1_ID_END, - .flags = IORESOURCE_MEM, - }, }; -static struct mspusb_device msp_usbhost1_device = { +static u64 msp_usbhost_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device msp_usbhost_device = { + .name = "pmcmsp-ehci", + .id = 0, .dev = { - .name = "pmcmsp-ehci", - .id = 1, - .dev = { - .dma_mask = &msp_usbhost1_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbhost1_resources), - .resource = msp_usbhost1_resources, + .dma_mask = &msp_usbhost_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), }, + .num_resources = ARRAY_SIZE(msp_usbhost_resources), + .resource = msp_usbhost_resources, }; -#endif /* CONFIG_MSP_HAS_DUAL_USB */ #endif /* CONFIG_USB_EHCI_HCD */ #if defined(CONFIG_USB_GADGET) -static struct resource msp_usbdev0_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB0_HS_START, - .end = MSP_USB0_HS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_USB, - .end = MSP_INT_USB, - .flags = IORESOURCE_IRQ, - }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB0_MAB_START, - .end = MSP_USB0_MAB_END, +static struct resource msp_usbdev_resources [] = { + [0] = { + .start = MSP_USB_BASE, + .end = MSP_USB_BASE_END, .flags = IORESOURCE_MEM, }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB0_ID_START, - .end = MSP_USB0_ID_END, - .flags = IORESOURCE_MEM, + [1] = { + .start = MSP_INT_USB, + .end = MSP_INT_USB, + .flags = IORESOURCE_IRQ, }, }; -static u64 msp_usbdev_dma_mask = 0xffffffffUL; +static u64 msp_usbdev_dma_mask = DMA_BIT_MASK(32); -/* This may need to be converted to a mspusb_device, too. */ -static struct mspusb_device msp_usbdev0_device = { +static struct platform_device msp_usbdev_device = { + .name = "msp71xx_udc", + .id = 0, .dev = { - .name = "msp71xx_udc", - .id = 0, - .dev = { - .dma_mask = &msp_usbdev_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbdev0_resources), - .resource = msp_usbdev0_resources, - }, -}; - -#ifdef CONFIG_MSP_HAS_DUAL_USB -static struct resource msp_usbdev1_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB1_HS_START, - .end = MSP_USB1_HS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_USB, - .end = MSP_INT_USB, - .flags = IORESOURCE_IRQ, - }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB1_MAB_START, - .end = MSP_USB1_MAB_END, - .flags = IORESOURCE_MEM, - }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB1_ID_START, - .end = MSP_USB1_ID_END, - .flags = IORESOURCE_MEM, + .dma_mask = &msp_usbdev_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), }, + .num_resources = ARRAY_SIZE(msp_usbdev_resources), + .resource = msp_usbdev_resources, }; +#endif /* CONFIG_USB_GADGET */ -/* This may need to be converted to a mspusb_device, too. */ -static struct mspusb_device msp_usbdev1_device = { - .dev = { - .name = "msp71xx_udc", - .id = 0, - .dev = { - .dma_mask = &msp_usbdev_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbdev1_resources), - .resource = msp_usbdev1_resources, - }, -}; +#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET) +static struct platform_device *msp_devs[1]; +#endif -#endif /* CONFIG_MSP_HAS_DUAL_USB */ -#endif /* CONFIG_USB_GADGET */ static int __init msp_usb_setup(void) { - char *strp; - char envstr[32]; - struct platform_device *msp_devs[NUM_USB_DEVS]; - unsigned int val; +#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET) + char *strp; + char envstr[32]; + unsigned int val = 0; + int result = 0; - /* construct environment name usbmode */ - /* set usbmode as pmon environment var */ /* - * Could this perhaps be integrated into the "features" env var? - * Use the features key "U", and follow with "H" for host-mode, - * "D" for device-mode. If it works for Ethernet, why not USB... - * -- hammtrev, 2007/03/22 + * construct environment name usbmode + * set usbmode as pmon environment var */ snprintf((char *)&envstr[0], sizeof(envstr), "usbmode"); - /* set default host mode */ +#if defined(CONFIG_USB_EHCI_HCD) + /* default to host mode */ val = 1; +#endif /* get environment string */ strp = prom_getenv((char *)&envstr[0]); if (strp) { - /* compare string */ if (!strcmp(strp, "device")) val = 0; } if (val) { #if defined(CONFIG_USB_EHCI_HCD) - msp_devs[0] = &msp_usbhost0_device.dev; - ppfinit("platform add USB HOST done %s.\n", msp_devs[0]->name); -#ifdef CONFIG_MSP_HAS_DUAL_USB - msp_devs[1] = &msp_usbhost1_device.dev; - ppfinit("platform add USB HOST done %s.\n", msp_devs[1]->name); -#endif -#else - ppfinit("%s: echi_hcd not supported\n", __FILE__); -#endif /* CONFIG_USB_EHCI_HCD */ - } else { + /* get host mode device */ + msp_devs[0] = &msp_usbhost_device; + ppfinit("platform add USB HOST done %s.\n", + msp_devs[0]->name); + + result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs)); +#endif /* CONFIG_USB_EHCI_HCD */ + } #if defined(CONFIG_USB_GADGET) + else { /* get device mode structure */ - msp_devs[0] = &msp_usbdev0_device.dev; - ppfinit("platform add USB DEVICE done %s.\n" - , msp_devs[0]->name); -#ifdef CONFIG_MSP_HAS_DUAL_USB - msp_devs[1] = &msp_usbdev1_device.dev; - ppfinit("platform add USB DEVICE done %s.\n" - , msp_devs[1]->name); -#endif -#else - ppfinit("%s: usb_gadget not supported\n", __FILE__); -#endif /* CONFIG_USB_GADGET */ + msp_devs[0] = &msp_usbdev_device; + ppfinit("platform add USB DEVICE done %s.\n", + msp_devs[0]->name); + + result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs)); } - /* add device */ - platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs)); +#endif /* CONFIG_USB_GADGET */ +#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */ - return 0; + return result; } subsys_initcall(msp_usb_setup); -#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */ diff --git a/trunk/arch/mips/pnx833x/common/interrupts.c b/trunk/arch/mips/pnx833x/common/interrupts.c index b226bcb0a2f4..941916f8aaff 100644 --- a/trunk/arch/mips/pnx833x/common/interrupts.c +++ b/trunk/arch/mips/pnx833x/common/interrupts.c @@ -152,6 +152,10 @@ static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) PNX833X_PIC_INT_REG(irq) = 0; } +static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ +#define IRQFLAG_STARTED 1 +#define IRQFLAG_DISABLED 2 + static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock); static unsigned int pnx833x_startup_pic_irq(unsigned int irq) @@ -160,54 +164,108 @@ static unsigned int pnx833x_startup_pic_irq(unsigned int irq) unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ pnx833x_hard_enable_pic_irq(pic_irq); + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); return 0; } -static void pnx833x_enable_pic_irq(struct irq_data *d) +static void pnx833x_shutdown_pic_irq(unsigned int irq) { unsigned long flags; - unsigned int pic_irq = d->irq - PNX833X_PIC_IRQ_BASE; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - pnx833x_hard_enable_pic_irq(pic_irq); + + irqflags[pic_irq] = 0; /* not started */ + pnx833x_hard_disable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_enable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] &= ~IRQFLAG_DISABLED; + if (irqflags[pic_irq] == IRQFLAG_STARTED) + pnx833x_hard_enable_pic_irq(pic_irq); + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); } -static void pnx833x_disable_pic_irq(struct irq_data *d) +static void pnx833x_disable_pic_irq(unsigned int irq) { unsigned long flags; - unsigned int pic_irq = d->irq - PNX833X_PIC_IRQ_BASE; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] |= IRQFLAG_DISABLED; pnx833x_hard_disable_pic_irq(pic_irq); + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); } +static void pnx833x_ack_pic_irq(unsigned int irq) +{ +} + +static void pnx833x_end_pic_irq(unsigned int irq) +{ +} + static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock); -static void pnx833x_enable_gpio_irq(struct irq_data *d) +static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_enable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); + return 0; +} + +static void pnx833x_enable_gpio_irq(unsigned int irq) { - int pin = d->irq - PNX833X_GPIO_IRQ_BASE; + int pin = irq - PNX833X_GPIO_IRQ_BASE; unsigned long flags; raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); pnx833x_gpio_enable_irq(pin); raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); } -static void pnx833x_disable_gpio_irq(struct irq_data *d) +static void pnx833x_disable_gpio_irq(unsigned int irq) { - int pin = d->irq - PNX833X_GPIO_IRQ_BASE; + int pin = irq - PNX833X_GPIO_IRQ_BASE; unsigned long flags; raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); pnx833x_gpio_disable_irq(pin); raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); } -static int pnx833x_set_type_gpio_irq(struct irq_data *d, unsigned int flow_type) +static void pnx833x_ack_gpio_irq(unsigned int irq) +{ +} + +static void pnx833x_end_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_clear_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) { - int pin = d->irq - PNX833X_GPIO_IRQ_BASE; + int pin = irq - PNX833X_GPIO_IRQ_BASE; int gpio_mode; switch (flow_type) { @@ -238,15 +296,23 @@ static int pnx833x_set_type_gpio_irq(struct irq_data *d, unsigned int flow_type) static struct irq_chip pnx833x_pic_irq_type = { .name = "PNX-PIC", - .irq_enable = pnx833x_enable_pic_irq, - .irq_disable = pnx833x_disable_pic_irq, + .startup = pnx833x_startup_pic_irq, + .shutdown = pnx833x_shutdown_pic_irq, + .enable = pnx833x_enable_pic_irq, + .disable = pnx833x_disable_pic_irq, + .ack = pnx833x_ack_pic_irq, + .end = pnx833x_end_pic_irq }; static struct irq_chip pnx833x_gpio_irq_type = { .name = "PNX-GPIO", - .irq_enable = pnx833x_enable_gpio_irq, - .irq_disable = pnx833x_disable_gpio_irq, - .irq_set_type = pnx833x_set_type_gpio_irq, + .startup = pnx833x_startup_gpio_irq, + .shutdown = pnx833x_disable_gpio_irq, + .enable = pnx833x_enable_gpio_irq, + .disable = pnx833x_disable_gpio_irq, + .ack = pnx833x_ack_gpio_irq, + .end = pnx833x_end_gpio_irq, + .set_type = pnx833x_set_type_gpio_irq }; void __init arch_init_irq(void) diff --git a/trunk/arch/mips/pnx8550/common/int.c b/trunk/arch/mips/pnx8550/common/int.c index dbdc35c3531d..cfed5051dc6d 100644 --- a/trunk/arch/mips/pnx8550/common/int.c +++ b/trunk/arch/mips/pnx8550/common/int.c @@ -114,10 +114,8 @@ static inline void unmask_gic_int(unsigned int irq_nr) PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr]; } -static inline void mask_irq(struct irq_data *d) +static inline void mask_irq(unsigned int irq_nr) { - unsigned int irq_nr = d->irq; - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { modify_cp0_intmask(1 << irq_nr, 0); } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && @@ -131,10 +129,8 @@ static inline void mask_irq(struct irq_data *d) } } -static inline void unmask_irq(struct irq_data *d) +static inline void unmask_irq(unsigned int irq_nr) { - unsigned int irq_nr = d->irq; - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { modify_cp0_intmask(0, 1 << irq_nr); } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && @@ -161,8 +157,10 @@ int pnx8550_set_gic_priority(int irq, int priority) static struct irq_chip level_irq_type = { .name = "PNX Level IRQ", - .irq_mask = mask_irq, - .irq_unmask = unmask_irq, + .ack = mask_irq, + .mask = mask_irq, + .mask_ack = mask_irq, + .unmask = unmask_irq, }; static struct irqaction gic_action = { @@ -182,8 +180,10 @@ void __init arch_init_irq(void) int i; int configPR; - for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) + for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + mask_irq(i); /* mask the irq just in case */ + } /* init of GIC/IPC interrupts */ /* should be done before cp0 since cp0 init enables the GIC int */ diff --git a/trunk/arch/mips/powertv/asic/irq_asic.c b/trunk/arch/mips/powertv/asic/irq_asic.c index 6f1c8ef6a719..e55382434155 100644 --- a/trunk/arch/mips/powertv/asic/irq_asic.c +++ b/trunk/arch/mips/powertv/asic/irq_asic.c @@ -21,10 +21,9 @@ #include -static inline void unmask_asic_irq(struct irq_data *d) +static inline void unmask_asic_irq(unsigned int irq) { unsigned long enable_bit; - unsigned int irq = d->irq; enable_bit = (1 << (irq & 0x1f)); @@ -46,10 +45,9 @@ static inline void unmask_asic_irq(struct irq_data *d) } } -static inline void mask_asic_irq(struct irq_data *d) +static inline void mask_asic_irq(unsigned int irq) { unsigned long disable_mask; - unsigned int irq = d->irq; disable_mask = ~(1 << (irq & 0x1f)); @@ -73,8 +71,11 @@ static inline void mask_asic_irq(struct irq_data *d) static struct irq_chip asic_irq_chip = { .name = "ASIC Level", - .irq_mask = mask_asic_irq, - .irq_unmask = unmask_asic_irq, + .ack = mask_asic_irq, + .mask = mask_asic_irq, + .mask_ack = mask_asic_irq, + .unmask = unmask_asic_irq, + .eoi = unmask_asic_irq, }; void __init asic_irq_init(void) diff --git a/trunk/arch/mips/rb532/irq.c b/trunk/arch/mips/rb532/irq.c index b32a768da894..ea6cec3c1e0d 100644 --- a/trunk/arch/mips/rb532/irq.c +++ b/trunk/arch/mips/rb532/irq.c @@ -111,10 +111,10 @@ static inline void ack_local_irq(unsigned int ip) clear_c0_cause(ipnum); } -static void rb532_enable_irq(struct irq_data *d) +static void rb532_enable_irq(unsigned int irq_nr) { - unsigned int group, intr_bit, irq_nr = d->irq; int ip = irq_nr - GROUP0_IRQ_BASE; + unsigned int group, intr_bit; volatile unsigned int *addr; if (ip < 0) @@ -132,10 +132,10 @@ static void rb532_enable_irq(struct irq_data *d) } } -static void rb532_disable_irq(struct irq_data *d) +static void rb532_disable_irq(unsigned int irq_nr) { - unsigned int group, intr_bit, mask, irq_nr = d->irq; int ip = irq_nr - GROUP0_IRQ_BASE; + unsigned int group, intr_bit, mask; volatile unsigned int *addr; if (ip < 0) { @@ -163,18 +163,18 @@ static void rb532_disable_irq(struct irq_data *d) } } -static void rb532_mask_and_ack_irq(struct irq_data *d) +static void rb532_mask_and_ack_irq(unsigned int irq_nr) { - rb532_disable_irq(d); - ack_local_irq(group_to_ip(irq_to_group(d->irq))); + rb532_disable_irq(irq_nr); + ack_local_irq(group_to_ip(irq_to_group(irq_nr))); } -static int rb532_set_type(struct irq_data *d, unsigned type) +static int rb532_set_type(unsigned int irq_nr, unsigned type) { - int gpio = d->irq - GPIO_MAPPED_IRQ_BASE; - int group = irq_to_group(d->irq); + int gpio = irq_nr - GPIO_MAPPED_IRQ_BASE; + int group = irq_to_group(irq_nr); - if (group != GPIO_MAPPED_IRQ_GROUP || d->irq > (GROUP4_IRQ_BASE + 13)) + if (group != GPIO_MAPPED_IRQ_GROUP || irq_nr > (GROUP4_IRQ_BASE + 13)) return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL; switch (type) { @@ -193,11 +193,11 @@ static int rb532_set_type(struct irq_data *d, unsigned type) static struct irq_chip rc32434_irq_type = { .name = "RB532", - .irq_ack = rb532_disable_irq, - .irq_mask = rb532_disable_irq, - .irq_mask_ack = rb532_mask_and_ack_irq, - .irq_unmask = rb532_enable_irq, - .irq_set_type = rb532_set_type, + .ack = rb532_disable_irq, + .mask = rb532_disable_irq, + .mask_ack = rb532_mask_and_ack_irq, + .unmask = rb532_enable_irq, + .set_type = rb532_set_type, }; void __init arch_init_irq(void) diff --git a/trunk/arch/mips/sgi-ip22/ip22-int.c b/trunk/arch/mips/sgi-ip22/ip22-int.c index e6e64750e90a..383f11d7f442 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-int.c +++ b/trunk/arch/mips/sgi-ip22/ip22-int.c @@ -31,80 +31,88 @@ static char lc3msk_to_irqnr[256]; extern int ip22_eisa_init(void); -static void enable_local0_irq(struct irq_data *d) +static void enable_local0_irq(unsigned int irq) { /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ - if (d->irq != SGI_MAP_0_IRQ) - sgint->imask0 |= (1 << (d->irq - SGINT_LOCAL0)); + if (irq != SGI_MAP_0_IRQ) + sgint->imask0 |= (1 << (irq - SGINT_LOCAL0)); } -static void disable_local0_irq(struct irq_data *d) +static void disable_local0_irq(unsigned int irq) { - sgint->imask0 &= ~(1 << (d->irq - SGINT_LOCAL0)); + sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); } static struct irq_chip ip22_local0_irq_type = { .name = "IP22 local 0", - .irq_mask = disable_local0_irq, - .irq_unmask = enable_local0_irq, + .ack = disable_local0_irq, + .mask = disable_local0_irq, + .mask_ack = disable_local0_irq, + .unmask = enable_local0_irq, }; -static void enable_local1_irq(struct irq_data *d) +static void enable_local1_irq(unsigned int irq) { /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ - if (d->irq != SGI_MAP_1_IRQ) - sgint->imask1 |= (1 << (d->irq - SGINT_LOCAL1)); + if (irq != SGI_MAP_1_IRQ) + sgint->imask1 |= (1 << (irq - SGINT_LOCAL1)); } -static void disable_local1_irq(struct irq_data *d) +static void disable_local1_irq(unsigned int irq) { - sgint->imask1 &= ~(1 << (d->irq - SGINT_LOCAL1)); + sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); } static struct irq_chip ip22_local1_irq_type = { .name = "IP22 local 1", - .irq_mask = disable_local1_irq, - .irq_unmask = enable_local1_irq, + .ack = disable_local1_irq, + .mask = disable_local1_irq, + .mask_ack = disable_local1_irq, + .unmask = enable_local1_irq, }; -static void enable_local2_irq(struct irq_data *d) +static void enable_local2_irq(unsigned int irq) { sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); - sgint->cmeimask0 |= (1 << (d->irq - SGINT_LOCAL2)); + sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); } -static void disable_local2_irq(struct irq_data *d) +static void disable_local2_irq(unsigned int irq) { - sgint->cmeimask0 &= ~(1 << (d->irq - SGINT_LOCAL2)); + sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); if (!sgint->cmeimask0) sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); } static struct irq_chip ip22_local2_irq_type = { .name = "IP22 local 2", - .irq_mask = disable_local2_irq, - .irq_unmask = enable_local2_irq, + .ack = disable_local2_irq, + .mask = disable_local2_irq, + .mask_ack = disable_local2_irq, + .unmask = enable_local2_irq, }; -static void enable_local3_irq(struct irq_data *d) +static void enable_local3_irq(unsigned int irq) { sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); - sgint->cmeimask1 |= (1 << (d->irq - SGINT_LOCAL3)); + sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3)); } -static void disable_local3_irq(struct irq_data *d) +static void disable_local3_irq(unsigned int irq) { - sgint->cmeimask1 &= ~(1 << (d->irq - SGINT_LOCAL3)); + sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3)); if (!sgint->cmeimask1) sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); } static struct irq_chip ip22_local3_irq_type = { .name = "IP22 local 3", - .irq_mask = disable_local3_irq, - .irq_unmask = enable_local3_irq, + .ack = disable_local3_irq, + .mask = disable_local3_irq, + .mask_ack = disable_local3_irq, + .unmask = enable_local3_irq, }; static void indy_local0_irqdispatch(void) diff --git a/trunk/arch/mips/sgi-ip27/ip27-irq.c b/trunk/arch/mips/sgi-ip27/ip27-irq.c index f2d09d7700dd..6a123ea72de5 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-irq.c +++ b/trunk/arch/mips/sgi-ip27/ip27-irq.c @@ -240,7 +240,7 @@ static int intr_disconnect_level(int cpu, int bit) } /* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int startup_bridge_irq(struct irq_data *d) +static unsigned int startup_bridge_irq(unsigned int irq) { struct bridge_controller *bc; bridgereg_t device; @@ -248,16 +248,16 @@ static unsigned int startup_bridge_irq(struct irq_data *d) int pin, swlevel; cpuid_t cpu; - pin = SLOT_FROM_PCI_IRQ(d->irq); - bc = IRQ_TO_BRIDGE(d->irq); + pin = SLOT_FROM_PCI_IRQ(irq); + bc = IRQ_TO_BRIDGE(irq); bridge = bc->base; - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); + pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); /* * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = find_level(&cpu, d->irq); + swlevel = find_level(&cpu, irq); bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); bridge->b_int_enable |= (1 << pin); bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ @@ -288,51 +288,53 @@ static unsigned int startup_bridge_irq(struct irq_data *d) } /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static void shutdown_bridge_irq(struct irq_data *d) +static void shutdown_bridge_irq(unsigned int irq) { - struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); + struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); bridge_t *bridge = bc->base; int pin, swlevel; cpuid_t cpu; - pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); - pin = SLOT_FROM_PCI_IRQ(d->irq); + pr_debug("bridge_shutdown: irq 0x%x\n", irq); + pin = SLOT_FROM_PCI_IRQ(irq); /* * map irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = find_level(&cpu, d->irq); + swlevel = find_level(&cpu, irq); intr_disconnect_level(cpu, swlevel); bridge->b_int_enable &= ~(1 << pin); bridge->b_wid_tflush; } -static inline void enable_bridge_irq(struct irq_data *d) +static inline void enable_bridge_irq(unsigned int irq) { cpuid_t cpu; int swlevel; - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + swlevel = find_level(&cpu, irq); /* Criminal offence */ intr_connect_level(cpu, swlevel); } -static inline void disable_bridge_irq(struct irq_data *d) +static inline void disable_bridge_irq(unsigned int irq) { cpuid_t cpu; int swlevel; - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + swlevel = find_level(&cpu, irq); /* Criminal offence */ intr_disconnect_level(cpu, swlevel); } static struct irq_chip bridge_irq_type = { .name = "bridge", - .irq_startup = startup_bridge_irq, - .irq_shutdown = shutdown_bridge_irq, - .irq_mask = disable_bridge_irq, - .irq_unmask = enable_bridge_irq, + .startup = startup_bridge_irq, + .shutdown = shutdown_bridge_irq, + .ack = disable_bridge_irq, + .mask = disable_bridge_irq, + .mask_ack = disable_bridge_irq, + .unmask = enable_bridge_irq, }; void __devinit register_bridge_irq(unsigned int irq) diff --git a/trunk/arch/mips/sgi-ip27/ip27-timer.c b/trunk/arch/mips/sgi-ip27/ip27-timer.c index c01f558a2a09..d6802d6d1f82 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-timer.c +++ b/trunk/arch/mips/sgi-ip27/ip27-timer.c @@ -36,18 +36,21 @@ #include #include -static void enable_rt_irq(struct irq_data *d) +static void enable_rt_irq(unsigned int irq) { } -static void disable_rt_irq(struct irq_data *d) +static void disable_rt_irq(unsigned int irq) { } static struct irq_chip rt_irq_type = { .name = "SN HUB RT timer", - .irq_mask = disable_rt_irq, - .irq_unmask = enable_rt_irq, + .ack = disable_rt_irq, + .mask = disable_rt_irq, + .mask_ack = disable_rt_irq, + .unmask = enable_rt_irq, + .eoi = enable_rt_irq, }; static int rt_next_event(unsigned long delta, struct clock_event_device *evt) diff --git a/trunk/arch/mips/sgi-ip32/ip32-irq.c b/trunk/arch/mips/sgi-ip32/ip32-irq.c index e0a3ce4a8d48..eb40824b172a 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-irq.c +++ b/trunk/arch/mips/sgi-ip32/ip32-irq.c @@ -130,48 +130,70 @@ static struct irqaction cpuerr_irq = { static uint64_t crime_mask; -static inline void crime_enable_irq(struct irq_data *d) +static inline void crime_enable_irq(unsigned int irq) { - unsigned int bit = d->irq - CRIME_IRQ_BASE; + unsigned int bit = irq - CRIME_IRQ_BASE; crime_mask |= 1 << bit; crime->imask = crime_mask; } -static inline void crime_disable_irq(struct irq_data *d) +static inline void crime_disable_irq(unsigned int irq) { - unsigned int bit = d->irq - CRIME_IRQ_BASE; + unsigned int bit = irq - CRIME_IRQ_BASE; crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } +static void crime_level_mask_and_ack_irq(unsigned int irq) +{ + crime_disable_irq(irq); +} + +static void crime_level_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + crime_enable_irq(irq); +} + static struct irq_chip crime_level_interrupt = { .name = "IP32 CRIME", - .irq_mask = crime_disable_irq, - .irq_unmask = crime_enable_irq, + .ack = crime_level_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_level_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_level_end_irq, }; -static void crime_edge_mask_and_ack_irq(struct irq_data *d) +static void crime_edge_mask_and_ack_irq(unsigned int irq) { - unsigned int bit = d->irq - CRIME_IRQ_BASE; + unsigned int bit = irq - CRIME_IRQ_BASE; uint64_t crime_int; /* Edge triggered interrupts must be cleared. */ + crime_int = crime->hard_int; crime_int &= ~(1 << bit); crime->hard_int = crime_int; - crime_disable_irq(d); + crime_disable_irq(irq); +} + +static void crime_edge_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + crime_enable_irq(irq); } static struct irq_chip crime_edge_interrupt = { .name = "IP32 CRIME", - .irq_ack = crime_edge_mask_and_ack_irq, - .irq_mask = crime_disable_irq, - .irq_mask_ack = crime_edge_mask_and_ack_irq, - .irq_unmask = crime_enable_irq, + .ack = crime_edge_mask_and_ack_irq, + .mask = crime_disable_irq, + .mask_ack = crime_edge_mask_and_ack_irq, + .unmask = crime_enable_irq, + .end = crime_edge_end_irq, }; /* @@ -182,28 +204,37 @@ static struct irq_chip crime_edge_interrupt = { static unsigned long macepci_mask; -static void enable_macepci_irq(struct irq_data *d) +static void enable_macepci_irq(unsigned int irq) { - macepci_mask |= MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ); + macepci_mask |= MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; - crime_mask |= 1 << (d->irq - CRIME_IRQ_BASE); + crime_mask |= 1 << (irq - CRIME_IRQ_BASE); crime->imask = crime_mask; } -static void disable_macepci_irq(struct irq_data *d) +static void disable_macepci_irq(unsigned int irq) { - crime_mask &= ~(1 << (d->irq - CRIME_IRQ_BASE)); + crime_mask &= ~(1 << (irq - CRIME_IRQ_BASE)); crime->imask = crime_mask; flush_crime_bus(); - macepci_mask &= ~MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ); + macepci_mask &= ~MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; flush_mace_bus(); } +static void end_macepci_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_macepci_irq(irq); +} + static struct irq_chip ip32_macepci_interrupt = { .name = "IP32 MACE PCI", - .irq_mask = disable_macepci_irq, - .irq_unmask = enable_macepci_irq, + .ack = disable_macepci_irq, + .mask = disable_macepci_irq, + .mask_ack = disable_macepci_irq, + .unmask = enable_macepci_irq, + .end = end_macepci_irq, }; /* This is used for MACE ISA interrupts. That means bits 4-6 in the @@ -245,13 +276,13 @@ static struct irq_chip ip32_macepci_interrupt = { static unsigned long maceisa_mask; -static void enable_maceisa_irq(struct irq_data *d) +static void enable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - pr_debug("maceisa enable: %u\n", d->irq); + pr_debug("maceisa enable: %u\n", irq); - switch (d->irq) { + switch (irq) { case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: crime_int = MACE_AUDIO_INT; break; @@ -265,15 +296,15 @@ static void enable_maceisa_irq(struct irq_data *d) pr_debug("crime_int %08x enabled\n", crime_int); crime_mask |= crime_int; crime->imask = crime_mask; - maceisa_mask |= 1 << (d->irq - MACEISA_AUDIO_SW_IRQ); + maceisa_mask |= 1 << (irq - MACEISA_AUDIO_SW_IRQ); mace->perif.ctrl.imask = maceisa_mask; } -static void disable_maceisa_irq(struct irq_data *d) +static void disable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - maceisa_mask &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ)); + maceisa_mask &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); if (!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; if (!(maceisa_mask & MACEISA_MISC_INT)) @@ -287,57 +318,76 @@ static void disable_maceisa_irq(struct irq_data *d) flush_mace_bus(); } -static void mask_and_ack_maceisa_irq(struct irq_data *d) +static void mask_and_ack_maceisa_irq(unsigned int irq) { unsigned long mace_int; /* edge triggered */ mace_int = mace->perif.ctrl.istat; - mace_int &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ)); + mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); mace->perif.ctrl.istat = mace_int; - disable_maceisa_irq(d); + disable_maceisa_irq(irq); +} + +static void end_maceisa_irq(unsigned irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_maceisa_irq(irq); } static struct irq_chip ip32_maceisa_level_interrupt = { .name = "IP32 MACE ISA", - .irq_mask = disable_maceisa_irq, - .irq_unmask = enable_maceisa_irq, + .ack = disable_maceisa_irq, + .mask = disable_maceisa_irq, + .mask_ack = disable_maceisa_irq, + .unmask = enable_maceisa_irq, + .end = end_maceisa_irq, }; static struct irq_chip ip32_maceisa_edge_interrupt = { .name = "IP32 MACE ISA", - .irq_ack = mask_and_ack_maceisa_irq, - .irq_mask = disable_maceisa_irq, - .irq_mask_ack = mask_and_ack_maceisa_irq, - .irq_unmask = enable_maceisa_irq, + .ack = mask_and_ack_maceisa_irq, + .mask = disable_maceisa_irq, + .mask_ack = mask_and_ack_maceisa_irq, + .unmask = enable_maceisa_irq, + .end = end_maceisa_irq, }; /* This is used for regular non-ISA, non-PCI MACE interrupts. That means * bits 0-3 and 7 in the CRIME register. */ -static void enable_mace_irq(struct irq_data *d) +static void enable_mace_irq(unsigned int irq) { - unsigned int bit = d->irq - CRIME_IRQ_BASE; + unsigned int bit = irq - CRIME_IRQ_BASE; crime_mask |= (1 << bit); crime->imask = crime_mask; } -static void disable_mace_irq(struct irq_data *d) +static void disable_mace_irq(unsigned int irq) { - unsigned int bit = d->irq - CRIME_IRQ_BASE; + unsigned int bit = irq - CRIME_IRQ_BASE; crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } +static void end_mace_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_mace_irq(irq); +} + static struct irq_chip ip32_mace_interrupt = { .name = "IP32 MACE", - .irq_mask = disable_mace_irq, - .irq_unmask = enable_mace_irq, + .ack = disable_mace_irq, + .mask = disable_mace_irq, + .mask_ack = disable_mace_irq, + .unmask = enable_mace_irq, + .end = end_mace_irq, }; static void ip32_unknown_interrupt(void) diff --git a/trunk/arch/mips/sibyte/bcm1480/irq.c b/trunk/arch/mips/sibyte/bcm1480/irq.c index 89e8188a4665..044bbe462c2c 100644 --- a/trunk/arch/mips/sibyte/bcm1480/irq.c +++ b/trunk/arch/mips/sibyte/bcm1480/irq.c @@ -44,10 +44,31 @@ * for interrupt lines */ + +static void end_bcm1480_irq(unsigned int irq); +static void enable_bcm1480_irq(unsigned int irq); +static void disable_bcm1480_irq(unsigned int irq); +static void ack_bcm1480_irq(unsigned int irq); +#ifdef CONFIG_SMP +static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask); +#endif + #ifdef CONFIG_PCI extern unsigned long ht_eoi_space; #endif +static struct irq_chip bcm1480_irq_type = { + .name = "BCM1480-IMR", + .ack = ack_bcm1480_irq, + .mask = disable_bcm1480_irq, + .mask_ack = ack_bcm1480_irq, + .unmask = enable_bcm1480_irq, + .end = end_bcm1480_irq, +#ifdef CONFIG_SMP + .set_affinity = bcm1480_set_affinity +#endif +}; + /* Store the CPU id (not the logical number) */ int bcm1480_irq_owner[BCM1480_NR_IRQS]; @@ -88,13 +109,12 @@ void bcm1480_unmask_irq(int cpu, int irq) } #ifdef CONFIG_SMP -static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask, - bool force) +static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask) { - unsigned int irq_dirty, irq = d->irq; int i = 0, old_cpu, cpu, int_on, k; u64 cur_ints; unsigned long flags; + unsigned int irq_dirty; i = cpumask_first(mask); @@ -136,25 +156,21 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask, /*****************************************************************************/ -static void disable_bcm1480_irq(struct irq_data *d) +static void disable_bcm1480_irq(unsigned int irq) { - unsigned int irq = d->irq; - bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); } -static void enable_bcm1480_irq(struct irq_data *d) +static void enable_bcm1480_irq(unsigned int irq) { - unsigned int irq = d->irq; - bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); } -static void ack_bcm1480_irq(struct irq_data *d) +static void ack_bcm1480_irq(unsigned int irq) { - unsigned int irq_dirty, irq = d->irq; u64 pending; + unsigned int irq_dirty; int k; /* @@ -201,15 +217,14 @@ static void ack_bcm1480_irq(struct irq_data *d) bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); } -static struct irq_chip bcm1480_irq_type = { - .name = "BCM1480-IMR", - .irq_mask_ack = ack_bcm1480_irq, - .irq_mask = disable_bcm1480_irq, - .irq_unmask = enable_bcm1480_irq, -#ifdef CONFIG_SMP - .irq_set_affinity = bcm1480_set_affinity -#endif -}; + +static void end_bcm1480_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); + } +} + void __init init_bcm1480_irqs(void) { diff --git a/trunk/arch/mips/sibyte/sb1250/irq.c b/trunk/arch/mips/sibyte/sb1250/irq.c index fd269ea8d8a8..12ac04a658ee 100644 --- a/trunk/arch/mips/sibyte/sb1250/irq.c +++ b/trunk/arch/mips/sibyte/sb1250/irq.c @@ -43,10 +43,31 @@ * for interrupt lines */ + +static void end_sb1250_irq(unsigned int irq); +static void enable_sb1250_irq(unsigned int irq); +static void disable_sb1250_irq(unsigned int irq); +static void ack_sb1250_irq(unsigned int irq); +#ifdef CONFIG_SMP +static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask); +#endif + #ifdef CONFIG_SIBYTE_HAS_LDT extern unsigned long ldt_eoi_space; #endif +static struct irq_chip sb1250_irq_type = { + .name = "SB1250-IMR", + .ack = ack_sb1250_irq, + .mask = disable_sb1250_irq, + .mask_ack = ack_sb1250_irq, + .unmask = enable_sb1250_irq, + .end = end_sb1250_irq, +#ifdef CONFIG_SMP + .set_affinity = sb1250_set_affinity +#endif +}; + /* Store the CPU id (not the logical number) */ int sb1250_irq_owner[SB1250_NR_IRQS]; @@ -81,11 +102,9 @@ void sb1250_unmask_irq(int cpu, int irq) } #ifdef CONFIG_SMP -static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, - bool force) +static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask) { int i = 0, old_cpu, cpu, int_on; - unsigned int irq = d->irq; u64 cur_ints; unsigned long flags; @@ -123,17 +142,21 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, } #endif -static void enable_sb1250_irq(struct irq_data *d) +/*****************************************************************************/ + +static void disable_sb1250_irq(unsigned int irq) { - unsigned int irq = d->irq; + sb1250_mask_irq(sb1250_irq_owner[irq], irq); +} +static void enable_sb1250_irq(unsigned int irq) +{ sb1250_unmask_irq(sb1250_irq_owner[irq], irq); } -static void ack_sb1250_irq(struct irq_data *d) +static void ack_sb1250_irq(unsigned int irq) { - unsigned int irq = d->irq; #ifdef CONFIG_SIBYTE_HAS_LDT u64 pending; @@ -176,14 +199,14 @@ static void ack_sb1250_irq(struct irq_data *d) sb1250_mask_irq(sb1250_irq_owner[irq], irq); } -static struct irq_chip sb1250_irq_type = { - .name = "SB1250-IMR", - .irq_mask_ack = ack_sb1250_irq, - .irq_unmask = enable_sb1250_irq, -#ifdef CONFIG_SMP - .irq_set_affinity = sb1250_set_affinity -#endif -}; + +static void end_sb1250_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + sb1250_unmask_irq(sb1250_irq_owner[irq], irq); + } +} + void __init init_sb1250_irqs(void) { diff --git a/trunk/arch/mips/sni/a20r.c b/trunk/arch/mips/sni/a20r.c index 72b94155778d..bbe7187879fa 100644 --- a/trunk/arch/mips/sni/a20r.c +++ b/trunk/arch/mips/sni/a20r.c @@ -168,22 +168,33 @@ static u32 a20r_ack_hwint(void) return status; } -static inline void unmask_a20r_irq(struct irq_data *d) +static inline void unmask_a20r_irq(unsigned int irq) { - set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE)); + set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE)); irq_enable_hazard(); } -static inline void mask_a20r_irq(struct irq_data *d) +static inline void mask_a20r_irq(unsigned int irq) { - clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE)); + clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE)); irq_disable_hazard(); } +static void end_a20r_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + a20r_ack_hwint(); + unmask_a20r_irq(irq); + } +} + static struct irq_chip a20r_irq_type = { .name = "A20R", - .irq_mask = mask_a20r_irq, - .irq_unmask = unmask_a20r_irq, + .ack = mask_a20r_irq, + .mask = mask_a20r_irq, + .mask_ack = mask_a20r_irq, + .unmask = unmask_a20r_irq, + .end = end_a20r_irq, }; /* diff --git a/trunk/arch/mips/sni/pcimt.c b/trunk/arch/mips/sni/pcimt.c index cfcc68abc5b2..8c92c73bc717 100644 --- a/trunk/arch/mips/sni/pcimt.c +++ b/trunk/arch/mips/sni/pcimt.c @@ -194,24 +194,33 @@ static struct pci_controller sni_controller = { .io_map_base = SNI_PORT_BASE }; -static void enable_pcimt_irq(struct irq_data *d) +static void enable_pcimt_irq(unsigned int irq) { - unsigned int mask = 1 << (d->irq - PCIMT_IRQ_INT2); + unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); *(volatile u8 *) PCIMT_IRQSEL |= mask; } -void disable_pcimt_irq(struct irq_data *d) +void disable_pcimt_irq(unsigned int irq) { - unsigned int mask = ~(1 << (d->irq - PCIMT_IRQ_INT2)); + unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2)); *(volatile u8 *) PCIMT_IRQSEL &= mask; } +static void end_pcimt_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pcimt_irq(irq); +} + static struct irq_chip pcimt_irq_type = { .name = "PCIMT", - .irq_mask = disable_pcimt_irq, - .irq_unmask = enable_pcimt_irq, + .ack = disable_pcimt_irq, + .mask = disable_pcimt_irq, + .mask_ack = disable_pcimt_irq, + .unmask = enable_pcimt_irq, + .end = end_pcimt_irq, }; /* diff --git a/trunk/arch/mips/sni/pcit.c b/trunk/arch/mips/sni/pcit.c index 0846e99a6efe..dc9874553bec 100644 --- a/trunk/arch/mips/sni/pcit.c +++ b/trunk/arch/mips/sni/pcit.c @@ -156,24 +156,33 @@ static struct pci_controller sni_pcit_controller = { .io_map_base = SNI_PORT_BASE }; -static void enable_pcit_irq(struct irq_data *d) +static void enable_pcit_irq(unsigned int irq) { - u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); + u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); *(volatile u32 *)SNI_PCIT_INT_REG |= mask; } -void disable_pcit_irq(struct irq_data *d) +void disable_pcit_irq(unsigned int irq) { - u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); + u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; } +void end_pcit_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pcit_irq(irq); +} + static struct irq_chip pcit_irq_type = { .name = "PCIT", - .irq_mask = disable_pcit_irq, - .irq_unmask = enable_pcit_irq, + .ack = disable_pcit_irq, + .mask = disable_pcit_irq, + .mask_ack = disable_pcit_irq, + .unmask = enable_pcit_irq, + .end = end_pcit_irq, }; static void pcit_hwint1(void) diff --git a/trunk/arch/mips/sni/rm200.c b/trunk/arch/mips/sni/rm200.c index f05d8e593300..0e6f42c2bbc8 100644 --- a/trunk/arch/mips/sni/rm200.c +++ b/trunk/arch/mips/sni/rm200.c @@ -155,11 +155,12 @@ static __iomem u8 *rm200_pic_slave; #define cached_master_mask (rm200_cached_irq_mask) #define cached_slave_mask (rm200_cached_irq_mask >> 8) -static void sni_rm200_disable_8259A_irq(struct irq_data *d) +static void sni_rm200_disable_8259A_irq(unsigned int irq) { - unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned int mask; unsigned long flags; + irq -= RM200_I8259A_IRQ_BASE; mask = 1 << irq; raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); rm200_cached_irq_mask |= mask; @@ -170,11 +171,12 @@ static void sni_rm200_disable_8259A_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); } -static void sni_rm200_enable_8259A_irq(struct irq_data *d) +static void sni_rm200_enable_8259A_irq(unsigned int irq) { - unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned int mask; unsigned long flags; + irq -= RM200_I8259A_IRQ_BASE; mask = ~(1 << irq); raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); rm200_cached_irq_mask &= mask; @@ -208,11 +210,12 @@ static inline int sni_rm200_i8259A_irq_real(unsigned int irq) * first, _then_ send the EOI, and the order of EOI * to the two 8259s is important! */ -void sni_rm200_mask_and_ack_8259A(struct irq_data *d) +void sni_rm200_mask_and_ack_8259A(unsigned int irq) { - unsigned int irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned int irqmask; unsigned long flags; + irq -= RM200_I8259A_IRQ_BASE; irqmask = 1 << irq; raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); /* @@ -282,9 +285,9 @@ void sni_rm200_mask_and_ack_8259A(struct irq_data *d) static struct irq_chip sni_rm200_i8259A_chip = { .name = "RM200-XT-PIC", - .irq_mask = sni_rm200_disable_8259A_irq, - .irq_unmask = sni_rm200_enable_8259A_irq, - .irq_mask_ack = sni_rm200_mask_and_ack_8259A, + .mask = sni_rm200_disable_8259A_irq, + .unmask = sni_rm200_enable_8259A_irq, + .mask_ack = sni_rm200_mask_and_ack_8259A, }; /* @@ -426,24 +429,33 @@ void __init sni_rm200_i8259_irqs(void) #define SNI_RM200_INT_START 24 #define SNI_RM200_INT_END 28 -static void enable_rm200_irq(struct irq_data *d) +static void enable_rm200_irq(unsigned int irq) { - unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START); + unsigned int mask = 1 << (irq - SNI_RM200_INT_START); *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask; } -void disable_rm200_irq(struct irq_data *d) +void disable_rm200_irq(unsigned int irq) { - unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START); + unsigned int mask = 1 << (irq - SNI_RM200_INT_START); *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask; } +void end_rm200_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_rm200_irq(irq); +} + static struct irq_chip rm200_irq_type = { .name = "RM200", - .irq_mask = disable_rm200_irq, - .irq_unmask = enable_rm200_irq, + .ack = disable_rm200_irq, + .mask = disable_rm200_irq, + .mask_ack = disable_rm200_irq, + .unmask = enable_rm200_irq, + .end = end_rm200_irq, }; static void sni_rm200_hwint(void) diff --git a/trunk/arch/mips/txx9/generic/irq_tx4939.c b/trunk/arch/mips/txx9/generic/irq_tx4939.c index 93b6edbedd64..3886ad77cbad 100644 --- a/trunk/arch/mips/txx9/generic/irq_tx4939.c +++ b/trunk/arch/mips/txx9/generic/irq_tx4939.c @@ -50,9 +50,9 @@ static struct { unsigned char mode; } tx4939irq[TX4939_NUM_IR] __read_mostly; -static void tx4939_irq_unmask(struct irq_data *d) +static void tx4939_irq_unmask(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 __iomem *lvlp; int ofs; if (irq_nr < 32) { @@ -68,9 +68,9 @@ static void tx4939_irq_unmask(struct irq_data *d) lvlp); } -static inline void tx4939_irq_mask(struct irq_data *d) +static inline void tx4939_irq_mask(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 __iomem *lvlp; int ofs; if (irq_nr < 32) { @@ -87,11 +87,11 @@ static inline void tx4939_irq_mask(struct irq_data *d) mmiowb(); } -static void tx4939_irq_mask_ack(struct irq_data *d) +static void tx4939_irq_mask_ack(unsigned int irq) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; - tx4939_irq_mask(d); + tx4939_irq_mask(irq); if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) { irq_nr--; /* clear edge detection */ @@ -101,9 +101,9 @@ static void tx4939_irq_mask_ack(struct irq_data *d) } } -static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type) +static int tx4939_irq_set_type(unsigned int irq, unsigned int flow_type) { - unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; + unsigned int irq_nr = irq - TXX9_IRQ_BASE; u32 cr; u32 __iomem *crp; int ofs; @@ -145,11 +145,11 @@ static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type) static struct irq_chip tx4939_irq_chip = { .name = "TX4939", - .irq_ack = tx4939_irq_mask_ack, - .irq_mask = tx4939_irq_mask, - .irq_mask_ack = tx4939_irq_mask_ack, - .irq_unmask = tx4939_irq_unmask, - .irq_set_type = tx4939_irq_set_type, + .ack = tx4939_irq_mask_ack, + .mask = tx4939_irq_mask, + .mask_ack = tx4939_irq_mask_ack, + .unmask = tx4939_irq_unmask, + .set_type = tx4939_irq_set_type, }; static int tx4939_irq_set_pri(int irc_irq, int new_pri) diff --git a/trunk/arch/mips/txx9/jmr3927/irq.c b/trunk/arch/mips/txx9/jmr3927/irq.c index 92a5c1b400f0..0a7f8e3b9fd7 100644 --- a/trunk/arch/mips/txx9/jmr3927/irq.c +++ b/trunk/arch/mips/txx9/jmr3927/irq.c @@ -47,20 +47,20 @@ * CP0_STATUS is a thread's resource (saved/restored on context switch). * So disable_irq/enable_irq MUST handle IOC/IRC registers. */ -static void mask_irq_ioc(struct irq_data *d) +static void mask_irq_ioc(unsigned int irq) { /* 0: mask */ - unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC; + unsigned int irq_nr = irq - JMR3927_IRQ_IOC; unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR); /* flush write buffer */ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); } -static void unmask_irq_ioc(struct irq_data *d) +static void unmask_irq_ioc(unsigned int irq) { /* 0: mask */ - unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC; + unsigned int irq_nr = irq - JMR3927_IRQ_IOC; unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR); @@ -95,8 +95,10 @@ static int jmr3927_irq_dispatch(int pending) static struct irq_chip jmr3927_irq_ioc = { .name = "jmr3927_ioc", - .irq_mask = mask_irq_ioc, - .irq_unmask = unmask_irq_ioc, + .ack = mask_irq_ioc, + .mask = mask_irq_ioc, + .mask_ack = mask_irq_ioc, + .unmask = unmask_irq_ioc, }; void __init jmr3927_irq_setup(void) diff --git a/trunk/arch/mips/txx9/rbtx4927/irq.c b/trunk/arch/mips/txx9/rbtx4927/irq.c index 7c0a048b307c..c4b54d20efd3 100644 --- a/trunk/arch/mips/txx9/rbtx4927/irq.c +++ b/trunk/arch/mips/txx9/rbtx4927/irq.c @@ -117,6 +117,18 @@ #include #include +static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq); + +#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" +static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { + .name = TOSHIBA_RBTX4927_IOC_NAME, + .ack = toshiba_rbtx4927_irq_ioc_disable, + .mask = toshiba_rbtx4927_irq_ioc_disable, + .mask_ack = toshiba_rbtx4927_irq_ioc_disable, + .unmask = toshiba_rbtx4927_irq_ioc_enable, +}; + static int toshiba_rbtx4927_irq_nested(int sw_irq) { u8 level3; @@ -127,32 +139,6 @@ static int toshiba_rbtx4927_irq_nested(int sw_irq) return RBTX4927_IRQ_IOC + __fls8(level3); } -static void toshiba_rbtx4927_irq_ioc_enable(struct irq_data *d) -{ - unsigned char v; - - v = readb(rbtx4927_imask_addr); - v |= (1 << (d->irq - RBTX4927_IRQ_IOC)); - writeb(v, rbtx4927_imask_addr); -} - -static void toshiba_rbtx4927_irq_ioc_disable(struct irq_data *d) -{ - unsigned char v; - - v = readb(rbtx4927_imask_addr); - v &= ~(1 << (d->irq - RBTX4927_IRQ_IOC)); - writeb(v, rbtx4927_imask_addr); - mmiowb(); -} - -#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" -static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { - .name = TOSHIBA_RBTX4927_IOC_NAME, - .irq_mask = toshiba_rbtx4927_irq_ioc_disable, - .irq_unmask = toshiba_rbtx4927_irq_ioc_enable, -}; - static void __init toshiba_rbtx4927_irq_ioc_init(void) { int i; @@ -169,6 +155,26 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void) set_irq_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq); } +static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq) +{ + unsigned char v; + + v = readb(rbtx4927_imask_addr); + v |= (1 << (irq - RBTX4927_IRQ_IOC)); + writeb(v, rbtx4927_imask_addr); +} + +static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) +{ + unsigned char v; + + v = readb(rbtx4927_imask_addr); + v &= ~(1 << (irq - RBTX4927_IRQ_IOC)); + writeb(v, rbtx4927_imask_addr); + mmiowb(); +} + + static int rbtx4927_irq_dispatch(int pending) { int irq; diff --git a/trunk/arch/mips/txx9/rbtx4938/irq.c b/trunk/arch/mips/txx9/rbtx4938/irq.c index 2ec4fe1b1670..67a73a8065ec 100644 --- a/trunk/arch/mips/txx9/rbtx4938/irq.c +++ b/trunk/arch/mips/txx9/rbtx4938/irq.c @@ -69,6 +69,18 @@ #include #include +static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq); +static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); + +#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" +static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { + .name = TOSHIBA_RBTX4938_IOC_NAME, + .ack = toshiba_rbtx4938_irq_ioc_disable, + .mask = toshiba_rbtx4938_irq_ioc_disable, + .mask_ack = toshiba_rbtx4938_irq_ioc_disable, + .unmask = toshiba_rbtx4938_irq_ioc_enable, +}; + static int toshiba_rbtx4938_irq_nested(int sw_irq) { u8 level3; @@ -80,33 +92,41 @@ static int toshiba_rbtx4938_irq_nested(int sw_irq) return RBTX4938_IRQ_IOC + __fls8(level3); } -static void toshiba_rbtx4938_irq_ioc_enable(struct irq_data *d) +static void __init +toshiba_rbtx4938_irq_ioc_init(void) +{ + int i; + + for (i = RBTX4938_IRQ_IOC; + i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++) + set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, + handle_level_irq); + + set_irq_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq); +} + +static void +toshiba_rbtx4938_irq_ioc_enable(unsigned int irq) { unsigned char v; v = readb(rbtx4938_imask_addr); - v |= (1 << (d->irq - RBTX4938_IRQ_IOC)); + v |= (1 << (irq - RBTX4938_IRQ_IOC)); writeb(v, rbtx4938_imask_addr); mmiowb(); } -static void toshiba_rbtx4938_irq_ioc_disable(struct irq_data *d) +static void +toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) { unsigned char v; v = readb(rbtx4938_imask_addr); - v &= ~(1 << (d->irq - RBTX4938_IRQ_IOC)); + v &= ~(1 << (irq - RBTX4938_IRQ_IOC)); writeb(v, rbtx4938_imask_addr); mmiowb(); } -#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" -static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { - .name = TOSHIBA_RBTX4938_IOC_NAME, - .irq_mask = toshiba_rbtx4938_irq_ioc_disable, - .irq_unmask = toshiba_rbtx4938_irq_ioc_enable, -}; - static int rbtx4938_irq_dispatch(int pending) { int irq; @@ -126,18 +146,6 @@ static int rbtx4938_irq_dispatch(int pending) return irq; } -static void __init toshiba_rbtx4938_irq_ioc_init(void) -{ - int i; - - for (i = RBTX4938_IRQ_IOC; - i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++) - set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, - handle_level_irq); - - set_irq_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq); -} - void __init rbtx4938_irq_setup(void) { txx9_irq_dispatch = rbtx4938_irq_dispatch; diff --git a/trunk/arch/mips/txx9/rbtx4939/irq.c b/trunk/arch/mips/txx9/rbtx4939/irq.c index 70074632fb99..57fa740a7205 100644 --- a/trunk/arch/mips/txx9/rbtx4939/irq.c +++ b/trunk/arch/mips/txx9/rbtx4939/irq.c @@ -19,16 +19,16 @@ * RBTX4939 IOC controller definition */ -static void rbtx4939_ioc_irq_unmask(struct irq_data *d) +static void rbtx4939_ioc_irq_unmask(unsigned int irq) { - int ioc_nr = d->irq - RBTX4939_IRQ_IOC; + int ioc_nr = irq - RBTX4939_IRQ_IOC; writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); } -static void rbtx4939_ioc_irq_mask(struct irq_data *d) +static void rbtx4939_ioc_irq_mask(unsigned int irq) { - int ioc_nr = d->irq - RBTX4939_IRQ_IOC; + int ioc_nr = irq - RBTX4939_IRQ_IOC; writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); mmiowb(); @@ -36,8 +36,10 @@ static void rbtx4939_ioc_irq_mask(struct irq_data *d) static struct irq_chip rbtx4939_ioc_irq_chip = { .name = "IOC", - .irq_mask = rbtx4939_ioc_irq_mask, - .irq_unmask = rbtx4939_ioc_irq_unmask, + .ack = rbtx4939_ioc_irq_mask, + .mask = rbtx4939_ioc_irq_mask, + .mask_ack = rbtx4939_ioc_irq_mask, + .unmask = rbtx4939_ioc_irq_unmask, }; diff --git a/trunk/arch/mips/vr41xx/common/icu.c b/trunk/arch/mips/vr41xx/common/icu.c index f53156bb9aa8..6153b6a05ccf 100644 --- a/trunk/arch/mips/vr41xx/common/icu.c +++ b/trunk/arch/mips/vr41xx/common/icu.c @@ -154,7 +154,7 @@ static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear) void vr41xx_enable_piuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(PIU_IRQ); + struct irq_desc *desc = irq_desc + PIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -169,7 +169,7 @@ EXPORT_SYMBOL(vr41xx_enable_piuint); void vr41xx_disable_piuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(PIU_IRQ); + struct irq_desc *desc = irq_desc + PIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -184,7 +184,7 @@ EXPORT_SYMBOL(vr41xx_disable_piuint); void vr41xx_enable_aiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(AIU_IRQ); + struct irq_desc *desc = irq_desc + AIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -199,7 +199,7 @@ EXPORT_SYMBOL(vr41xx_enable_aiuint); void vr41xx_disable_aiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(AIU_IRQ); + struct irq_desc *desc = irq_desc + AIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -214,7 +214,7 @@ EXPORT_SYMBOL(vr41xx_disable_aiuint); void vr41xx_enable_kiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(KIU_IRQ); + struct irq_desc *desc = irq_desc + KIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -229,7 +229,7 @@ EXPORT_SYMBOL(vr41xx_enable_kiuint); void vr41xx_disable_kiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(KIU_IRQ); + struct irq_desc *desc = irq_desc + KIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || @@ -244,7 +244,7 @@ EXPORT_SYMBOL(vr41xx_disable_kiuint); void vr41xx_enable_macint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); + struct irq_desc *desc = irq_desc + ETHERNET_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -256,7 +256,7 @@ EXPORT_SYMBOL(vr41xx_enable_macint); void vr41xx_disable_macint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); + struct irq_desc *desc = irq_desc + ETHERNET_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -268,7 +268,7 @@ EXPORT_SYMBOL(vr41xx_disable_macint); void vr41xx_enable_dsiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(DSIU_IRQ); + struct irq_desc *desc = irq_desc + DSIU_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -280,7 +280,7 @@ EXPORT_SYMBOL(vr41xx_enable_dsiuint); void vr41xx_disable_dsiuint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(DSIU_IRQ); + struct irq_desc *desc = irq_desc + DSIU_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -292,7 +292,7 @@ EXPORT_SYMBOL(vr41xx_disable_dsiuint); void vr41xx_enable_firint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(FIR_IRQ); + struct irq_desc *desc = irq_desc + FIR_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -304,7 +304,7 @@ EXPORT_SYMBOL(vr41xx_enable_firint); void vr41xx_disable_firint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(FIR_IRQ); + struct irq_desc *desc = irq_desc + FIR_IRQ; unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); @@ -316,7 +316,7 @@ EXPORT_SYMBOL(vr41xx_disable_firint); void vr41xx_enable_pciint(void) { - struct irq_desc *desc = irq_to_desc(PCI_IRQ); + struct irq_desc *desc = irq_desc + PCI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -332,7 +332,7 @@ EXPORT_SYMBOL(vr41xx_enable_pciint); void vr41xx_disable_pciint(void) { - struct irq_desc *desc = irq_to_desc(PCI_IRQ); + struct irq_desc *desc = irq_desc + PCI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -348,7 +348,7 @@ EXPORT_SYMBOL(vr41xx_disable_pciint); void vr41xx_enable_scuint(void) { - struct irq_desc *desc = irq_to_desc(SCU_IRQ); + struct irq_desc *desc = irq_desc + SCU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -364,7 +364,7 @@ EXPORT_SYMBOL(vr41xx_enable_scuint); void vr41xx_disable_scuint(void) { - struct irq_desc *desc = irq_to_desc(SCU_IRQ); + struct irq_desc *desc = irq_desc + SCU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -380,7 +380,7 @@ EXPORT_SYMBOL(vr41xx_disable_scuint); void vr41xx_enable_csiint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(CSI_IRQ); + struct irq_desc *desc = irq_desc + CSI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -396,7 +396,7 @@ EXPORT_SYMBOL(vr41xx_enable_csiint); void vr41xx_disable_csiint(uint16_t mask) { - struct irq_desc *desc = irq_to_desc(CSI_IRQ); + struct irq_desc *desc = irq_desc + CSI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -412,7 +412,7 @@ EXPORT_SYMBOL(vr41xx_disable_csiint); void vr41xx_enable_bcuint(void) { - struct irq_desc *desc = irq_to_desc(BCU_IRQ); + struct irq_desc *desc = irq_desc + BCU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -428,7 +428,7 @@ EXPORT_SYMBOL(vr41xx_enable_bcuint); void vr41xx_disable_bcuint(void) { - struct irq_desc *desc = irq_to_desc(BCU_IRQ); + struct irq_desc *desc = irq_desc + BCU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || @@ -442,41 +442,45 @@ void vr41xx_disable_bcuint(void) EXPORT_SYMBOL(vr41xx_disable_bcuint); -static void disable_sysint1_irq(struct irq_data *d) +static void disable_sysint1_irq(unsigned int irq) { - icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); + icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } -static void enable_sysint1_irq(struct irq_data *d) +static void enable_sysint1_irq(unsigned int irq) { - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); + icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } static struct irq_chip sysint1_irq_type = { .name = "SYSINT1", - .irq_mask = disable_sysint1_irq, - .irq_unmask = enable_sysint1_irq, + .ack = disable_sysint1_irq, + .mask = disable_sysint1_irq, + .mask_ack = disable_sysint1_irq, + .unmask = enable_sysint1_irq, }; -static void disable_sysint2_irq(struct irq_data *d) +static void disable_sysint2_irq(unsigned int irq) { - icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); + icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } -static void enable_sysint2_irq(struct irq_data *d) +static void enable_sysint2_irq(unsigned int irq) { - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); + icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } static struct irq_chip sysint2_irq_type = { .name = "SYSINT2", - .irq_mask = disable_sysint2_irq, - .irq_unmask = enable_sysint2_irq, + .ack = disable_sysint2_irq, + .mask = disable_sysint2_irq, + .mask_ack = disable_sysint2_irq, + .unmask = enable_sysint2_irq, }; static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) { - struct irq_desc *desc = irq_to_desc(irq); + struct irq_desc *desc = irq_desc + irq; uint16_t intassign0, intassign1; unsigned int pin; @@ -536,7 +540,7 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) { - struct irq_desc *desc = irq_to_desc(irq); + struct irq_desc *desc = irq_desc + irq; uint16_t intassign2, intassign3; unsigned int pin; diff --git a/trunk/arch/mips/vr41xx/common/irq.c b/trunk/arch/mips/vr41xx/common/irq.c index 9ff7f397c0e1..0975eb72d385 100644 --- a/trunk/arch/mips/vr41xx/common/irq.c +++ b/trunk/arch/mips/vr41xx/common/irq.c @@ -62,6 +62,7 @@ EXPORT_SYMBOL_GPL(cascade_irq); static void irq_dispatch(unsigned int irq) { irq_cascade_t *cascade; + struct irq_desc *desc; if (irq >= NR_IRQS) { atomic_inc(&irq_err_count); @@ -70,16 +71,14 @@ static void irq_dispatch(unsigned int irq) cascade = irq_cascade + irq; if (cascade->get_irq != NULL) { - struct irq_desc *desc = irq_to_desc(irq); - struct irq_data *idata = irq_desc_get_irq_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned int source_irq = irq; int ret; - - if (chip->irq_mask_ack) - chip->irq_mask_ack(idata); + desc = irq_desc + source_irq; + if (desc->chip->mask_ack) + desc->chip->mask_ack(source_irq); else { - chip->irq_mask(idata); - chip->irq_ack(idata); + desc->chip->mask(source_irq); + desc->chip->ack(source_irq); } ret = cascade->get_irq(irq); irq = ret; @@ -87,8 +86,8 @@ static void irq_dispatch(unsigned int irq) atomic_inc(&irq_err_count); else irq_dispatch(irq); - if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask) - chip->irq_unmask(idata); + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(source_irq); } else do_IRQ(irq); } diff --git a/trunk/arch/s390/include/asm/ccwdev.h b/trunk/arch/s390/include/asm/ccwdev.h index 623f2fb71774..ff6f62e0ec3e 100644 --- a/trunk/arch/s390/include/asm/ccwdev.h +++ b/trunk/arch/s390/include/asm/ccwdev.h @@ -112,6 +112,7 @@ enum uc_todo { /** * struct ccw driver - device driver for channel attached devices + * @owner: owning module * @ids: ids supported by this driver * @probe: function called on probe * @remove: function called on remove @@ -127,8 +128,10 @@ enum uc_todo { * @restore: callback for restoring after hibernation * @uc_handler: callback for unit check handler * @driver: embedded device driver structure + * @name: device driver name */ struct ccw_driver { + struct module *owner; struct ccw_device_id *ids; int (*probe) (struct ccw_device *); void (*remove) (struct ccw_device *); @@ -144,6 +147,7 @@ struct ccw_driver { int (*restore)(struct ccw_device *); enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); struct device_driver driver; + char *name; }; extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, diff --git a/trunk/arch/s390/include/asm/ccwgroup.h b/trunk/arch/s390/include/asm/ccwgroup.h index f2ea2c56a7e1..c79c1e787b86 100644 --- a/trunk/arch/s390/include/asm/ccwgroup.h +++ b/trunk/arch/s390/include/asm/ccwgroup.h @@ -29,6 +29,8 @@ struct ccwgroup_device { /** * struct ccwgroup_driver - driver for ccw group devices + * @owner: driver owner + * @name: driver name * @max_slaves: maximum number of slave devices * @driver_id: unique id * @probe: function called on probe @@ -44,6 +46,8 @@ struct ccwgroup_device { * @driver: embedded driver structure */ struct ccwgroup_driver { + struct module *owner; + char *name; int max_slaves; unsigned long driver_id; diff --git a/trunk/arch/s390/include/asm/cmpxchg.h b/trunk/arch/s390/include/asm/cmpxchg.h deleted file mode 100644 index 7488e52efa97..000000000000 --- a/trunk/arch/s390/include/asm/cmpxchg.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright IBM Corp. 1999, 2011 - * - * Author(s): Martin Schwidefsky , - */ - -#ifndef __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H - -#include - -extern void __xchg_called_with_bad_pointer(void); - -static inline unsigned long __xchg(unsigned long x, void *ptr, int size) -{ - unsigned long addr, old; - int shift; - - switch (size) { - case 1: - addr = (unsigned long) ptr; - shift = (3 ^ (addr & 3)) << 3; - addr ^= addr & 3; - asm volatile( - " l %0,%4\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%4\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) addr) - : "d" (x << shift), "d" (~(255 << shift)), - "Q" (*(int *) addr) : "memory", "cc", "0"); - return old >> shift; - case 2: - addr = (unsigned long) ptr; - shift = (2 ^ (addr & 2)) << 3; - addr ^= addr & 2; - asm volatile( - " l %0,%4\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%4\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) addr) - : "d" (x << shift), "d" (~(65535 << shift)), - "Q" (*(int *) addr) : "memory", "cc", "0"); - return old >> shift; - case 4: - asm volatile( - " l %0,%3\n" - "0: cs %0,%2,%3\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) ptr) - : "d" (x), "Q" (*(int *) ptr) - : "memory", "cc"); - return old; -#ifdef CONFIG_64BIT - case 8: - asm volatile( - " lg %0,%3\n" - "0: csg %0,%2,%3\n" - " jl 0b\n" - : "=&d" (old), "=m" (*(long *) ptr) - : "d" (x), "Q" (*(long *) ptr) - : "memory", "cc"); - return old; -#endif /* CONFIG_64BIT */ - } - __xchg_called_with_bad_pointer(); - return x; -} - -#define xchg(ptr, x) \ -({ \ - __typeof__(*(ptr)) __ret; \ - __ret = (__typeof__(*(ptr))) \ - __xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\ - __ret; \ -}) - -/* - * Atomic compare and exchange. Compare OLD with MEM, if identical, - * store NEW in MEM. Return the initial value in MEM. Success is - * indicated by comparing RETURN with OLD. - */ - -#define __HAVE_ARCH_CMPXCHG - -extern void __cmpxchg_called_with_bad_pointer(void); - -static inline unsigned long __cmpxchg(void *ptr, unsigned long old, - unsigned long new, int size) -{ - unsigned long addr, prev, tmp; - int shift; - - switch (size) { - case 1: - addr = (unsigned long) ptr; - shift = (3 ^ (addr & 3)) << 3; - addr ^= addr & 3; - asm volatile( - " l %0,%2\n" - "0: nr %0,%5\n" - " lr %1,%0\n" - " or %0,%3\n" - " or %1,%4\n" - " cs %0,%1,%2\n" - " jnl 1f\n" - " xr %1,%0\n" - " nr %1,%5\n" - " jnz 0b\n" - "1:" - : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) - : "d" (old << shift), "d" (new << shift), - "d" (~(255 << shift)), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev >> shift; - case 2: - addr = (unsigned long) ptr; - shift = (2 ^ (addr & 2)) << 3; - addr ^= addr & 2; - asm volatile( - " l %0,%2\n" - "0: nr %0,%5\n" - " lr %1,%0\n" - " or %0,%3\n" - " or %1,%4\n" - " cs %0,%1,%2\n" - " jnl 1f\n" - " xr %1,%0\n" - " nr %1,%5\n" - " jnz 0b\n" - "1:" - : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) - : "d" (old << shift), "d" (new << shift), - "d" (~(65535 << shift)), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev >> shift; - case 4: - asm volatile( - " cs %0,%3,%1\n" - : "=&d" (prev), "=Q" (*(int *) ptr) - : "0" (old), "d" (new), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev; -#ifdef CONFIG_64BIT - case 8: - asm volatile( - " csg %0,%3,%1\n" - : "=&d" (prev), "=Q" (*(long *) ptr) - : "0" (old), "d" (new), "Q" (*(long *) ptr) - : "memory", "cc"); - return prev; -#endif /* CONFIG_64BIT */ - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#define cmpxchg(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) - -#ifdef CONFIG_64BIT -#define cmpxchg64(ptr, o, n) \ -({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg((ptr), (o), (n)); \ -}) -#else /* CONFIG_64BIT */ -static inline unsigned long long __cmpxchg64(void *ptr, - unsigned long long old, - unsigned long long new) -{ - register_pair rp_old = {.pair = old}; - register_pair rp_new = {.pair = new}; - - asm volatile( - " cds %0,%2,%1" - : "+&d" (rp_old), "=Q" (ptr) - : "d" (rp_new), "Q" (ptr) - : "cc"); - return rp_old.pair; -} -#define cmpxchg64(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg64((ptr), \ - (unsigned long long)(o), \ - (unsigned long long)(n))) -#endif /* CONFIG_64BIT */ - -#include - -static inline unsigned long __cmpxchg_local(void *ptr, - unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 1: - case 2: - case 4: -#ifdef CONFIG_64BIT - case 8: -#endif - return __cmpxchg(ptr, old, new, size); - default: - return __cmpxchg_local_generic(ptr, old, new, size); - } - - return old; -} - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) - -#define cmpxchg64_local(ptr, o, n) cmpxchg64((ptr), (o), (n)) - -#endif /* __ASM_CMPXCHG_H */ diff --git a/trunk/arch/s390/include/asm/system.h b/trunk/arch/s390/include/asm/system.h index d382629a0172..8f8d759f6a7b 100644 --- a/trunk/arch/s390/include/asm/system.h +++ b/trunk/arch/s390/include/asm/system.h @@ -14,7 +14,6 @@ #include #include #include -#include #ifdef __KERNEL__ @@ -121,6 +120,161 @@ extern int memcpy_real(void *, void *, size_t); #define nop() asm volatile("nop") +#define xchg(ptr,x) \ +({ \ + __typeof__(*(ptr)) __ret; \ + __ret = (__typeof__(*(ptr))) \ + __xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \ + __ret; \ +}) + +extern void __xchg_called_with_bad_pointer(void); + +static inline unsigned long __xchg(unsigned long x, void * ptr, int size) +{ + unsigned long addr, old; + int shift; + + switch (size) { + case 1: + addr = (unsigned long) ptr; + shift = (3 ^ (addr & 3)) << 3; + addr ^= addr & 3; + asm volatile( + " l %0,%4\n" + "0: lr 0,%0\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,%4\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) addr) + : "d" (x << shift), "d" (~(255 << shift)), + "Q" (*(int *) addr) : "memory", "cc", "0"); + return old >> shift; + case 2: + addr = (unsigned long) ptr; + shift = (2 ^ (addr & 2)) << 3; + addr ^= addr & 2; + asm volatile( + " l %0,%4\n" + "0: lr 0,%0\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,%4\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) addr) + : "d" (x << shift), "d" (~(65535 << shift)), + "Q" (*(int *) addr) : "memory", "cc", "0"); + return old >> shift; + case 4: + asm volatile( + " l %0,%3\n" + "0: cs %0,%2,%3\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) ptr) + : "d" (x), "Q" (*(int *) ptr) + : "memory", "cc"); + return old; +#ifdef __s390x__ + case 8: + asm volatile( + " lg %0,%3\n" + "0: csg %0,%2,%3\n" + " jl 0b\n" + : "=&d" (old), "=m" (*(long *) ptr) + : "d" (x), "Q" (*(long *) ptr) + : "memory", "cc"); + return old; +#endif /* __s390x__ */ + } + __xchg_called_with_bad_pointer(); + return x; +} + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ + +#define __HAVE_ARCH_CMPXCHG 1 + +#define cmpxchg(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) + +extern void __cmpxchg_called_with_bad_pointer(void); + +static inline unsigned long +__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) +{ + unsigned long addr, prev, tmp; + int shift; + + switch (size) { + case 1: + addr = (unsigned long) ptr; + shift = (3 ^ (addr & 3)) << 3; + addr ^= addr & 3; + asm volatile( + " l %0,%2\n" + "0: nr %0,%5\n" + " lr %1,%0\n" + " or %0,%3\n" + " or %1,%4\n" + " cs %0,%1,%2\n" + " jnl 1f\n" + " xr %1,%0\n" + " nr %1,%5\n" + " jnz 0b\n" + "1:" + : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) + : "d" (old << shift), "d" (new << shift), + "d" (~(255 << shift)), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev >> shift; + case 2: + addr = (unsigned long) ptr; + shift = (2 ^ (addr & 2)) << 3; + addr ^= addr & 2; + asm volatile( + " l %0,%2\n" + "0: nr %0,%5\n" + " lr %1,%0\n" + " or %0,%3\n" + " or %1,%4\n" + " cs %0,%1,%2\n" + " jnl 1f\n" + " xr %1,%0\n" + " nr %1,%5\n" + " jnz 0b\n" + "1:" + : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) + : "d" (old << shift), "d" (new << shift), + "d" (~(65535 << shift)), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev >> shift; + case 4: + asm volatile( + " cs %0,%3,%1\n" + : "=&d" (prev), "=Q" (*(int *) ptr) + : "0" (old), "d" (new), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev; +#ifdef __s390x__ + case 8: + asm volatile( + " csg %0,%3,%1\n" + : "=&d" (prev), "=Q" (*(long *) ptr) + : "0" (old), "d" (new), "Q" (*(long *) ptr) + : "memory", "cc"); + return prev; +#endif /* __s390x__ */ + } + __cmpxchg_called_with_bad_pointer(); + return old; +} + /* * Force strict CPU ordering. * And yes, this is required on UP too when we're talking @@ -199,6 +353,46 @@ extern int memcpy_real(void *, void *, size_t); __ctl_load(__dummy, cr, cr); \ }) +#include + +#include + +static inline unsigned long __cmpxchg_local(volatile void *ptr, + unsigned long old, + unsigned long new, int size) +{ + switch (size) { + case 1: + case 2: + case 4: +#ifdef __s390x__ + case 8: +#endif + return __cmpxchg(ptr, old, new, size); + default: + return __cmpxchg_local_generic(ptr, old, new, size); + } + + return old; +} + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#ifdef __s390x__ +#define cmpxchg64_local(ptr, o, n) \ + ({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg_local((ptr), (o), (n)); \ + }) +#else +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#endif + /* * Use to set psw mask except for the first byte which * won't be changed by this function. diff --git a/trunk/arch/s390/include/asm/unistd.h b/trunk/arch/s390/include/asm/unistd.h index e82152572377..1049ef27c15e 100644 --- a/trunk/arch/s390/include/asm/unistd.h +++ b/trunk/arch/s390/include/asm/unistd.h @@ -272,11 +272,7 @@ #define __NR_fanotify_init 332 #define __NR_fanotify_mark 333 #define __NR_prlimit64 334 -#define __NR_name_to_handle_at 335 -#define __NR_open_by_handle_at 336 -#define __NR_clock_adjtime 337 -#define __NR_syncfs 338 -#define NR_syscalls 339 +#define NR_syscalls 335 /* * There are some system calls that are not present on 64 bit, some diff --git a/trunk/arch/s390/kernel/compat_wrapper.S b/trunk/arch/s390/kernel/compat_wrapper.S index 1dc96ea08fa8..8e60fb23b90d 100644 --- a/trunk/arch/s390/kernel/compat_wrapper.S +++ b/trunk/arch/s390/kernel/compat_wrapper.S @@ -1877,30 +1877,3 @@ sys_prlimit64_wrapper: llgtr %r4,%r4 # const struct rlimit64 __user * llgtr %r5,%r5 # struct rlimit64 __user * jg sys_prlimit64 # branch to system call - - .globl sys_name_to_handle_at_wrapper -sys_name_to_handle_at_wrapper: - lgfr %r2,%r2 # int - llgtr %r3,%r3 # const char __user * - llgtr %r4,%r4 # struct file_handle __user * - llgtr %r5,%r5 # int __user * - lgfr %r6,%r6 # int - jg sys_name_to_handle_at - - .globl compat_sys_open_by_handle_at_wrapper -compat_sys_open_by_handle_at_wrapper: - lgfr %r2,%r2 # int - llgtr %r3,%r3 # struct file_handle __user * - lgfr %r4,%r4 # int - jg compat_sys_open_by_handle_at - - .globl compat_sys_clock_adjtime_wrapper -compat_sys_clock_adjtime_wrapper: - lgfr %r2,%r2 # clockid_t (int) - llgtr %r3,%r3 # struct compat_timex __user * - jg compat_sys_clock_adjtime - - .globl sys_syncfs_wrapper -sys_syncfs_wrapper: - lgfr %r2,%r2 # int - jg sys_syncfs diff --git a/trunk/arch/s390/kernel/early.c b/trunk/arch/s390/kernel/early.c index 068f8465c4ee..3b7e7dddc324 100644 --- a/trunk/arch/s390/kernel/early.c +++ b/trunk/arch/s390/kernel/early.c @@ -94,7 +94,6 @@ static noinline __init void create_kernel_nss(void) unsigned int sinitrd_pfn, einitrd_pfn; #endif int response; - int hlen; size_t len; char *savesys_ptr; char defsys_cmd[DEFSYS_CMD_SIZE]; @@ -125,27 +124,24 @@ static noinline __init void create_kernel_nss(void) end_pfn = PFN_UP(__pa(&_end)); min_size = end_pfn << 2; - hlen = snprintf(defsys_cmd, DEFSYS_CMD_SIZE, - "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", - kernel_nss_name, stext_pfn - 1, stext_pfn, - eshared_pfn - 1, eshared_pfn, end_pfn); + sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", + kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, + eshared_pfn, end_pfn); #ifdef CONFIG_BLK_DEV_INITRD if (INITRD_START && INITRD_SIZE) { sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); min_size = einitrd_pfn << 2; - hlen += snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, - " EW %.5X-%.5X", sinitrd_pfn, einitrd_pfn); + sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, + sinitrd_pfn, einitrd_pfn); } #endif - snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, - " EW MINSIZE=%.7iK PARMREGS=0-13", min_size); - defsys_cmd[DEFSYS_CMD_SIZE - 1] = '\0'; - snprintf(savesys_cmd, SAVESYS_CMD_SIZE, "SAVESYS %s \n IPL %s", - kernel_nss_name, kernel_nss_name); - savesys_cmd[SAVESYS_CMD_SIZE - 1] = '\0'; + sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13", + defsys_cmd, min_size); + sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", + kernel_nss_name, kernel_nss_name); __cpcmd(defsys_cmd, NULL, 0, &response); diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index ed183c2c6168..6f6350826c81 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -102,6 +102,16 @@ EXPORT_SYMBOL(lowcore_ptr); #include +static struct resource code_resource = { + .name = "Kernel code", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource data_resource = { + .name = "Kernel data", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + /* * condev= and conmode= setup parameter. */ @@ -426,43 +436,21 @@ setup_lowcore(void) lowcore_ptr[0] = lc; } -static struct resource code_resource = { - .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, -}; - -static struct resource data_resource = { - .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, -}; - -static struct resource bss_resource = { - .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, -}; - -static struct resource __initdata *standard_resources[] = { - &code_resource, - &data_resource, - &bss_resource, -}; - -static void __init setup_resources(void) +static void __init +setup_resources(void) { - struct resource *res, *std_res, *sub_res; - int i, j; + struct resource *res, *sub_res; + int i; code_resource.start = (unsigned long) &_text; code_resource.end = (unsigned long) &_etext - 1; data_resource.start = (unsigned long) &_etext; data_resource.end = (unsigned long) &_edata - 1; - bss_resource.start = (unsigned long) &__bss_start; - bss_resource.end = (unsigned long) &__bss_stop - 1; for (i = 0; i < MEMORY_CHUNKS; i++) { if (!memory_chunk[i].size) continue; - res = alloc_bootmem_low(sizeof(*res)); + res = alloc_bootmem_low(sizeof(struct resource)); res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; switch (memory_chunk[i].type) { case CHUNK_READ_WRITE: @@ -476,24 +464,40 @@ static void __init setup_resources(void) res->name = "reserved"; } res->start = memory_chunk[i].addr; - res->end = res->start + memory_chunk[i].size - 1; + res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; request_resource(&iomem_resource, res); - for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { - std_res = standard_resources[j]; - if (std_res->start < res->start || - std_res->start > res->end) - continue; - if (std_res->end > res->end) { - sub_res = alloc_bootmem_low(sizeof(*sub_res)); - *sub_res = *std_res; - sub_res->end = res->end; - std_res->start = res->end + 1; - request_resource(res, sub_res); - } else { - request_resource(res, std_res); - } + if (code_resource.start >= res->start && + code_resource.start <= res->end && + code_resource.end > res->end) { + sub_res = alloc_bootmem_low(sizeof(struct resource)); + memcpy(sub_res, &code_resource, + sizeof(struct resource)); + sub_res->end = res->end; + code_resource.start = res->end + 1; + request_resource(res, sub_res); + } + + if (code_resource.start >= res->start && + code_resource.start <= res->end && + code_resource.end <= res->end) + request_resource(res, &code_resource); + + if (data_resource.start >= res->start && + data_resource.start <= res->end && + data_resource.end > res->end) { + sub_res = alloc_bootmem_low(sizeof(struct resource)); + memcpy(sub_res, &data_resource, + sizeof(struct resource)); + sub_res->end = res->end; + data_resource.start = res->end + 1; + request_resource(res, sub_res); } + + if (data_resource.start >= res->start && + data_resource.start <= res->end && + data_resource.end <= res->end) + request_resource(res, &data_resource); } } diff --git a/trunk/arch/s390/kernel/syscalls.S b/trunk/arch/s390/kernel/syscalls.S index 9c65fd4ddce0..a8fee1b14395 100644 --- a/trunk/arch/s390/kernel/syscalls.S +++ b/trunk/arch/s390/kernel/syscalls.S @@ -343,7 +343,3 @@ SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) -SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ -SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper) -SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper) -SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) diff --git a/trunk/arch/s390/oprofile/Makefile b/trunk/arch/s390/oprofile/Makefile index 524c4b615821..d698cddcfbdd 100644 --- a/trunk/arch/s390/oprofile/Makefile +++ b/trunk/arch/s390/oprofile/Makefile @@ -6,5 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) init.o backtrace.o -oprofile-$(CONFIG_64BIT) += hwsampler.o +oprofile-y := $(DRIVER_OBJS) init.o backtrace.o hwsampler.o diff --git a/trunk/arch/s390/oprofile/init.c b/trunk/arch/s390/oprofile/init.c index c63d7e58352b..16c76def4a9d 100644 --- a/trunk/arch/s390/oprofile/init.c +++ b/trunk/arch/s390/oprofile/init.c @@ -18,11 +18,6 @@ #include #include "../../../drivers/oprofile/oprof.h" - -extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); - -#ifdef CONFIG_64BIT - #include "hwsampler.h" #define DEFAULT_INTERVAL 4096 @@ -42,6 +37,8 @@ static int hwsampler_running; /* start_mutex must be held to change */ static struct oprofile_operations timer_ops; +extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); + static int oprofile_hwsampler_start(void) { int retval; @@ -175,22 +172,14 @@ static void oprofile_hwsampler_exit(void) hwsampler_shutdown(); } -#endif /* CONFIG_64BIT */ - int __init oprofile_arch_init(struct oprofile_operations *ops) { ops->backtrace = s390_backtrace; -#ifdef CONFIG_64BIT return oprofile_hwsampler_init(ops); -#else - return -ENODEV; -#endif } void oprofile_arch_exit(void) { -#ifdef CONFIG_64BIT oprofile_hwsampler_exit(); -#endif } diff --git a/trunk/arch/sparc/kernel/time_32.c b/trunk/arch/sparc/kernel/time_32.c index 4e236391b635..8237dd4dfeb4 100644 --- a/trunk/arch/sparc/kernel/time_32.c +++ b/trunk/arch/sparc/kernel/time_32.c @@ -145,10 +145,6 @@ static int __devinit clock_probe(struct platform_device *op) if (!model) return -ENODEV; - /* Only the primary RTC has an address property */ - if (!of_find_property(dp, "address", NULL)) - return -ENODEV; - m48t59_rtc.resource = &op->resource[0]; if (!strcmp(model, "mk48t02")) { /* Map the clock register io area read-only */ diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index e0a062363937..59b5c00c0126 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -271,7 +271,7 @@ EXPORT_SYMBOL(blk_start_queue); **/ void blk_stop_queue(struct request_queue *q) { - __cancel_delayed_work(&q->delay_work); + cancel_delayed_work(&q->delay_work); queue_flag_set(QUEUE_FLAG_STOPPED, q); } EXPORT_SYMBOL(blk_stop_queue); @@ -2702,10 +2702,7 @@ static void flush_plug_list(struct blk_plug *plug) /* * rq is already accounted, so use raw insert */ - if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) - __elv_add_request(q, rq, ELEVATOR_INSERT_FLUSH); - else - __elv_add_request(q, rq, ELEVATOR_INSERT_SORT_MERGE); + __elv_add_request(q, rq, ELEVATOR_INSERT_SORT_MERGE); } if (q) { diff --git a/trunk/drivers/memstick/host/Kconfig b/trunk/drivers/memstick/host/Kconfig index cc0997a05171..4ce5c8dffb68 100644 --- a/trunk/drivers/memstick/host/Kconfig +++ b/trunk/drivers/memstick/host/Kconfig @@ -30,15 +30,3 @@ config MEMSTICK_JMICRON_38X To compile this driver as a module, choose M here: the module will be called jmb38x_ms. - -config MEMSTICK_R592 - tristate "Ricoh R5C592 MemoryStick interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI - - help - Say Y here if you want to be able to access MemoryStick cards with - the Ricoh R5C592 MemoryStick card reader (which is part of 5 in one - multifunction reader) - - To compile this driver as a module, choose M here: the module will - be called r592. diff --git a/trunk/drivers/memstick/host/Makefile b/trunk/drivers/memstick/host/Makefile index 31ba8d378e46..a1815e9dd019 100644 --- a/trunk/drivers/memstick/host/Makefile +++ b/trunk/drivers/memstick/host/Makefile @@ -4,4 +4,3 @@ obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o -obj-$(CONFIG_MEMSTICK_R592) += r592.o diff --git a/trunk/drivers/memstick/host/r592.c b/trunk/drivers/memstick/host/r592.c deleted file mode 100644 index 767406c95291..000000000000 --- a/trunk/drivers/memstick/host/r592.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * driver for Ricoh memstick readers - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "r592.h" - -static int enable_dma = 1; -static int debug; - -static const char *tpc_names[] = { - "MS_TPC_READ_MG_STATUS", - "MS_TPC_READ_LONG_DATA", - "MS_TPC_READ_SHORT_DATA", - "MS_TPC_READ_REG", - "MS_TPC_READ_QUAD_DATA", - "INVALID", - "MS_TPC_GET_INT", - "MS_TPC_SET_RW_REG_ADRS", - "MS_TPC_EX_SET_CMD", - "MS_TPC_WRITE_QUAD_DATA", - "MS_TPC_WRITE_REG", - "MS_TPC_WRITE_SHORT_DATA", - "MS_TPC_WRITE_LONG_DATA", - "MS_TPC_SET_CMD", -}; - -/** - * memstick_debug_get_tpc_name - debug helper that returns string for - * a TPC number - */ -const char *memstick_debug_get_tpc_name(int tpc) -{ - return tpc_names[tpc-1]; -} -EXPORT_SYMBOL(memstick_debug_get_tpc_name); - - -/* Read a register*/ -static inline u32 r592_read_reg(struct r592_device *dev, int address) -{ - u32 value = readl(dev->mmio + address); - dbg_reg("reg #%02d == 0x%08x", address, value); - return value; -} - -/* Write a register */ -static inline void r592_write_reg(struct r592_device *dev, - int address, u32 value) -{ - dbg_reg("reg #%02d <- 0x%08x", address, value); - writel(value, dev->mmio + address); -} - -/* Reads a big endian DWORD register */ -static inline u32 r592_read_reg_raw_be(struct r592_device *dev, int address) -{ - u32 value = __raw_readl(dev->mmio + address); - dbg_reg("reg #%02d == 0x%08x", address, value); - return be32_to_cpu(value); -} - -/* Writes a big endian DWORD register */ -static inline void r592_write_reg_raw_be(struct r592_device *dev, - int address, u32 value) -{ - dbg_reg("reg #%02d <- 0x%08x", address, value); - __raw_writel(cpu_to_be32(value), dev->mmio + address); -} - -/* Set specific bits in a register (little endian) */ -static inline void r592_set_reg_mask(struct r592_device *dev, - int address, u32 mask) -{ - u32 reg = readl(dev->mmio + address); - dbg_reg("reg #%02d |= 0x%08x (old =0x%08x)", address, mask, reg); - writel(reg | mask , dev->mmio + address); -} - -/* Clear specific bits in a register (little endian) */ -static inline void r592_clear_reg_mask(struct r592_device *dev, - int address, u32 mask) -{ - u32 reg = readl(dev->mmio + address); - dbg_reg("reg #%02d &= 0x%08x (old = 0x%08x, mask = 0x%08x)", - address, ~mask, reg, mask); - writel(reg & ~mask, dev->mmio + address); -} - - -/* Wait for status bits while checking for errors */ -static int r592_wait_status(struct r592_device *dev, u32 mask, u32 wanted_mask) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - u32 reg = r592_read_reg(dev, R592_STATUS); - - if ((reg & mask) == wanted_mask) - return 0; - - while (time_before(jiffies, timeout)) { - - reg = r592_read_reg(dev, R592_STATUS); - - if ((reg & mask) == wanted_mask) - return 0; - - if (reg & (R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR)) - return -EIO; - - cpu_relax(); - } - return -ETIME; -} - - -/* Enable/disable device */ -static int r592_enable_device(struct r592_device *dev, bool enable) -{ - dbg("%sabling the device", enable ? "en" : "dis"); - - if (enable) { - - /* Power up the card */ - r592_write_reg(dev, R592_POWER, R592_POWER_0 | R592_POWER_1); - - /* Perform a reset */ - r592_set_reg_mask(dev, R592_IO, R592_IO_RESET); - - msleep(100); - } else - /* Power down the card */ - r592_write_reg(dev, R592_POWER, 0); - - return 0; -} - -/* Set serial/parallel mode */ -static int r592_set_mode(struct r592_device *dev, bool parallel_mode) -{ - if (!parallel_mode) { - dbg("switching to serial mode"); - - /* Set serial mode */ - r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_SERIAL); - - r592_clear_reg_mask(dev, R592_POWER, R592_POWER_20); - - } else { - dbg("switching to parallel mode"); - - /* This setting should be set _before_ switch TPC */ - r592_set_reg_mask(dev, R592_POWER, R592_POWER_20); - - r592_clear_reg_mask(dev, R592_IO, - R592_IO_SERIAL1 | R592_IO_SERIAL2); - - /* Set the parallel mode now */ - r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_PARALLEL); - } - - dev->parallel_mode = parallel_mode; - return 0; -} - -/* Perform a controller reset without powering down the card */ -static void r592_host_reset(struct r592_device *dev) -{ - r592_set_reg_mask(dev, R592_IO, R592_IO_RESET); - msleep(100); - r592_set_mode(dev, dev->parallel_mode); -} - -/* Disable all hardware interrupts */ -static void r592_clear_interrupts(struct r592_device *dev) -{ - /* Disable & ACK all interrupts */ - r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK); - r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK); -} - -/* Tests if there is an CRC error */ -static int r592_test_io_error(struct r592_device *dev) -{ - if (!(r592_read_reg(dev, R592_STATUS) & - (R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR))) - return 0; - - return -EIO; -} - -/* Ensure that FIFO is ready for use */ -static int r592_test_fifo_empty(struct r592_device *dev) -{ - if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY) - return 0; - - dbg("FIFO not ready, trying to reset the device"); - r592_host_reset(dev); - - if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY) - return 0; - - message("FIFO still not ready, giving up"); - return -EIO; -} - -/* Activates the DMA transfer from to FIFO */ -static void r592_start_dma(struct r592_device *dev, bool is_write) -{ - unsigned long flags; - u32 reg; - spin_lock_irqsave(&dev->irq_lock, flags); - - /* Ack interrupts (just in case) + enable them */ - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK); - r592_set_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK); - - /* Set DMA address */ - r592_write_reg(dev, R592_FIFO_DMA, sg_dma_address(&dev->req->sg)); - - /* Enable the DMA */ - reg = r592_read_reg(dev, R592_FIFO_DMA_SETTINGS); - reg |= R592_FIFO_DMA_SETTINGS_EN; - - if (!is_write) - reg |= R592_FIFO_DMA_SETTINGS_DIR; - else - reg &= ~R592_FIFO_DMA_SETTINGS_DIR; - r592_write_reg(dev, R592_FIFO_DMA_SETTINGS, reg); - - spin_unlock_irqrestore(&dev->irq_lock, flags); -} - -/* Cleanups DMA related settings */ -static void r592_stop_dma(struct r592_device *dev, int error) -{ - r592_clear_reg_mask(dev, R592_FIFO_DMA_SETTINGS, - R592_FIFO_DMA_SETTINGS_EN); - - /* This is only a precation */ - r592_write_reg(dev, R592_FIFO_DMA, - dev->dummy_dma_page_physical_address); - - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK); - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK); - dev->dma_error = error; -} - -/* Test if hardware supports DMA */ -static void r592_check_dma(struct r592_device *dev) -{ - dev->dma_capable = enable_dma && - (r592_read_reg(dev, R592_FIFO_DMA_SETTINGS) & - R592_FIFO_DMA_SETTINGS_CAP); -} - -/* Transfers fifo contents in/out using DMA */ -static int r592_transfer_fifo_dma(struct r592_device *dev) -{ - int len, sg_count; - bool is_write; - - if (!dev->dma_capable || !dev->req->long_data) - return -EINVAL; - - len = dev->req->sg.length; - is_write = dev->req->data_dir == WRITE; - - if (len != R592_LFIFO_SIZE) - return -EINVAL; - - dbg_verbose("doing dma transfer"); - - dev->dma_error = 0; - INIT_COMPLETION(dev->dma_done); - - /* TODO: hidden assumption about nenth beeing always 1 */ - sg_count = dma_map_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - - if (sg_count != 1 || - (sg_dma_len(&dev->req->sg) < dev->req->sg.length)) { - message("problem in dma_map_sg"); - return -EIO; - } - - r592_start_dma(dev, is_write); - - /* Wait for DMA completion */ - if (!wait_for_completion_timeout( - &dev->dma_done, msecs_to_jiffies(1000))) { - message("DMA timeout"); - r592_stop_dma(dev, -ETIMEDOUT); - } - - dma_unmap_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - - - return dev->dma_error; -} - -/* - * Writes the FIFO in 4 byte chunks. - * If length isn't 4 byte aligned, rest of the data if put to a fifo - * to be written later - * Use r592_flush_fifo_write to flush that fifo when writing for the - * last time - */ -static void r592_write_fifo_pio(struct r592_device *dev, - unsigned char *buffer, int len) -{ - /* flush spill from former write */ - if (!kfifo_is_empty(&dev->pio_fifo)) { - - u8 tmp[4] = {0}; - int copy_len = kfifo_in(&dev->pio_fifo, buffer, len); - - if (!kfifo_is_full(&dev->pio_fifo)) - return; - len -= copy_len; - buffer += copy_len; - - copy_len = kfifo_out(&dev->pio_fifo, tmp, 4); - WARN_ON(copy_len != 4); - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)tmp); - } - - WARN_ON(!kfifo_is_empty(&dev->pio_fifo)); - - /* write full dwords */ - while (len >= 4) { - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer); - buffer += 4; - len -= 4; - } - - /* put remaining bytes to the spill */ - if (len) - kfifo_in(&dev->pio_fifo, buffer, len); -} - -/* Flushes the temporary FIFO used to make aligned DWORD writes */ -static void r592_flush_fifo_write(struct r592_device *dev) -{ - u8 buffer[4] = { 0 }; - int len; - - if (kfifo_is_empty(&dev->pio_fifo)) - return; - - len = kfifo_out(&dev->pio_fifo, buffer, 4); - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer); -} - -/* - * Read a fifo in 4 bytes chunks. - * If input doesn't fit the buffer, it places bytes of last dword in spill - * buffer, so that they don't get lost on last read, just throw these away. - */ -static void r592_read_fifo_pio(struct r592_device *dev, - unsigned char *buffer, int len) -{ - u8 tmp[4]; - - /* Read from last spill */ - if (!kfifo_is_empty(&dev->pio_fifo)) { - int bytes_copied = - kfifo_out(&dev->pio_fifo, buffer, min(4, len)); - buffer += bytes_copied; - len -= bytes_copied; - - if (!kfifo_is_empty(&dev->pio_fifo)) - return; - } - - /* Reads dwords from FIFO */ - while (len >= 4) { - *(u32 *)buffer = r592_read_reg_raw_be(dev, R592_FIFO_PIO); - buffer += 4; - len -= 4; - } - - if (len) { - *(u32 *)tmp = r592_read_reg_raw_be(dev, R592_FIFO_PIO); - kfifo_in(&dev->pio_fifo, tmp, 4); - len -= kfifo_out(&dev->pio_fifo, buffer, len); - } - - WARN_ON(len); - return; -} - -/* Transfers actual data using PIO. */ -static int r592_transfer_fifo_pio(struct r592_device *dev) -{ - unsigned long flags; - - bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS; - struct sg_mapping_iter miter; - - kfifo_reset(&dev->pio_fifo); - - if (!dev->req->long_data) { - if (is_write) { - r592_write_fifo_pio(dev, dev->req->data, - dev->req->data_len); - r592_flush_fifo_write(dev); - } else - r592_read_fifo_pio(dev, dev->req->data, - dev->req->data_len); - return 0; - } - - local_irq_save(flags); - sg_miter_start(&miter, &dev->req->sg, 1, SG_MITER_ATOMIC | - (is_write ? SG_MITER_FROM_SG : SG_MITER_TO_SG)); - - /* Do the transfer fifo<->memory*/ - while (sg_miter_next(&miter)) - if (is_write) - r592_write_fifo_pio(dev, miter.addr, miter.length); - else - r592_read_fifo_pio(dev, miter.addr, miter.length); - - - /* Write last few non aligned bytes*/ - if (is_write) - r592_flush_fifo_write(dev); - - sg_miter_stop(&miter); - local_irq_restore(flags); - return 0; -} - -/* Executes one TPC (data is read/written from small or large fifo) */ -static void r592_execute_tpc(struct r592_device *dev) -{ - bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS; - int len, error; - u32 status, reg; - - if (!dev->req) { - message("BUG: tpc execution without request!"); - return; - } - - len = dev->req->long_data ? - dev->req->sg.length : dev->req->data_len; - - /* Ensure that FIFO can hold the input data */ - if (len > R592_LFIFO_SIZE) { - message("IO: hardware doesn't support TPCs longer that 512"); - error = -ENOSYS; - goto out; - } - - if (!(r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_PRSNT)) { - dbg("IO: refusing to send TPC because card is absent"); - error = -ENODEV; - goto out; - } - - dbg("IO: executing %s LEN=%d", - memstick_debug_get_tpc_name(dev->req->tpc), len); - - /* Set IO direction */ - if (is_write) - r592_set_reg_mask(dev, R592_IO, R592_IO_DIRECTION); - else - r592_clear_reg_mask(dev, R592_IO, R592_IO_DIRECTION); - - - error = r592_test_fifo_empty(dev); - if (error) - goto out; - - /* Transfer write data */ - if (is_write) { - error = r592_transfer_fifo_dma(dev); - if (error == -EINVAL) - error = r592_transfer_fifo_pio(dev); - } - - if (error) - goto out; - - /* Trigger the TPC */ - reg = (len << R592_TPC_EXEC_LEN_SHIFT) | - (dev->req->tpc << R592_TPC_EXEC_TPC_SHIFT) | - R592_TPC_EXEC_BIG_FIFO; - - r592_write_reg(dev, R592_TPC_EXEC, reg); - - /* Wait for TPC completion */ - status = R592_STATUS_RDY; - if (dev->req->need_card_int) - status |= R592_STATUS_CED; - - error = r592_wait_status(dev, status, status); - if (error) { - message("card didn't respond"); - goto out; - } - - /* Test IO errors */ - error = r592_test_io_error(dev); - if (error) { - dbg("IO error"); - goto out; - } - - /* Read data from FIFO */ - if (!is_write) { - error = r592_transfer_fifo_dma(dev); - if (error == -EINVAL) - error = r592_transfer_fifo_pio(dev); - } - - /* read INT reg. This can be shortened with shifts, but that way - its more readable */ - if (dev->parallel_mode && dev->req->need_card_int) { - - dev->req->int_reg = 0; - status = r592_read_reg(dev, R592_STATUS); - - if (status & R592_STATUS_P_CMDNACK) - dev->req->int_reg |= MEMSTICK_INT_CMDNAK; - if (status & R592_STATUS_P_BREQ) - dev->req->int_reg |= MEMSTICK_INT_BREQ; - if (status & R592_STATUS_P_INTERR) - dev->req->int_reg |= MEMSTICK_INT_ERR; - if (status & R592_STATUS_P_CED) - dev->req->int_reg |= MEMSTICK_INT_CED; - } - - if (error) - dbg("FIFO read error"); -out: - dev->req->error = error; - r592_clear_reg_mask(dev, R592_REG_MSC, R592_REG_MSC_LED); - return; -} - -/* Main request processing thread */ -static int r592_process_thread(void *data) -{ - int error; - struct r592_device *dev = (struct r592_device *)data; - unsigned long flags; - - while (!kthread_should_stop()) { - spin_lock_irqsave(&dev->io_thread_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - error = memstick_next_req(dev->host, &dev->req); - spin_unlock_irqrestore(&dev->io_thread_lock, flags); - - if (error) { - if (error == -ENXIO || error == -EAGAIN) { - dbg_verbose("IO: done IO, sleeping"); - } else { - dbg("IO: unknown error from " - "memstick_next_req %d", error); - } - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - schedule(); - } else { - set_current_state(TASK_RUNNING); - r592_execute_tpc(dev); - } - } - return 0; -} - -/* Reprogram chip to detect change in card state */ -/* eg, if card is detected, arm it to detect removal, and vice versa */ -static void r592_update_card_detect(struct r592_device *dev) -{ - u32 reg = r592_read_reg(dev, R592_REG_MSC); - bool card_detected = reg & R592_REG_MSC_PRSNT; - - dbg("update card detect. card state: %s", card_detected ? - "present" : "absent"); - - reg &= ~((R592_REG_MSC_IRQ_REMOVE | R592_REG_MSC_IRQ_INSERT) << 16); - - if (card_detected) - reg |= (R592_REG_MSC_IRQ_REMOVE << 16); - else - reg |= (R592_REG_MSC_IRQ_INSERT << 16); - - r592_write_reg(dev, R592_REG_MSC, reg); -} - -/* Timer routine that fires 1 second after last card detection event, */ -static void r592_detect_timer(long unsigned int data) -{ - struct r592_device *dev = (struct r592_device *)data; - r592_update_card_detect(dev); - memstick_detect_change(dev->host); -} - -/* Interrupt handler */ -static irqreturn_t r592_irq(int irq, void *data) -{ - struct r592_device *dev = (struct r592_device *)data; - irqreturn_t ret = IRQ_NONE; - u32 reg; - u16 irq_enable, irq_status; - unsigned long flags; - int error; - - spin_lock_irqsave(&dev->irq_lock, flags); - - reg = r592_read_reg(dev, R592_REG_MSC); - irq_enable = reg >> 16; - irq_status = reg & 0xFFFF; - - /* Ack the interrupts */ - reg &= ~irq_status; - r592_write_reg(dev, R592_REG_MSC, reg); - - /* Get the IRQ status minus bits that aren't enabled */ - irq_status &= (irq_enable); - - /* Due to limitation of memstick core, we don't look at bits that - indicate that card was removed/inserted and/or present */ - if (irq_status & (R592_REG_MSC_IRQ_INSERT | R592_REG_MSC_IRQ_REMOVE)) { - - bool card_was_added = irq_status & R592_REG_MSC_IRQ_INSERT; - ret = IRQ_HANDLED; - - message("IRQ: card %s", card_was_added ? "added" : "removed"); - - mod_timer(&dev->detect_timer, - jiffies + msecs_to_jiffies(card_was_added ? 500 : 50)); - } - - if (irq_status & - (R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR)) { - ret = IRQ_HANDLED; - - if (irq_status & R592_REG_MSC_FIFO_DMA_ERR) { - message("IRQ: DMA error"); - error = -EIO; - } else { - dbg_verbose("IRQ: dma done"); - error = 0; - } - - r592_stop_dma(dev, error); - complete(&dev->dma_done); - } - - spin_unlock_irqrestore(&dev->irq_lock, flags); - return ret; -} - -/* External inteface: set settings */ -static int r592_set_param(struct memstick_host *host, - enum memstick_param param, int value) -{ - struct r592_device *dev = memstick_priv(host); - - switch (param) { - case MEMSTICK_POWER: - switch (value) { - case MEMSTICK_POWER_ON: - return r592_enable_device(dev, true); - case MEMSTICK_POWER_OFF: - return r592_enable_device(dev, false); - default: - return -EINVAL; - } - case MEMSTICK_INTERFACE: - switch (value) { - case MEMSTICK_SERIAL: - return r592_set_mode(dev, 0); - case MEMSTICK_PAR4: - return r592_set_mode(dev, 1); - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} - -/* External interface: submit requests */ -static void r592_submit_req(struct memstick_host *host) -{ - struct r592_device *dev = memstick_priv(host); - unsigned long flags; - - if (dev->req) - return; - - spin_lock_irqsave(&dev->io_thread_lock, flags); - if (wake_up_process(dev->io_thread)) - dbg_verbose("IO thread woken to process requests"); - spin_unlock_irqrestore(&dev->io_thread_lock, flags); -} - -static const struct pci_device_id r592_pci_id_tbl[] = { - - { PCI_VDEVICE(RICOH, 0x0592), }, - { }, -}; - -/* Main entry */ -static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int error = -ENOMEM; - struct memstick_host *host; - struct r592_device *dev; - - /* Allocate memory */ - host = memstick_alloc_host(sizeof(struct r592_device), &pdev->dev); - if (!host) - goto error1; - - dev = memstick_priv(host); - dev->host = host; - dev->pci_dev = pdev; - pci_set_drvdata(pdev, dev); - - /* pci initialization */ - error = pci_enable_device(pdev); - if (error) - goto error2; - - pci_set_master(pdev); - error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (error) - goto error3; - - error = pci_request_regions(pdev, DRV_NAME); - if (error) - goto error3; - - dev->mmio = pci_ioremap_bar(pdev, 0); - if (!dev->mmio) - goto error4; - - dev->irq = pdev->irq; - spin_lock_init(&dev->irq_lock); - spin_lock_init(&dev->io_thread_lock); - init_completion(&dev->dma_done); - INIT_KFIFO(dev->pio_fifo); - setup_timer(&dev->detect_timer, - r592_detect_timer, (long unsigned int)dev); - - /* Host initialization */ - host->caps = MEMSTICK_CAP_PAR4; - host->request = r592_submit_req; - host->set_param = r592_set_param; - r592_check_dma(dev); - - dev->io_thread = kthread_run(r592_process_thread, dev, "r592_io"); - if (IS_ERR(dev->io_thread)) { - error = PTR_ERR(dev->io_thread); - goto error5; - } - - /* This is just a precation, so don't fail */ - dev->dummy_dma_page = pci_alloc_consistent(pdev, PAGE_SIZE, - &dev->dummy_dma_page_physical_address); - r592_stop_dma(dev , 0); - - if (request_irq(dev->irq, &r592_irq, IRQF_SHARED, - DRV_NAME, dev)) - goto error6; - - r592_update_card_detect(dev); - if (memstick_add_host(host)) - goto error7; - - message("driver succesfully loaded"); - return 0; -error7: - free_irq(dev->irq, dev); -error6: - if (dev->dummy_dma_page) - pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page, - dev->dummy_dma_page_physical_address); - - kthread_stop(dev->io_thread); -error5: - iounmap(dev->mmio); -error4: - pci_release_regions(pdev); -error3: - pci_disable_device(pdev); -error2: - memstick_free_host(host); -error1: - return error; -} - -static void r592_remove(struct pci_dev *pdev) -{ - int error = 0; - struct r592_device *dev = pci_get_drvdata(pdev); - - /* Stop the processing thread. - That ensures that we won't take any more requests */ - kthread_stop(dev->io_thread); - - r592_enable_device(dev, false); - - while (!error && dev->req) { - dev->req->error = -ETIME; - error = memstick_next_req(dev->host, &dev->req); - } - memstick_remove_host(dev->host); - - free_irq(dev->irq, dev); - iounmap(dev->mmio); - pci_release_regions(pdev); - pci_disable_device(pdev); - memstick_free_host(dev->host); - - if (dev->dummy_dma_page) - pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page, - dev->dummy_dma_page_physical_address); -} - -#ifdef CONFIG_PM -static int r592_suspend(struct device *core_dev) -{ - struct pci_dev *pdev = to_pci_dev(core_dev); - struct r592_device *dev = pci_get_drvdata(pdev); - - r592_clear_interrupts(dev); - memstick_suspend_host(dev->host); - del_timer_sync(&dev->detect_timer); - return 0; -} - -static int r592_resume(struct device *core_dev) -{ - struct pci_dev *pdev = to_pci_dev(core_dev); - struct r592_device *dev = pci_get_drvdata(pdev); - - r592_clear_interrupts(dev); - r592_enable_device(dev, false); - memstick_resume_host(dev->host); - r592_update_card_detect(dev); - return 0; -} - -SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume); -#endif - -MODULE_DEVICE_TABLE(pci, r592_pci_id_tbl); - -static struct pci_driver r852_pci_driver = { - .name = DRV_NAME, - .id_table = r592_pci_id_tbl, - .probe = r592_probe, - .remove = r592_remove, -#ifdef CONFIG_PM - .driver.pm = &r592_pm_ops, -#endif -}; - -static __init int r592_module_init(void) -{ - return pci_register_driver(&r852_pci_driver); -} - -static void __exit r592_module_exit(void) -{ - pci_unregister_driver(&r852_pci_driver); -} - -module_init(r592_module_init); -module_exit(r592_module_exit); - -module_param(enable_dma, bool, S_IRUGO); -MODULE_PARM_DESC(enable_dma, "Enable usage of the DMA (default)"); -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level (0-3)"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Maxim Levitsky "); -MODULE_DESCRIPTION("Ricoh R5C592 Memstick/Memstick PRO card reader driver"); diff --git a/trunk/drivers/memstick/host/r592.h b/trunk/drivers/memstick/host/r592.h deleted file mode 100644 index eee264e6028f..000000000000 --- a/trunk/drivers/memstick/host/r592.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * driver for Ricoh memstick readers - * - * 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 R592_H - -#include -#include -#include -#include -#include -#include - -/* write to this reg (number,len) triggers TPC execution */ -#define R592_TPC_EXEC 0x00 -#define R592_TPC_EXEC_LEN_SHIFT 16 /* Bits 16..25 are TPC len */ -#define R592_TPC_EXEC_BIG_FIFO (1 << 26) /* If bit 26 is set, large fifo is used (reg 48) */ -#define R592_TPC_EXEC_TPC_SHIFT 28 /* Bits 28..31 are the TPC number */ - - -/* Window for small TPC fifo (big endian)*/ -/* reads and writes always are done in 8 byte chunks */ -/* Not used in driver, because large fifo does better job */ -#define R592_SFIFO 0x08 - - -/* Status register (ms int, small fifo, IO)*/ -#define R592_STATUS 0x10 - /* Parallel INT bits */ -#define R592_STATUS_P_CMDNACK (1 << 16) /* INT reg: NACK (parallel mode) */ -#define R592_STATUS_P_BREQ (1 << 17) /* INT reg: card ready (parallel mode)*/ -#define R592_STATUS_P_INTERR (1 << 18) /* INT reg: int error (parallel mode)*/ -#define R592_STATUS_P_CED (1 << 19) /* INT reg: command done (parallel mode) */ - - /* Fifo status */ -#define R592_STATUS_SFIFO_FULL (1 << 20) /* Small Fifo almost full (last chunk is written) */ -#define R592_STATUS_SFIFO_EMPTY (1 << 21) /* Small Fifo empty */ - - /* Error detection via CRC */ -#define R592_STATUS_SEND_ERR (1 << 24) /* Send failed */ -#define R592_STATUS_RECV_ERR (1 << 25) /* Recieve failed */ - - /* Card state */ -#define R592_STATUS_RDY (1 << 28) /* RDY signal recieved */ -#define R592_STATUS_CED (1 << 29) /* INT: Command done (serial mode)*/ -#define R592_STATUS_SFIFO_INPUT (1 << 30) /* Small fifo recieved data*/ - -#define R592_SFIFO_SIZE 32 /* total size of small fifo is 32 bytes */ -#define R592_SFIFO_PACKET 8 /* packet size of small fifo */ - -/* IO control */ -#define R592_IO 0x18 -#define R592_IO_16 (1 << 16) /* Set by default, can be cleared */ -#define R592_IO_18 (1 << 18) /* Set by default, can be cleared */ -#define R592_IO_SERIAL1 (1 << 20) /* Set by default, can be cleared, (cleared on parallel) */ -#define R592_IO_22 (1 << 22) /* Set by default, can be cleared */ -#define R592_IO_DIRECTION (1 << 24) /* TPC direction (1 write 0 read) */ -#define R592_IO_26 (1 << 26) /* Set by default, can be cleared */ -#define R592_IO_SERIAL2 (1 << 30) /* Set by default, can be cleared (cleared on parallel), serial doesn't work if unset */ -#define R592_IO_RESET (1 << 31) /* Reset, sets defaults*/ - - -/* Turns hardware on/off */ -#define R592_POWER 0x20 /* bits 0-7 writeable */ -#define R592_POWER_0 (1 << 0) /* set on start, cleared on stop - must be set*/ -#define R592_POWER_1 (1 << 1) /* set on start, cleared on stop - must be set*/ -#define R592_POWER_3 (1 << 3) /* must be clear */ -#define R592_POWER_20 (1 << 5) /* set before switch to parallel */ - -/* IO mode*/ -#define R592_IO_MODE 0x24 -#define R592_IO_MODE_SERIAL 1 -#define R592_IO_MODE_PARALLEL 3 - - -/* IRQ,card detection,large fifo (first word irq status, second enable) */ -/* IRQs are ACKed by clearing the bits */ -#define R592_REG_MSC 0x28 -#define R592_REG_MSC_PRSNT (1 << 1) /* card present (only status)*/ -#define R592_REG_MSC_IRQ_INSERT (1 << 8) /* detect insert / card insered */ -#define R592_REG_MSC_IRQ_REMOVE (1 << 9) /* detect removal / card removed */ -#define R592_REG_MSC_FIFO_EMPTY (1 << 10) /* fifo is empty */ -#define R592_REG_MSC_FIFO_DMA_DONE (1 << 11) /* dma enable / dma done */ - -#define R592_REG_MSC_FIFO_USER_ORN (1 << 12) /* set if software reads empty fifo (if R592_REG_MSC_FIFO_EMPTY is set) */ -#define R592_REG_MSC_FIFO_MISMATH (1 << 13) /* set if amount of data in fifo doesn't match amount in TPC */ -#define R592_REG_MSC_FIFO_DMA_ERR (1 << 14) /* IO failure */ -#define R592_REG_MSC_LED (1 << 15) /* clear to turn led off (only status)*/ - -#define DMA_IRQ_ACK_MASK \ - (R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR) - -#define DMA_IRQ_EN_MASK (DMA_IRQ_ACK_MASK << 16) - -#define IRQ_ALL_ACK_MASK 0x00007F00 -#define IRQ_ALL_EN_MASK (IRQ_ALL_ACK_MASK << 16) - -/* DMA address for large FIFO read/writes*/ -#define R592_FIFO_DMA 0x2C - -/* PIO access to large FIFO (512 bytes) (big endian)*/ -#define R592_FIFO_PIO 0x30 -#define R592_LFIFO_SIZE 512 /* large fifo size */ - - -/* large FIFO DMA settings */ -#define R592_FIFO_DMA_SETTINGS 0x34 -#define R592_FIFO_DMA_SETTINGS_EN (1 << 0) /* DMA enabled */ -#define R592_FIFO_DMA_SETTINGS_DIR (1 << 1) /* Dma direction (1 read, 0 write) */ -#define R592_FIFO_DMA_SETTINGS_CAP (1 << 24) /* Dma is aviable */ - -/* Maybe just an delay */ -/* Bits 17..19 are just number */ -/* bit 16 is set, then bit 20 is waited */ -/* time to wait is about 50 spins * 2 ^ (bits 17..19) */ -/* seems to be possible just to ignore */ -/* Probably debug register */ -#define R592_REG38 0x38 -#define R592_REG38_CHANGE (1 << 16) /* Start bit */ -#define R592_REG38_DONE (1 << 20) /* HW set this after the delay */ -#define R592_REG38_SHIFT 17 - -/* Debug register, written (0xABCDEF00) when error happens - not used*/ -#define R592_REG_3C 0x3C - -struct r592_device { - struct pci_dev *pci_dev; - struct memstick_host *host; /* host backpointer */ - struct memstick_request *req; /* current request */ - - /* Registers, IRQ */ - void __iomem *mmio; - int irq; - spinlock_t irq_lock; - spinlock_t io_thread_lock; - struct timer_list detect_timer; - - struct task_struct *io_thread; - bool parallel_mode; - - DECLARE_KFIFO(pio_fifo, u8, sizeof(u32)); - - /* DMA area */ - int dma_capable; - int dma_error; - struct completion dma_done; - void *dummy_dma_page; - dma_addr_t dummy_dma_page_physical_address; - -}; - -#define DRV_NAME "r592" - - -#define message(format, ...) \ - printk(KERN_INFO DRV_NAME ": " format "\n", ## __VA_ARGS__) - -#define __dbg(level, format, ...) \ - do { \ - if (debug >= level) \ - printk(KERN_DEBUG DRV_NAME \ - ": " format "\n", ## __VA_ARGS__); \ - } while (0) - - -#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) -#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__) -#define dbg_reg(format, ...) __dbg(3, format, ## __VA_ARGS__) - -#endif diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 459f2cbe80fc..379d8592bc6e 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -3982,10 +3982,8 @@ static int dasd_eckd_reload_device(struct dasd_device *device) } static struct ccw_driver dasd_eckd_driver = { - .driver = { - .name = "dasd-eckd", - .owner = THIS_MODULE, - }, + .name = "dasd-eckd", + .owner = THIS_MODULE, .ids = dasd_eckd_ids, .probe = dasd_eckd_probe, .remove = dasd_generic_remove, diff --git a/trunk/drivers/s390/block/dasd_fba.c b/trunk/drivers/s390/block/dasd_fba.c index 4b71b1164868..be89b3a893da 100644 --- a/trunk/drivers/s390/block/dasd_fba.c +++ b/trunk/drivers/s390/block/dasd_fba.c @@ -65,10 +65,8 @@ dasd_fba_set_online(struct ccw_device *cdev) } static struct ccw_driver dasd_fba_driver = { - .driver = { - .name = "dasd-fba", - .owner = THIS_MODULE, - }, + .name = "dasd-fba", + .owner = THIS_MODULE, .ids = dasd_fba_ids, .probe = dasd_fba_probe, .remove = dasd_generic_remove, diff --git a/trunk/drivers/s390/char/con3215.c b/trunk/drivers/s390/char/con3215.c index 694464c65fcd..3fb4335d491d 100644 --- a/trunk/drivers/s390/char/con3215.c +++ b/trunk/drivers/s390/char/con3215.c @@ -764,10 +764,8 @@ static struct ccw_device_id raw3215_id[] = { }; static struct ccw_driver raw3215_ccw_driver = { - .driver = { - .name = "3215", - .owner = THIS_MODULE, - }, + .name = "3215", + .owner = THIS_MODULE, .ids = raw3215_id, .probe = &raw3215_probe, .remove = &raw3215_remove, diff --git a/trunk/drivers/s390/char/raw3270.c b/trunk/drivers/s390/char/raw3270.c index 4c023761946f..96ba2fd1c8ad 100644 --- a/trunk/drivers/s390/char/raw3270.c +++ b/trunk/drivers/s390/char/raw3270.c @@ -1388,10 +1388,8 @@ static struct ccw_device_id raw3270_id[] = { }; static struct ccw_driver raw3270_ccw_driver = { - .driver = { - .name = "3270", - .owner = THIS_MODULE, - }, + .name = "3270", + .owner = THIS_MODULE, .ids = raw3270_id, .probe = &raw3270_probe, .remove = &raw3270_remove, diff --git a/trunk/drivers/s390/char/tape_34xx.c b/trunk/drivers/s390/char/tape_34xx.c index 9eff2df70ddb..c26511171ffe 100644 --- a/trunk/drivers/s390/char/tape_34xx.c +++ b/trunk/drivers/s390/char/tape_34xx.c @@ -1320,10 +1320,8 @@ tape_34xx_online(struct ccw_device *cdev) } static struct ccw_driver tape_34xx_driver = { - .driver = { - .name = "tape_34xx", - .owner = THIS_MODULE, - }, + .name = "tape_34xx", + .owner = THIS_MODULE, .ids = tape_34xx_ids, .probe = tape_generic_probe, .remove = tape_generic_remove, diff --git a/trunk/drivers/s390/char/tape_3590.c b/trunk/drivers/s390/char/tape_3590.c index b98dcbd16711..de2e99e0a71b 100644 --- a/trunk/drivers/s390/char/tape_3590.c +++ b/trunk/drivers/s390/char/tape_3590.c @@ -1761,10 +1761,8 @@ tape_3590_online(struct ccw_device *cdev) } static struct ccw_driver tape_3590_driver = { - .driver = { - .name = "tape_3590", - .owner = THIS_MODULE, - }, + .name = "tape_3590", + .owner = THIS_MODULE, .ids = tape_3590_ids, .probe = tape_generic_probe, .remove = tape_generic_remove, diff --git a/trunk/drivers/s390/char/vmur.c b/trunk/drivers/s390/char/vmur.c index f6b00c3df425..caef1757341d 100644 --- a/trunk/drivers/s390/char/vmur.c +++ b/trunk/drivers/s390/char/vmur.c @@ -64,10 +64,8 @@ static int ur_set_offline(struct ccw_device *cdev); static int ur_pm_suspend(struct ccw_device *cdev); static struct ccw_driver ur_driver = { - .driver = { - .name = "vmur", - .owner = THIS_MODULE, - }, + .name = "vmur", + .owner = THIS_MODULE, .ids = ur_ids, .probe = ur_probe, .remove = ur_remove, diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index 5c567414c4bb..2864581d8ecb 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -428,7 +428,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - if (!try_module_get(gdrv->driver.owner)) + if (!try_module_get(gdrv->owner)) return -EINVAL; ret = strict_strtoul(buf, 0, &value); @@ -442,7 +442,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const else ret = -EINVAL; out: - module_put(gdrv->driver.owner); + module_put(gdrv->owner); return (ret == 0) ? count : ret; } @@ -616,6 +616,8 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ cdriver->driver.bus = &ccwgroup_bus_type; + cdriver->driver.name = cdriver->name; + cdriver->driver.owner = cdriver->owner; return driver_register(&cdriver->driver); } diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index df14c51f6532..e50b12163afe 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -127,7 +127,7 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) return ret; } -static struct bus_type ccw_bus_type; +struct bus_type ccw_bus_type; static void io_subchannel_irq(struct subchannel *); static int io_subchannel_probe(struct subchannel *); @@ -547,7 +547,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) return -EAGAIN; - if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { + if (cdev->drv && !try_module_get(cdev->drv->owner)) { atomic_set(&cdev->private->onoff, 0); return -EINVAL; } @@ -573,7 +573,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, } out: if (cdev->drv) - module_put(cdev->drv->driver.owner); + module_put(cdev->drv->owner); atomic_set(&cdev->private->onoff, 0); return (ret < 0) ? ret : count; } @@ -1970,7 +1970,7 @@ static const struct dev_pm_ops ccw_pm_ops = { .restore = ccw_device_pm_restore, }; -static struct bus_type ccw_bus_type = { +struct bus_type ccw_bus_type = { .name = "ccw", .match = ccw_bus_match, .uevent = ccw_uevent, @@ -1993,6 +1993,8 @@ int ccw_driver_register(struct ccw_driver *cdriver) struct device_driver *drv = &cdriver->driver; drv->bus = &ccw_bus_type; + drv->name = cdriver->name; + drv->owner = cdriver->owner; return driver_register(drv); } @@ -2110,4 +2112,5 @@ EXPORT_SYMBOL(ccw_device_set_offline); EXPORT_SYMBOL(ccw_driver_register); EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); +EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/trunk/drivers/s390/cio/device.h b/trunk/drivers/s390/cio/device.h index 7e297c7bb5ff..379de2d1ec49 100644 --- a/trunk/drivers/s390/cio/device.h +++ b/trunk/drivers/s390/cio/device.h @@ -133,6 +133,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); +extern struct bus_type ccw_bus_type; /* Channel measurement facility related */ void retry_set_schib(struct ccw_device *cdev); diff --git a/trunk/drivers/s390/cio/qdio_main.c b/trunk/drivers/s390/cio/qdio_main.c index 479c665e9e7c..5640c89cd9de 100644 --- a/trunk/drivers/s390/cio/qdio_main.c +++ b/trunk/drivers/s390/cio/qdio_main.c @@ -1508,8 +1508,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) return -EBUSY; - if (!count) - return 0; + if (callflags & QDIO_FLAG_SYNC_INPUT) return handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr, count); diff --git a/trunk/drivers/s390/net/claw.c b/trunk/drivers/s390/net/claw.c index 9feb62febb3d..ce3a5c13ce0b 100644 --- a/trunk/drivers/s390/net/claw.c +++ b/trunk/drivers/s390/net/claw.c @@ -264,10 +264,8 @@ static struct device *claw_root_dev; /* ccwgroup table */ static struct ccwgroup_driver claw_group_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "claw", - }, + .owner = THIS_MODULE, + .name = "claw", .max_slaves = 2, .driver_id = 0xC3D3C1E6, .probe = claw_probe, @@ -284,10 +282,8 @@ static struct ccw_device_id claw_ids[] = { MODULE_DEVICE_TABLE(ccw, claw_ids); static struct ccw_driver claw_ccw_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "claw", - }, + .owner = THIS_MODULE, + .name = "claw", .ids = claw_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, diff --git a/trunk/drivers/s390/net/ctcm_main.c b/trunk/drivers/s390/net/ctcm_main.c index c189296763a4..4c2845985927 100644 --- a/trunk/drivers/s390/net/ctcm_main.c +++ b/trunk/drivers/s390/net/ctcm_main.c @@ -1764,20 +1764,16 @@ static struct ccw_device_id ctcm_ids[] = { MODULE_DEVICE_TABLE(ccw, ctcm_ids); static struct ccw_driver ctcm_ccw_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "ctcm", - }, + .owner = THIS_MODULE, + .name = "ctcm", .ids = ctcm_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, }; static struct ccwgroup_driver ctcm_group_driver = { - .driver = { - .owner = THIS_MODULE, - .name = CTC_DRIVER_NAME, - }, + .owner = THIS_MODULE, + .name = CTC_DRIVER_NAME, .max_slaves = 2, .driver_id = 0xC3E3C3D4, /* CTCM */ .probe = ctcm_probe_device, diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index 7fbc4adbb6d5..30b2a820e670 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -2396,10 +2396,8 @@ static struct ccw_device_id lcs_ids[] = { MODULE_DEVICE_TABLE(ccw, lcs_ids); static struct ccw_driver lcs_ccw_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "lcs", - }, + .owner = THIS_MODULE, + .name = "lcs", .ids = lcs_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, @@ -2409,10 +2407,8 @@ static struct ccw_driver lcs_ccw_driver = { * LCS ccwgroup driver registration */ static struct ccwgroup_driver lcs_group_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "lcs", - }, + .owner = THIS_MODULE, + .name = "lcs", .max_slaves = 2, .driver_id = 0xD3C3E2, .probe = lcs_probe_device, diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index 10a3a3b4dd3e..25eef304bd47 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -3902,9 +3902,7 @@ static struct ccw_device_id qeth_ids[] = { MODULE_DEVICE_TABLE(ccw, qeth_ids); static struct ccw_driver qeth_ccw_driver = { - .driver = { - .name = "qeth", - }, + .name = "qeth", .ids = qeth_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, @@ -4430,10 +4428,8 @@ static int qeth_core_restore(struct ccwgroup_device *gdev) } static struct ccwgroup_driver qeth_core_ccwgroup_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "qeth", - }, + .owner = THIS_MODULE, + .name = "qeth", .driver_id = 0xD8C5E3C8, .probe = qeth_core_probe_device, .remove = qeth_core_remove_device, diff --git a/trunk/drivers/s390/scsi/zfcp_ccw.c b/trunk/drivers/s390/scsi/zfcp_ccw.c index e8b7cee62046..4f7852dd30c7 100644 --- a/trunk/drivers/s390/scsi/zfcp_ccw.c +++ b/trunk/drivers/s390/scsi/zfcp_ccw.c @@ -251,10 +251,8 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) } struct ccw_driver zfcp_ccw_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "zfcp", - }, + .owner = THIS_MODULE, + .name = "zfcp", .ids = zfcp_ccw_device_id, .probe = zfcp_ccw_probe, .remove = zfcp_ccw_remove, diff --git a/trunk/fs/coda/sysctl.c b/trunk/fs/coda/sysctl.c index af56ad56a89a..06d27a41807f 100644 --- a/trunk/fs/coda/sysctl.c +++ b/trunk/fs/coda/sysctl.c @@ -61,13 +61,4 @@ void coda_sysctl_clean(void) fs_table_header = NULL; } } - -#else -void coda_sysctl_init(void) -{ -} - -void coda_sysctl_clean(void) -{ -} #endif diff --git a/trunk/fs/ext4/balloc.c b/trunk/fs/ext4/balloc.c index 97b970e7dd13..adf96b822781 100644 --- a/trunk/fs/ext4/balloc.c +++ b/trunk/fs/ext4/balloc.c @@ -21,8 +21,6 @@ #include "ext4_jbd2.h" #include "mballoc.h" -#include - /* * balloc.c contains the blocks allocation and deallocation routines */ @@ -344,7 +342,6 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) * We do it here so the bitmap uptodate bit * get set with buffer lock held. */ - trace_ext4_read_block_bitmap_load(sb, block_group); set_bitmap_uptodate(bh); if (bh_submit_read(bh) < 0) { put_bh(bh); diff --git a/trunk/fs/ext4/ext4_jbd2.h b/trunk/fs/ext4/ext4_jbd2.h index e25e99bf7ee1..d8b992e658c1 100644 --- a/trunk/fs/ext4/ext4_jbd2.h +++ b/trunk/fs/ext4/ext4_jbd2.h @@ -202,6 +202,13 @@ static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed) return 1; } +static inline void ext4_journal_release_buffer(handle_t *handle, + struct buffer_head *bh) +{ + if (ext4_handle_valid(handle)) + jbd2_journal_release_buffer(handle, bh); +} + static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks) { return ext4_journal_start_sb(inode->i_sb, nblocks); diff --git a/trunk/fs/ext4/extents.c b/trunk/fs/ext4/extents.c index dd2cb5076ff9..7516fb9c0bd5 100644 --- a/trunk/fs/ext4/extents.c +++ b/trunk/fs/ext4/extents.c @@ -44,8 +44,6 @@ #include "ext4_jbd2.h" #include "ext4_extents.h" -#include - static int ext4_ext_truncate_extend_restart(handle_t *handle, struct inode *inode, int needed) @@ -666,8 +664,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, if (unlikely(!bh)) goto err; if (!bh_uptodate_or_lock(bh)) { - trace_ext4_ext_load_extent(inode, block, - path[ppos].p_block); if (bh_submit_read(bh) < 0) { put_bh(bh); goto err; @@ -1038,7 +1034,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, for (i = 0; i < depth; i++) { if (!ablocks[i]) continue; - ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, + ext4_free_blocks(handle, inode, 0, ablocks[i], 1, EXT4_FREE_BLOCKS_METADATA); } } @@ -2063,7 +2059,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, if (err) return err; ext_debug("index is empty, remove it, free block %llu\n", leaf); - ext4_free_blocks(handle, inode, NULL, leaf, 1, + ext4_free_blocks(handle, inode, 0, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return err; } @@ -2160,7 +2156,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, num = le32_to_cpu(ex->ee_block) + ee_len - from; start = ext4_ext_pblock(ex) + ee_len - num; ext_debug("free last %u blocks starting %llu\n", num, start); - ext4_free_blocks(handle, inode, NULL, start, num, flags); + ext4_free_blocks(handle, inode, 0, start, num, flags); } else if (from == le32_to_cpu(ex->ee_block) && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", @@ -3112,13 +3108,14 @@ static int check_eofblocks_fl(handle_t *handle, struct inode *inode, { int i, depth; struct ext4_extent_header *eh; - struct ext4_extent *last_ex; + struct ext4_extent *ex, *last_ex; if (!ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)) return 0; depth = ext_depth(inode); eh = path[depth].p_hdr; + ex = path[depth].p_ext; if (unlikely(!eh->eh_entries)) { EXT4_ERROR_INODE(inode, "eh->eh_entries == 0 and " @@ -3298,8 +3295,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags) { struct ext4_ext_path *path = NULL; + struct ext4_extent_header *eh; struct ext4_extent newex, *ex; - ext4_fsblk_t newblock = 0; + ext4_fsblk_t newblock; int err = 0, depth, ret; unsigned int allocated = 0; struct ext4_allocation_request ar; @@ -3307,7 +3305,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext_debug("blocks %u/%u requested for inode %lu\n", map->m_lblk, map->m_len, inode->i_ino); - trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); /* check in cache */ if (ext4_ext_in_cache(inode, map->m_lblk, &newex)) { @@ -3355,6 +3352,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, err = -EIO; goto out2; } + eh = path[depth].p_hdr; ex = path[depth].p_ext; if (ex) { @@ -3487,7 +3485,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), + ext4_free_blocks(handle, inode, 0, ext4_ext_pblock(&newex), ext4_ext_get_actual_len(&newex), 0); goto out2; } @@ -3527,8 +3525,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext4_ext_drop_refs(path); kfree(path); } - trace_ext4_ext_map_blocks_exit(inode, map->m_lblk, - newblock, map->m_len, err ? err : allocated); return err ? err : allocated; } @@ -3662,7 +3658,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) return -EOPNOTSUPP; - trace_ext4_fallocate_enter(inode, offset, len, mode); map.m_lblk = offset >> blkbits; /* * We can't just convert len to max_blocks because @@ -3678,7 +3673,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) ret = inode_newsize_ok(inode, (len + offset)); if (ret) { mutex_unlock(&inode->i_mutex); - trace_ext4_fallocate_exit(inode, offset, max_blocks, ret); return ret; } retry: @@ -3723,8 +3717,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) goto retry; } mutex_unlock(&inode->i_mutex); - trace_ext4_fallocate_exit(inode, offset, max_blocks, - ret > 0 ? ret2 : ret); return ret > 0 ? ret2 : ret; } @@ -3783,7 +3775,6 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, } return ret > 0 ? ret2 : ret; } - /* * Callback function called for each extent to gather FIEMAP information. */ @@ -3791,162 +3782,38 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, struct ext4_ext_cache *newex, struct ext4_extent *ex, void *data) { + struct fiemap_extent_info *fieinfo = data; + unsigned char blksize_bits = inode->i_sb->s_blocksize_bits; __u64 logical; __u64 physical; __u64 length; - loff_t size; __u32 flags = 0; - int ret = 0; - struct fiemap_extent_info *fieinfo = data; - unsigned char blksize_bits; + int error; - blksize_bits = inode->i_sb->s_blocksize_bits; - logical = (__u64)newex->ec_block << blksize_bits; + logical = (__u64)newex->ec_block << blksize_bits; if (newex->ec_start == 0) { - /* - * No extent in extent-tree contains block @newex->ec_start, - * then the block may stay in 1)a hole or 2)delayed-extent. - * - * Holes or delayed-extents are processed as follows. - * 1. lookup dirty pages with specified range in pagecache. - * If no page is got, then there is no delayed-extent and - * return with EXT_CONTINUE. - * 2. find the 1st mapped buffer, - * 3. check if the mapped buffer is both in the request range - * and a delayed buffer. If not, there is no delayed-extent, - * then return. - * 4. a delayed-extent is found, the extent will be collected. - */ - ext4_lblk_t end = 0; - pgoff_t last_offset; - pgoff_t offset; - pgoff_t index; - struct page **pages = NULL; + pgoff_t offset; + struct page *page; struct buffer_head *bh = NULL; - struct buffer_head *head = NULL; - unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *); - - pages = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (pages == NULL) - return -ENOMEM; offset = logical >> PAGE_SHIFT; -repeat: - last_offset = offset; - head = NULL; - ret = find_get_pages_tag(inode->i_mapping, &offset, - PAGECACHE_TAG_DIRTY, nr_pages, pages); - - if (!(flags & FIEMAP_EXTENT_DELALLOC)) { - /* First time, try to find a mapped buffer. */ - if (ret == 0) { -out: - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - /* just a hole. */ - kfree(pages); - return EXT_CONTINUE; - } + page = find_get_page(inode->i_mapping, offset); + if (!page || !page_has_buffers(page)) + return EXT_CONTINUE; - /* Try to find the 1st mapped buffer. */ - end = ((__u64)pages[0]->index << PAGE_SHIFT) >> - blksize_bits; - if (!page_has_buffers(pages[0])) - goto out; - head = page_buffers(pages[0]); - if (!head) - goto out; + bh = page_buffers(page); - bh = head; - do { - if (buffer_mapped(bh)) { - /* get the 1st mapped buffer. */ - if (end > newex->ec_block + - newex->ec_len) - /* The buffer is out of - * the request range. - */ - goto out; - goto found_mapped_buffer; - } - bh = bh->b_this_page; - end++; - } while (bh != head); + if (!bh) + return EXT_CONTINUE; - /* No mapped buffer found. */ - goto out; + if (buffer_delay(bh)) { + flags |= FIEMAP_EXTENT_DELALLOC; + page_cache_release(page); } else { - /*Find contiguous delayed buffers. */ - if (ret > 0 && pages[0]->index == last_offset) - head = page_buffers(pages[0]); - bh = head; + page_cache_release(page); + return EXT_CONTINUE; } - -found_mapped_buffer: - if (bh != NULL && buffer_delay(bh)) { - /* 1st or contiguous delayed buffer found. */ - if (!(flags & FIEMAP_EXTENT_DELALLOC)) { - /* - * 1st delayed buffer found, record - * the start of extent. - */ - flags |= FIEMAP_EXTENT_DELALLOC; - newex->ec_block = end; - logical = (__u64)end << blksize_bits; - } - /* Find contiguous delayed buffers. */ - do { - if (!buffer_delay(bh)) - goto found_delayed_extent; - bh = bh->b_this_page; - end++; - } while (bh != head); - - for (index = 1; index < ret; index++) { - if (!page_has_buffers(pages[index])) { - bh = NULL; - break; - } - head = page_buffers(pages[index]); - if (!head) { - bh = NULL; - break; - } - if (pages[index]->index != - pages[0]->index + index) { - /* Blocks are not contiguous. */ - bh = NULL; - break; - } - bh = head; - do { - if (!buffer_delay(bh)) - /* Delayed-extent ends. */ - goto found_delayed_extent; - bh = bh->b_this_page; - end++; - } while (bh != head); - } - } else if (!(flags & FIEMAP_EXTENT_DELALLOC)) - /* a hole found. */ - goto out; - -found_delayed_extent: - newex->ec_len = min(end - newex->ec_block, - (ext4_lblk_t)EXT_INIT_MAX_LEN); - if (ret == nr_pages && bh != NULL && - newex->ec_len < EXT_INIT_MAX_LEN && - buffer_delay(bh)) { - /* Have not collected an extent and continue. */ - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - goto repeat; - } - - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - kfree(pages); } physical = (__u64)newex->ec_start << blksize_bits; @@ -3955,16 +3822,32 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, if (ex && ext4_ext_is_uninitialized(ex)) flags |= FIEMAP_EXTENT_UNWRITTEN; - size = i_size_read(inode); - if (logical + length >= size) + /* + * If this extent reaches EXT_MAX_BLOCK, it must be last. + * + * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK, + * this also indicates no more allocated blocks. + * + * XXX this might miss a single-block extent at EXT_MAX_BLOCK + */ + if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK || + newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) { + loff_t size = i_size_read(inode); + loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb); + flags |= FIEMAP_EXTENT_LAST; + if ((flags & FIEMAP_EXTENT_DELALLOC) && + logical+length > size) + length = (size - logical + bs - 1) & ~(bs-1); + } - ret = fiemap_fill_next_extent(fieinfo, logical, physical, + error = fiemap_fill_next_extent(fieinfo, logical, physical, length, flags); - if (ret < 0) - return ret; - if (ret == 1) + if (error < 0) + return error; + if (error == 1) return EXT_BREAK; + return EXT_CONTINUE; } diff --git a/trunk/fs/ext4/fsync.c b/trunk/fs/ext4/fsync.c index 7f74019d6d77..7829b287822a 100644 --- a/trunk/fs/ext4/fsync.c +++ b/trunk/fs/ext4/fsync.c @@ -164,20 +164,20 @@ int ext4_sync_file(struct file *file, int datasync) J_ASSERT(ext4_journal_current_handle() == NULL); - trace_ext4_sync_file_enter(file, datasync); + trace_ext4_sync_file(file, datasync); if (inode->i_sb->s_flags & MS_RDONLY) return 0; ret = ext4_flush_completed_IO(inode); if (ret < 0) - goto out; + return ret; if (!journal) { ret = generic_file_fsync(file, datasync); if (!ret && !list_empty(&inode->i_dentry)) ext4_sync_parent(inode); - goto out; + return ret; } /* @@ -194,10 +194,8 @@ int ext4_sync_file(struct file *file, int datasync) * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ - if (ext4_should_journal_data(inode)) { - ret = ext4_force_commit(inode->i_sb); - goto out; - } + if (ext4_should_journal_data(inode)) + return ext4_force_commit(inode->i_sb); commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; if (jbd2_log_start_commit(journal, commit_tid)) { @@ -217,7 +215,5 @@ int ext4_sync_file(struct file *file, int datasync) ret = jbd2_log_wait_commit(journal, commit_tid); } else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); - out: - trace_ext4_sync_file_exit(inode, ret); return ret; } diff --git a/trunk/fs/ext4/ialloc.c b/trunk/fs/ext4/ialloc.c index 21bb2f61e502..78b79e1bd7ed 100644 --- a/trunk/fs/ext4/ialloc.c +++ b/trunk/fs/ext4/ialloc.c @@ -152,7 +152,6 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) * We do it here so the bitmap uptodate bit * get set with buffer lock held. */ - trace_ext4_load_inode_bitmap(sb, block_group); set_bitmap_uptodate(bh); if (bh_submit_read(bh) < 0) { put_bh(bh); @@ -650,7 +649,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent, *group = parent_group + flex_size; if (*group > ngroups) *group = 0; - return find_group_orlov(sb, parent, group, mode, NULL); + return find_group_orlov(sb, parent, group, mode, 0); } /* @@ -1055,11 +1054,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, } } - if (ext4_handle_valid(handle)) { - ei->i_sync_tid = handle->h_transaction->t_tid; - ei->i_datasync_tid = handle->h_transaction->t_tid; - } - err = ext4_mark_inode_dirty(handle, inode); if (err) { ext4_std_error(sb, err); diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index 1a86282b9024..9297ad46c465 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -173,7 +173,7 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, BUG_ON(EXT4_JOURNAL(inode) == NULL); jbd_debug(2, "restarting handle %p\n", handle); up_write(&EXT4_I(inode)->i_data_sem); - ret = ext4_journal_restart(handle, nblocks); + ret = ext4_journal_restart(handle, blocks_for_truncate(inode)); down_write(&EXT4_I(inode)->i_data_sem); ext4_discard_preallocations(inode); @@ -720,7 +720,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode, return ret; failed_out: for (i = 0; i < index; i++) - ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); return ret; } @@ -823,20 +823,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, return err; failed: /* Allocation failed, free what we already allocated */ - ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0); for (i = 1; i <= n ; i++) { /* * branch[i].bh is newly allocated, so there is no * need to revoke the block, which is why we don't * need to set EXT4_FREE_BLOCKS_METADATA. */ - ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, EXT4_FREE_BLOCKS_FORGET); } for (i = n+1; i < indirect_blks; i++) - ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); - ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0); return err; } @@ -924,7 +924,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, where[i].bh, 0, 1, EXT4_FREE_BLOCKS_FORGET); } - ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key), + ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key), blks, 0); return err; @@ -973,7 +973,6 @@ static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, int count = 0; ext4_fsblk_t first_block = 0; - trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))); J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); depth = ext4_block_to_path(inode, map->m_lblk, offsets, @@ -1059,8 +1058,6 @@ static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, partial--; } out: - trace_ext4_ind_map_blocks_exit(inode, map->m_lblk, - map->m_pblk, map->m_len, err); return err; } @@ -2063,7 +2060,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { - int commit_write = 0, skip_page = 0; + int commit_write = 0, redirty_page = 0; struct page *page = pvec.pages[i]; index = page->index; @@ -2089,12 +2086,14 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, * If the page does not have buffers (for * whatever reason), try to create them using * __block_write_begin. If this fails, - * skip the page and move on. + * redirty the page and move on. */ if (!page_has_buffers(page)) { if (__block_write_begin(page, 0, len, noalloc_get_block_write)) { - skip_page: + redirty_page: + redirty_page_for_writepage(mpd->wbc, + page); unlock_page(page); continue; } @@ -2105,7 +2104,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, block_start = 0; do { if (!bh) - goto skip_page; + goto redirty_page; if (map && (cur_logical >= map->m_lblk) && (cur_logical <= (map->m_lblk + (map->m_len - 1)))) { @@ -2121,23 +2120,22 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, clear_buffer_unwritten(bh); } - /* skip page if block allocation undone */ + /* redirty page if block allocation undone */ if (buffer_delay(bh) || buffer_unwritten(bh)) - skip_page = 1; + redirty_page = 1; bh = bh->b_this_page; block_start += bh->b_size; cur_logical++; pblock++; } while (bh != page_bufs); - if (skip_page) - goto skip_page; + if (redirty_page) + goto redirty_page; if (commit_write) /* mark the buffer_heads as dirty & uptodate */ block_commit_write(page, 0, len); - clear_page_dirty_for_io(page); /* * Delalloc doesn't support data journalling, * but eventually maybe we'll lift this @@ -2167,7 +2165,8 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, return ret; } -static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) +static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, + sector_t logical, long blk_cnt) { int nr_pages, i; pgoff_t index, end; @@ -2175,8 +2174,9 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) struct inode *inode = mpd->inode; struct address_space *mapping = inode->i_mapping; - index = mpd->first_page; - end = mpd->next_page - 1; + index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); + end = (logical + blk_cnt - 1) >> + (PAGE_CACHE_SHIFT - inode->i_blkbits); while (index <= end) { nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); if (nr_pages == 0) @@ -2279,8 +2279,9 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) err = blks; /* * If get block returns EAGAIN or ENOSPC and there - * appears to be free blocks we will just let - * mpage_da_submit_io() unlock all of the pages. + * appears to be free blocks we will call + * ext4_writepage() for all of the pages which will + * just redirty the pages. */ if (err == -EAGAIN) goto submit_io; @@ -2311,10 +2312,8 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) ext4_print_free_blocks(mpd->inode); } /* invalidate all the pages */ - ext4_da_block_invalidatepages(mpd); - - /* Mark this page range as having been completed */ - mpd->io_done = 1; + ext4_da_block_invalidatepages(mpd, next, + mpd->b_size >> mpd->inode->i_blkbits); return; } BUG_ON(blks == 0); @@ -2438,6 +2437,102 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh) return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh); } +/* + * __mpage_da_writepage - finds extent of pages and blocks + * + * @page: page to consider + * @wbc: not used, we just follow rules + * @data: context + * + * The function finds extents of pages and scan them for all blocks. + */ +static int __mpage_da_writepage(struct page *page, + struct writeback_control *wbc, + struct mpage_da_data *mpd) +{ + struct inode *inode = mpd->inode; + struct buffer_head *bh, *head; + sector_t logical; + + /* + * Can we merge this page to current extent? + */ + if (mpd->next_page != page->index) { + /* + * Nope, we can't. So, we map non-allocated blocks + * and start IO on them + */ + if (mpd->next_page != mpd->first_page) { + mpage_da_map_and_submit(mpd); + /* + * skip rest of the page in the page_vec + */ + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return MPAGE_DA_EXTENT_TAIL; + } + + /* + * Start next extent of pages ... + */ + mpd->first_page = page->index; + + /* + * ... and blocks + */ + mpd->b_size = 0; + mpd->b_state = 0; + mpd->b_blocknr = 0; + } + + mpd->next_page = page->index + 1; + logical = (sector_t) page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + + if (!page_has_buffers(page)) { + mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, + (1 << BH_Dirty) | (1 << BH_Uptodate)); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; + } else { + /* + * Page with regular buffer heads, just add all dirty ones + */ + head = page_buffers(page); + bh = head; + do { + BUG_ON(buffer_locked(bh)); + /* + * We need to try to allocate + * unmapped blocks in the same page. + * Otherwise we won't make progress + * with the page in ext4_writepage + */ + if (ext4_bh_delay_or_unwritten(NULL, bh)) { + mpage_add_bh_to_extent(mpd, logical, + bh->b_size, + bh->b_state); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; + } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { + /* + * mapped dirty buffer. We need to update + * the b_state because we look at + * b_state in mpage_da_map_blocks. We don't + * update b_size because if we find an + * unmapped buffer_head later we need to + * use the b_state flag of that buffer_head. + */ + if (mpd->b_size == 0) + mpd->b_state = bh->b_state & BH_FLAGS; + } + logical++; + } while ((bh = bh->b_this_page) != head); + } + + return 0; +} + /* * This is a special get_blocks_t callback which is used by * ext4_da_write_begin(). It will either return mapped block or @@ -2502,6 +2597,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, * for partial write. */ set_buffer_new(bh); + set_buffer_mapped(bh); } return 0; } @@ -2715,27 +2811,27 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) /* * write_cache_pages_da - walk the list of dirty pages of the given - * address space and accumulate pages that need writing, and call - * mpage_da_map_and_submit to map a single contiguous memory region - * and then write them. + * address space and call the callback function (which usually writes + * the pages). + * + * This is a forked version of write_cache_pages(). Differences: + * Range cyclic is ignored. + * no_nrwrite_index_update is always presumed true */ static int write_cache_pages_da(struct address_space *mapping, struct writeback_control *wbc, struct mpage_da_data *mpd, pgoff_t *done_index) { - struct buffer_head *bh, *head; - struct inode *inode = mapping->host; - struct pagevec pvec; - unsigned int nr_pages; - sector_t logical; - pgoff_t index, end; - long nr_to_write = wbc->nr_to_write; - int i, tag, ret = 0; - - memset(mpd, 0, sizeof(struct mpage_da_data)); - mpd->wbc = wbc; - mpd->inode = inode; + int ret = 0; + int done = 0; + struct pagevec pvec; + unsigned nr_pages; + pgoff_t index; + pgoff_t end; /* Inclusive */ + long nr_to_write = wbc->nr_to_write; + int tag; + pagevec_init(&pvec, 0); index = wbc->range_start >> PAGE_CACHE_SHIFT; end = wbc->range_end >> PAGE_CACHE_SHIFT; @@ -2746,11 +2842,13 @@ static int write_cache_pages_da(struct address_space *mapping, tag = PAGECACHE_TAG_DIRTY; *done_index = index; - while (index <= end) { + while (!done && (index <= end)) { + int i; + nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) - return 0; + break; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; @@ -2762,100 +2860,60 @@ static int write_cache_pages_da(struct address_space *mapping, * mapping. However, page->index will not change * because we have a reference on the page. */ - if (page->index > end) - goto out; + if (page->index > end) { + done = 1; + break; + } *done_index = page->index + 1; - /* - * If we can't merge this page, and we have - * accumulated an contiguous region, write it - */ - if ((mpd->next_page != page->index) && - (mpd->next_page != mpd->first_page)) { - mpage_da_map_and_submit(mpd); - goto ret_extent_tail; - } - lock_page(page); /* - * If the page is no longer dirty, or its - * mapping no longer corresponds to inode we - * are writing (which means it has been - * truncated or invalidated), or the page is - * already under writeback and we are not - * doing a data integrity writeback, skip the page + * Page truncated or invalidated. We can freely skip it + * then, even for data integrity operations: the page + * has disappeared concurrently, so there could be no + * real expectation of this data interity operation + * even if there is now a new, dirty page at the same + * pagecache address. */ - if (!PageDirty(page) || - (PageWriteback(page) && - (wbc->sync_mode == WB_SYNC_NONE)) || - unlikely(page->mapping != mapping)) { + if (unlikely(page->mapping != mapping)) { +continue_unlock: unlock_page(page); continue; } - if (PageWriteback(page)) - wait_on_page_writeback(page); + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } - BUG_ON(PageWriteback(page)); + if (PageWriteback(page)) { + if (wbc->sync_mode != WB_SYNC_NONE) + wait_on_page_writeback(page); + else + goto continue_unlock; + } - if (mpd->next_page != page->index) - mpd->first_page = page->index; - mpd->next_page = page->index + 1; - logical = (sector_t) page->index << - (PAGE_CACHE_SHIFT - inode->i_blkbits); + BUG_ON(PageWriteback(page)); + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; - if (!page_has_buffers(page)) { - mpage_add_bh_to_extent(mpd, logical, - PAGE_CACHE_SIZE, - (1 << BH_Dirty) | (1 << BH_Uptodate)); - if (mpd->io_done) - goto ret_extent_tail; - } else { - /* - * Page with regular buffer heads, - * just add all dirty ones - */ - head = page_buffers(page); - bh = head; - do { - BUG_ON(buffer_locked(bh)); - /* - * We need to try to allocate - * unmapped blocks in the same page. - * Otherwise we won't make progress - * with the page in ext4_writepage - */ - if (ext4_bh_delay_or_unwritten(NULL, bh)) { - mpage_add_bh_to_extent(mpd, logical, - bh->b_size, - bh->b_state); - if (mpd->io_done) - goto ret_extent_tail; - } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { - /* - * mapped dirty buffer. We need - * to update the b_state - * because we look at b_state - * in mpage_da_map_blocks. We - * don't update b_size because - * if we find an unmapped - * buffer_head later we need to - * use the b_state flag of that - * buffer_head. - */ - if (mpd->b_size == 0) - mpd->b_state = bh->b_state & BH_FLAGS; - } - logical++; - } while ((bh = bh->b_this_page) != head); + ret = __mpage_da_writepage(page, wbc, mpd); + if (unlikely(ret)) { + if (ret == AOP_WRITEPAGE_ACTIVATE) { + unlock_page(page); + ret = 0; + } else { + done = 1; + break; + } } if (nr_to_write > 0) { nr_to_write--; if (nr_to_write == 0 && - wbc->sync_mode == WB_SYNC_NONE) + wbc->sync_mode == WB_SYNC_NONE) { /* * We stop writing back only if we are * not doing integrity sync. In case of @@ -2866,18 +2924,14 @@ static int write_cache_pages_da(struct address_space *mapping, * pages, but have not synced all of the * old dirty pages. */ - goto out; + done = 1; + break; + } } } pagevec_release(&pvec); cond_resched(); } - return 0; -ret_extent_tail: - ret = MPAGE_DA_EXTENT_TAIL; -out: - pagevec_release(&pvec); - cond_resched(); return ret; } @@ -2891,6 +2945,7 @@ static int ext4_da_writepages(struct address_space *mapping, struct mpage_da_data mpd; struct inode *inode = mapping->host; int pages_written = 0; + long pages_skipped; unsigned int max_pages; int range_cyclic, cycled = 1, io_done = 0; int needed_blocks, ret = 0; @@ -2973,6 +3028,11 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->nr_to_write = desired_nr_to_write; } + mpd.wbc = wbc; + mpd.inode = mapping->host; + + pages_skipped = wbc->pages_skipped; + retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); @@ -2999,10 +3059,22 @@ static int ext4_da_writepages(struct address_space *mapping, } /* - * Now call write_cache_pages_da() to find the next + * Now call __mpage_da_writepage to find the next * contiguous region of logical blocks that need - * blocks to be allocated by ext4 and submit them. + * blocks to be allocated by ext4. We don't actually + * submit the blocks for I/O here, even though + * write_cache_pages thinks it will, and will set the + * pages as clean for write before calling + * __mpage_da_writepage(). */ + mpd.b_size = 0; + mpd.b_state = 0; + mpd.b_blocknr = 0; + mpd.first_page = 0; + mpd.next_page = 0; + mpd.io_done = 0; + mpd.pages_written = 0; + mpd.retval = 0; ret = write_cache_pages_da(mapping, wbc, &mpd, &done_index); /* * If we have a contiguous extent of pages and we @@ -3024,6 +3096,7 @@ static int ext4_da_writepages(struct address_space *mapping, * and try again */ jbd2_journal_force_commit_nested(sbi->s_journal); + wbc->pages_skipped = pages_skipped; ret = 0; } else if (ret == MPAGE_DA_EXTENT_TAIL) { /* @@ -3031,6 +3104,7 @@ static int ext4_da_writepages(struct address_space *mapping, * rest of the pages */ pages_written += mpd.pages_written; + wbc->pages_skipped = pages_skipped; ret = 0; io_done = 1; } else if (wbc->nr_to_write) @@ -3048,6 +3122,11 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->range_end = mapping->writeback_index - 1; goto retry; } + if (pages_skipped != wbc->pages_skipped) + ext4_msg(inode->i_sb, KERN_CRIT, + "This should not happen leaving %s " + "with nr_to_write = %ld ret = %d", + __func__, wbc->nr_to_write, ret); /* Update index */ wbc->range_cyclic = range_cyclic; @@ -3381,7 +3460,6 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) static int ext4_readpage(struct file *file, struct page *page) { - trace_ext4_readpage(page); return mpage_readpage(page, ext4_get_block); } @@ -3416,8 +3494,6 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset) { journal_t *journal = EXT4_JOURNAL(page->mapping->host); - trace_ext4_invalidatepage(page, offset); - /* * free any io_end structure allocated for buffers to be discarded */ @@ -3439,8 +3515,6 @@ static int ext4_releasepage(struct page *page, gfp_t wait) { journal_t *journal = EXT4_JOURNAL(page->mapping->host); - trace_ext4_releasepage(page); - WARN_ON(PageChecked(page)); if (!page_has_buffers(page)) return 0; @@ -3799,16 +3873,11 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - ssize_t ret; - trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); - else - ret = ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); - trace_ext4_direct_IO_exit(inode, offset, - iov_length(iov, nr_segs), rw, ret); - return ret; + return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); + + return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); } /* @@ -4104,9 +4173,6 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth, * * We release `count' blocks on disk, but (last - first) may be greater * than `count' because there can be holes in there. - * - * Return 0 on success, 1 on invalid block range - * and < 0 on fatal error. */ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh, @@ -4133,32 +4199,33 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, if (bh) { BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, inode, bh); - if (unlikely(err)) - goto out_err; + if (unlikely(err)) { + ext4_std_error(inode->i_sb, err); + return 1; + } } err = ext4_mark_inode_dirty(handle, inode); - if (unlikely(err)) - goto out_err; + if (unlikely(err)) { + ext4_std_error(inode->i_sb, err); + return 1; + } err = ext4_truncate_restart_trans(handle, inode, blocks_for_truncate(inode)); - if (unlikely(err)) - goto out_err; + if (unlikely(err)) { + ext4_std_error(inode->i_sb, err); + return 1; + } if (bh) { BUFFER_TRACE(bh, "retaking write access"); - err = ext4_journal_get_write_access(handle, bh); - if (unlikely(err)) - goto out_err; + ext4_journal_get_write_access(handle, bh); } } for (p = first; p < last; p++) *p = 0; - ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags); + ext4_free_blocks(handle, inode, 0, block_to_free, count, flags); return 0; -out_err: - ext4_std_error(inode->i_sb, err); - return err; } /** @@ -4192,7 +4259,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, ext4_fsblk_t nr; /* Current block # */ __le32 *p; /* Pointer into inode/ind for current block */ - int err = 0; + int err; if (this_bh) { /* For indirect block */ BUFFER_TRACE(this_bh, "get_write_access"); @@ -4214,10 +4281,9 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } else if (nr == block_to_free + count) { count++; } else { - err = ext4_clear_blocks(handle, inode, this_bh, - block_to_free, count, - block_to_free_p, p); - if (err) + if (ext4_clear_blocks(handle, inode, this_bh, + block_to_free, count, + block_to_free_p, p)) break; block_to_free = nr; block_to_free_p = p; @@ -4226,12 +4292,9 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } } - if (!err && count > 0) - err = ext4_clear_blocks(handle, inode, this_bh, block_to_free, - count, block_to_free_p, p); - if (err < 0) - /* fatal error */ - return; + if (count > 0) + ext4_clear_blocks(handle, inode, this_bh, block_to_free, + count, block_to_free_p, p); if (this_bh) { BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata"); @@ -4349,7 +4412,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, * transaction where the data blocks are * actually freed. */ - ext4_free_blocks(handle, inode, NULL, nr, 1, + ext4_free_blocks(handle, inode, 0, nr, 1, EXT4_FREE_BLOCKS_METADATA| EXT4_FREE_BLOCKS_FORGET); @@ -4433,8 +4496,6 @@ void ext4_truncate(struct inode *inode) ext4_lblk_t last_block; unsigned blocksize = inode->i_sb->s_blocksize; - trace_ext4_truncate_enter(inode); - if (!ext4_can_truncate(inode)) return; @@ -4445,7 +4506,6 @@ void ext4_truncate(struct inode *inode) if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { ext4_ext_truncate(inode); - trace_ext4_truncate_exit(inode); return; } @@ -4575,7 +4635,6 @@ void ext4_truncate(struct inode *inode) ext4_orphan_del(handle, inode); ext4_journal_stop(handle); - trace_ext4_truncate_exit(inode); } /* @@ -4707,7 +4766,6 @@ static int __ext4_get_inode_loc(struct inode *inode, * has in-inode xattrs, or we don't have this inode in memory. * Read the block from disk. */ - trace_ext4_load_inode(inode); get_bh(bh); bh->b_end_io = end_buffer_read_sync; submit_bh(READ_META, bh); @@ -4813,7 +4871,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); - iloc.bh = NULL; + iloc.bh = 0; ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) diff --git a/trunk/fs/ext4/ioctl.c b/trunk/fs/ext4/ioctl.c index 808c554e773f..a84faa110bcd 100644 --- a/trunk/fs/ext4/ioctl.c +++ b/trunk/fs/ext4/ioctl.c @@ -334,22 +334,16 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case FITRIM: { struct super_block *sb = inode->i_sb; - struct request_queue *q = bdev_get_queue(sb->s_bdev); struct fstrim_range range; int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!blk_queue_discard(q)) - return -EOPNOTSUPP; - if (copy_from_user(&range, (struct fstrim_range *)arg, sizeof(range))) return -EFAULT; - range.minlen = max((unsigned int)range.minlen, - q->limits.discard_granularity); ret = ext4_trim_fs(sb, &range); if (ret < 0) return ret; @@ -427,7 +421,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } case EXT4_IOC_MOVE_EXT: - case FITRIM: break; default: return -ENOIOCTLCMD; diff --git a/trunk/fs/ext4/mballoc.c b/trunk/fs/ext4/mballoc.c index a5837a837a8b..d1fe09aea73d 100644 --- a/trunk/fs/ext4/mballoc.c +++ b/trunk/fs/ext4/mballoc.c @@ -432,10 +432,9 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) } /* at order 0 we see each particular block */ - if (order == 0) { - *max = 1 << (e4b->bd_blkbits + 3); + *max = 1 << (e4b->bd_blkbits + 3); + if (order == 0) return EXT4_MB_BITMAP(e4b); - } bb = EXT4_MB_BUDDY(e4b) + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order]; *max = EXT4_SB(e4b->bd_sb)->s_mb_maxs[order]; @@ -617,6 +616,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); grp = ext4_get_group_info(sb, e4b->bd_group); + buddy = mb_find_buddy(e4b, 0, &max); list_for_each(cur, &grp->bb_prealloc_list) { ext4_group_t groupnr; struct ext4_prealloc_space *pa; @@ -635,12 +635,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, #define mb_check_buddy(e4b) #endif -/* - * Divide blocks started from @first with length @len into - * smaller chunks with power of 2 blocks. - * Clear the bits in bitmap which the blocks of the chunk(s) covered, - * then increase bb_counters[] for corresponded chunk size. - */ +/* FIXME!! need more doc */ static void ext4_mb_mark_free_simple(struct super_block *sb, void *buddy, ext4_grpblk_t first, ext4_grpblk_t len, struct ext4_group_info *grp) @@ -2386,7 +2381,7 @@ static int ext4_mb_init_backend(struct super_block *sb) /* An 8TB filesystem with 64-bit pointers requires a 4096 byte * kmalloc. A 128kb malloc should suffice for a 256TB filesystem. * So a two level scheme suffices for now. */ - sbi->s_group_info = kzalloc(array_size, GFP_KERNEL); + sbi->s_group_info = kmalloc(array_size, GFP_KERNEL); if (sbi->s_group_info == NULL) { printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n"); return -ENOMEM; @@ -3213,7 +3208,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block, cur_distance = abs(goal_block - cpa->pa_pstart); new_distance = abs(goal_block - pa->pa_pstart); - if (cur_distance <= new_distance) + if (cur_distance < new_distance) return cpa; /* drop the previous reference */ @@ -3912,8 +3907,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac) struct super_block *sb = ac->ac_sb; ext4_group_t ngroups, i; - if (!mb_enable_debug || - (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)) + if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) return; printk(KERN_ERR "EXT4-fs: Can't allocate:" @@ -4759,8 +4753,7 @@ static int ext4_trim_extent(struct super_block *sb, int start, int count, * bitmap. Then issue a TRIM command on this extent and free the extent in * the group buddy bitmap. This is done until whole group is scanned. */ -static ext4_grpblk_t -ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, +ext4_grpblk_t ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t minblocks) { void *bitmap; @@ -4870,15 +4863,10 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) break; } - /* - * For all the groups except the last one, last block will - * always be EXT4_BLOCKS_PER_GROUP(sb), so we only need to - * change it for the last group in which case start + - * len < EXT4_BLOCKS_PER_GROUP(sb). - */ - if (first_block + len < EXT4_BLOCKS_PER_GROUP(sb)) + if (len >= EXT4_BLOCKS_PER_GROUP(sb)) + len -= (EXT4_BLOCKS_PER_GROUP(sb) - first_block); + else last_block = first_block + len; - len -= last_block - first_block; if (e4b.bd_info->bb_free >= minlen) { cnt = ext4_trim_all_free(sb, &e4b, first_block, diff --git a/trunk/fs/ext4/mballoc.h b/trunk/fs/ext4/mballoc.h index 22bd4d7f289b..b619322c76f0 100644 --- a/trunk/fs/ext4/mballoc.h +++ b/trunk/fs/ext4/mballoc.h @@ -169,7 +169,7 @@ struct ext4_allocation_context { /* original request */ struct ext4_free_extent ac_o_ex; - /* goal request (normalized ac_o_ex) */ + /* goal request (after normalization) */ struct ext4_free_extent ac_g_ex; /* the best found extent */ diff --git a/trunk/fs/ext4/migrate.c b/trunk/fs/ext4/migrate.c index d1bafa57f483..b0a126f23c20 100644 --- a/trunk/fs/ext4/migrate.c +++ b/trunk/fs/ext4/migrate.c @@ -263,7 +263,7 @@ static int free_dind_blocks(handle_t *handle, for (i = 0; i < max_entries; i++) { if (tmp_idata[i]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, NULL, + ext4_free_blocks(handle, inode, 0, le32_to_cpu(tmp_idata[i]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -271,7 +271,7 @@ static int free_dind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -302,7 +302,7 @@ static int free_tind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -315,7 +315,7 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) /* ei->i_data[EXT4_IND_BLOCK] */ if (i_data[0]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, NULL, + ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data[0]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -428,7 +428,7 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, NULL, block, 1, + ext4_free_blocks(handle, inode, 0, block, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return retval; } diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index 67fd0b025858..e781b7ea5630 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -40,7 +40,6 @@ #include "xattr.h" #include "acl.h" -#include /* * define how far ahead to read directories while searching them. */ @@ -2184,7 +2183,6 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) struct ext4_dir_entry_2 *de; handle_t *handle; - trace_ext4_unlink_enter(dir, dentry); /* Initialize quotas before so that eventual writes go * in separate transaction */ dquot_initialize(dir); @@ -2230,7 +2228,6 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) end_unlink: ext4_journal_stop(handle); brelse(bh); - trace_ext4_unlink_exit(dentry, retval); return retval; } @@ -2405,10 +2402,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, if (!new_inode && new_dir != old_dir && EXT4_DIR_LINK_MAX(new_dir)) goto end_rename; - BUFFER_TRACE(dir_bh, "get_write_access"); - retval = ext4_journal_get_write_access(handle, dir_bh); - if (retval) - goto end_rename; } if (!new_bh) { retval = ext4_add_entry(handle, new_dentry, old_inode); @@ -2416,9 +2409,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, goto end_rename; } else { BUFFER_TRACE(new_bh, "get write access"); - retval = ext4_journal_get_write_access(handle, new_bh); - if (retval) - goto end_rename; + ext4_journal_get_write_access(handle, new_bh); new_de->inode = cpu_to_le32(old_inode->i_ino); if (EXT4_HAS_INCOMPAT_FEATURE(new_dir->i_sb, EXT4_FEATURE_INCOMPAT_FILETYPE)) @@ -2479,6 +2470,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir); ext4_update_dx_flag(old_dir); if (dir_bh) { + BUFFER_TRACE(dir_bh, "get_write_access"); + ext4_journal_get_write_access(handle, dir_bh); PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); diff --git a/trunk/fs/ext4/page-io.c b/trunk/fs/ext4/page-io.c index b6dbd056fcb1..e2cd90e4bb7c 100644 --- a/trunk/fs/ext4/page-io.c +++ b/trunk/fs/ext4/page-io.c @@ -259,11 +259,6 @@ static void ext4_end_bio(struct bio *bio, int error) bi_sector >> (inode->i_blkbits - 9)); } - if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { - ext4_free_io_end(io_end); - return; - } - /* Add the io_end to per-inode completed io list*/ spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); @@ -284,9 +279,9 @@ void ext4_io_submit(struct ext4_io_submit *io) BUG_ON(bio_flagged(io->io_bio, BIO_EOPNOTSUPP)); bio_put(io->io_bio); } - io->io_bio = NULL; + io->io_bio = 0; io->io_op = 0; - io->io_end = NULL; + io->io_end = 0; } static int io_submit_init(struct ext4_io_submit *io, @@ -385,6 +380,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io, BUG_ON(!PageLocked(page)); BUG_ON(PageWriteback(page)); + set_page_writeback(page); + ClearPageError(page); io_page = kmem_cache_alloc(io_page_cachep, GFP_NOFS); if (!io_page) { @@ -395,8 +392,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io, io_page->p_page = page; atomic_set(&io_page->p_count, 1); get_page(page); - set_page_writeback(page); - ClearPageError(page); for (bh = head = page_buffers(page), block_start = 0; bh != head || !block_start; diff --git a/trunk/fs/ext4/resize.c b/trunk/fs/ext4/resize.c index 80bbc9c60c24..3ecc6e45d2f9 100644 --- a/trunk/fs/ext4/resize.c +++ b/trunk/fs/ext4/resize.c @@ -230,7 +230,7 @@ static int setup_new_group_blocks(struct super_block *sb, } /* Zero out all of the reserved backup group descriptor table blocks */ - ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb, GFP_NOFS); @@ -248,7 +248,7 @@ static int setup_new_group_blocks(struct super_block *sb, /* Zero out all of the inode table blocks */ block = input->inode_table; - ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS); if (err) @@ -499,12 +499,12 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, return err; exit_inode: - /* ext4_handle_release_buffer(handle, iloc.bh); */ + /* ext4_journal_release_buffer(handle, iloc.bh); */ brelse(iloc.bh); exit_dindj: - /* ext4_handle_release_buffer(handle, dind); */ + /* ext4_journal_release_buffer(handle, dind); */ exit_sbh: - /* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ + /* ext4_journal_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ exit_dind: brelse(dind); exit_bh: @@ -586,7 +586,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, /* int j; for (j = 0; j < i; j++) - ext4_handle_release_buffer(handle, primary[j]); + ext4_journal_release_buffer(handle, primary[j]); */ goto exit_bh; } diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index 22546ad7f0ae..203f9e4a70be 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -54,9 +54,9 @@ static struct proc_dir_entry *ext4_proc_root; static struct kset *ext4_kset; -static struct ext4_lazy_init *ext4_li_info; -static struct mutex ext4_li_mtx; -static struct ext4_features *ext4_feat; +struct ext4_lazy_init *ext4_li_info; +struct mutex ext4_li_mtx; +struct ext4_features *ext4_feat; static int ext4_load_journal(struct super_block *, struct ext4_super_block *, unsigned long journal_devnum); @@ -75,7 +75,6 @@ static void ext4_write_super(struct super_block *sb); static int ext4_freeze(struct super_block *sb); static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); -static int ext4_feature_set_ok(struct super_block *sb, int readonly); static void ext4_destroy_lazyinit_thread(void); static void ext4_unregister_li_request(struct super_block *sb); static void ext4_clear_request_list(void); @@ -595,7 +594,7 @@ __acquires(bitlock) vaf.fmt = fmt; vaf.va = &args; - printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", + printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u", sb->s_id, function, line, grp); if (ino) printk(KERN_CONT "inode %lu: ", ino); @@ -998,10 +997,13 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, OLDALLOC)) seq_puts(seq, ",oldalloc"); #ifdef CONFIG_EXT4_FS_XATTR - if (test_opt(sb, XATTR_USER)) + if (test_opt(sb, XATTR_USER) && + !(def_mount_opts & EXT4_DEFM_XATTR_USER)) seq_puts(seq, ",user_xattr"); - if (!test_opt(sb, XATTR_USER)) + if (!test_opt(sb, XATTR_USER) && + (def_mount_opts & EXT4_DEFM_XATTR_USER)) { seq_puts(seq, ",nouser_xattr"); + } #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) @@ -1039,8 +1041,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) !(def_mount_opts & EXT4_DEFM_NODELALLOC)) seq_puts(seq, ",nodelalloc"); - if (!test_opt(sb, MBLK_IO_SUBMIT)) - seq_puts(seq, ",nomblk_io_submit"); + if (test_opt(sb, MBLK_IO_SUBMIT)) + seq_puts(seq, ",mblk_io_submit"); if (sbi->s_stripe) seq_printf(seq, ",stripe=%lu", sbi->s_stripe); /* @@ -1449,7 +1451,7 @@ static int parse_options(char *options, struct super_block *sb, * Initialize args struct so we know whether arg was * found; some options take optional arguments. */ - args[0].to = args[0].from = NULL; + args[0].to = args[0].from = 0; token = match_token(p, tokens, args); switch (token) { case Opt_bsd_df: @@ -1769,7 +1771,7 @@ static int parse_options(char *options, struct super_block *sb, return 0; if (option < 0 || option > (1 << 30)) return 0; - if (option && !is_power_of_2(option)) { + if (!is_power_of_2(option)) { ext4_msg(sb, KERN_ERR, "EXT4-fs: inode_readahead_blks" " must be a power of 2"); @@ -2118,13 +2120,6 @@ static void ext4_orphan_cleanup(struct super_block *sb, return; } - /* Check if feature set would not allow a r/w mount */ - if (!ext4_feature_set_ok(sb, 0)) { - ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to " - "unknown ROCOMPAT features"); - return; - } - if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) { if (es->s_last_orphan) jbd_debug(1, "Errors on filesystem, " @@ -2417,7 +2412,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a, if (parse_strtoul(buf, 0x40000000, &t)) return -EINVAL; - if (t && !is_power_of_2(t)) + if (!is_power_of_2(t)) return -EINVAL; sbi->s_inode_readahead_blks = t; @@ -3100,14 +3095,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } if (def_mount_opts & EXT4_DEFM_UID16) set_opt(sb, NO_UID32); - /* xattr user namespace & acls are now defaulted on */ #ifdef CONFIG_EXT4_FS_XATTR - set_opt(sb, XATTR_USER); + if (def_mount_opts & EXT4_DEFM_XATTR_USER) + set_opt(sb, XATTR_USER); #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL - set_opt(sb, POSIX_ACL); + if (def_mount_opts & EXT4_DEFM_ACL) + set_opt(sb, POSIX_ACL); #endif - set_opt(sb, MBLK_IO_SUBMIT); if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) set_opt(sb, JOURNAL_DATA); else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) @@ -3521,7 +3516,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) * concurrency isn't really necessary. Limit it to 1. */ EXT4_SB(sb)->dio_unwritten_wq = - alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM | WQ_UNBOUND, 1); + alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM, 1); if (!EXT4_SB(sb)->dio_unwritten_wq) { printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); goto failed_mount_wq; @@ -3536,16 +3531,17 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (IS_ERR(root)) { ext4_msg(sb, KERN_ERR, "get root inode failed"); ret = PTR_ERR(root); - root = NULL; goto failed_mount4; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { + iput(root); ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck"); goto failed_mount4; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { ext4_msg(sb, KERN_ERR, "get root dentry failed"); + iput(root); ret = -ENOMEM; goto failed_mount4; } @@ -3661,8 +3657,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; failed_mount4: - iput(root); - sb->s_root = NULL; ext4_msg(sb, KERN_ERR, "mount failed"); destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); failed_mount_wq: diff --git a/trunk/fs/ext4/xattr.c b/trunk/fs/ext4/xattr.c index b545ca1c459c..fc32176eee39 100644 --- a/trunk/fs/ext4/xattr.c +++ b/trunk/fs/ext4/xattr.c @@ -735,7 +735,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, int offset = (char *)s->here - bs->bh->b_data; unlock_buffer(bs->bh); - ext4_handle_release_buffer(handle, bs->bh); + jbd2_journal_release_buffer(handle, bs->bh); if (ce) { mb_cache_entry_release(ce); ce = NULL; @@ -833,7 +833,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, new_bh = sb_getblk(sb, block); if (!new_bh) { getblk_failed: - ext4_free_blocks(handle, inode, NULL, block, 1, + ext4_free_blocks(handle, inode, 0, block, 1, EXT4_FREE_BLOCKS_METADATA); error = -EIO; goto cleanup; diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index 7237672216c8..abdf38d5971d 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -44,7 +44,6 @@ /* #define NFS_DEBUG_VERBOSE 1 */ static int nfs_opendir(struct inode *, struct file *); -static int nfs_closedir(struct inode *, struct file *); static int nfs_readdir(struct file *, void *, filldir_t); static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); @@ -65,7 +64,7 @@ const struct file_operations nfs_dir_operations = { .read = generic_read_dir, .readdir = nfs_readdir, .open = nfs_opendir, - .release = nfs_closedir, + .release = nfs_release, .fsync = nfs_fsync_dir, }; @@ -134,35 +133,13 @@ const struct inode_operations nfs4_dir_inode_operations = { #endif /* CONFIG_NFS_V4 */ -static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred *cred) -{ - struct nfs_open_dir_context *ctx; - ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); - if (ctx != NULL) { - ctx->duped = 0; - ctx->dir_cookie = 0; - ctx->dup_cookie = 0; - ctx->cred = get_rpccred(cred); - } else - ctx = ERR_PTR(-ENOMEM); - return ctx; -} - -static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) -{ - put_rpccred(ctx->cred); - kfree(ctx); -} - /* * Open file */ static int nfs_opendir(struct inode *inode, struct file *filp) { - int res = 0; - struct nfs_open_dir_context *ctx; - struct rpc_cred *cred; + int res; dfprintk(FILE, "NFS: open dir(%s/%s)\n", filp->f_path.dentry->d_parent->d_name.name, @@ -170,15 +147,8 @@ nfs_opendir(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSOPEN); - cred = rpc_lookup_cred(); - if (IS_ERR(cred)) - return PTR_ERR(cred); - ctx = alloc_nfs_open_dir_context(cred); - if (IS_ERR(ctx)) { - res = PTR_ERR(ctx); - goto out; - } - filp->private_data = ctx; + /* Call generic open code in order to cache credentials */ + res = nfs_open(inode, filp); if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { /* This is a mountpoint, so d_revalidate will never * have been called, so we need to refresh the @@ -186,18 +156,9 @@ nfs_opendir(struct inode *inode, struct file *filp) */ __nfs_revalidate_inode(NFS_SERVER(inode), inode); } -out: - put_rpccred(cred); return res; } -static int -nfs_closedir(struct inode *inode, struct file *filp) -{ - put_nfs_open_dir_context(filp->private_data); - return 0; -} - struct nfs_cache_array_entry { u64 cookie; u64 ino; @@ -323,20 +284,19 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri { loff_t diff = desc->file->f_pos - desc->current_index; unsigned int index; - struct nfs_open_dir_context *ctx = desc->file->private_data; if (diff < 0) goto out_eof; if (diff >= array->size) { if (array->eof_index >= 0) goto out_eof; + desc->current_index += array->size; return -EAGAIN; } index = (unsigned int)diff; *desc->dir_cookie = array->array[index].cookie; desc->cache_entry_index = index; - ctx->duped = 0; return 0; out_eof: desc->eof = 1; @@ -347,18 +307,10 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) { int i; - loff_t new_pos; int status = -EAGAIN; - struct nfs_open_dir_context *ctx = desc->file->private_data; for (i = 0; i < array->size; i++) { if (array->array[i].cookie == *desc->dir_cookie) { - new_pos = desc->current_index + i; - if (new_pos < desc->file->f_pos) { - ctx->dup_cookie = *desc->dir_cookie; - ctx->duped = 1; - } - desc->file->f_pos = new_pos; desc->cache_entry_index = i; return 0; } @@ -390,7 +342,6 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) if (status == -EAGAIN) { desc->last_cookie = array->last_cookie; - desc->current_index += array->size; desc->page_index++; } nfs_readdir_release_array(desc->page); @@ -403,8 +354,7 @@ static int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct file *file, struct inode *inode) { - struct nfs_open_dir_context *ctx = file->private_data; - struct rpc_cred *cred = ctx->cred; + struct rpc_cred *cred = nfs_file_cred(file); unsigned long timestamp, gencount; int error; @@ -743,20 +693,6 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, int i = 0; int res = 0; struct nfs_cache_array *array = NULL; - struct nfs_open_dir_context *ctx = file->private_data; - - if (ctx->duped != 0 && ctx->dup_cookie == *desc->dir_cookie) { - if (printk_ratelimit()) { - pr_notice("NFS: directory %s/%s contains a readdir loop. " - "Please contact your server vendor. " - "Offending cookie: %llu\n", - file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, - *desc->dir_cookie); - } - res = -ELOOP; - goto out; - } array = nfs_readdir_get_array(desc->page); if (IS_ERR(array)) { @@ -849,7 +785,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *inode = dentry->d_inode; nfs_readdir_descriptor_t my_desc, *desc = &my_desc; - struct nfs_open_dir_context *dir_ctx = filp->private_data; int res; dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", @@ -866,7 +801,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) memset(desc, 0, sizeof(*desc)); desc->file = filp; - desc->dir_cookie = &dir_ctx->dir_cookie; + desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; desc->decode = NFS_PROTO(inode)->decode_dirent; desc->plus = NFS_USE_READDIRPLUS(inode); @@ -918,7 +853,6 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; - struct nfs_open_dir_context *dir_ctx = filp->private_data; dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", dentry->d_parent->d_name.name, @@ -938,8 +872,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) } if (offset != filp->f_pos) { filp->f_pos = offset; - dir_ctx->dir_cookie = 0; - dir_ctx->duped = 0; + nfs_file_open_context(filp)->dir_cookie = 0; } out: mutex_unlock(&inode->i_mutex); @@ -1135,7 +1068,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) if (fhandle == NULL || fattr == NULL) goto out_error; - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error) goto out_bad; if (nfs_compare_fh(NFS_FH(inode), fhandle)) @@ -1291,7 +1224,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru parent = dentry->d_parent; /* Protect against concurrent sillydeletes */ nfs_block_sillyrename(parent); - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error == -ENOENT) goto no_entry; if (error < 0) { @@ -1629,7 +1562,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, if (dentry->d_inode) goto out; if (fhandle->size == 0) { - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error) goto out_error; } diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 3ac5bd695e5e..d85a534b15cd 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -326,9 +326,6 @@ nfs_file_fsync(struct file *file, int datasync) ret = xchg(&ctx->error, 0); if (!ret && status < 0) ret = status; - if (!ret && !datasync) - /* application has asked for meta-data sync */ - ret = pnfs_layoutcommit_inode(inode, true); return ret; } diff --git a/trunk/fs/nfs/getroot.c b/trunk/fs/nfs/getroot.c index dcb61548887f..1084792bc0fe 100644 --- a/trunk/fs/nfs/getroot.c +++ b/trunk/fs/nfs/getroot.c @@ -222,10 +222,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh, goto out; } - if (fattr->valid & NFS_ATTR_FATTR_FSID && - !nfs_fsid_equal(&server->fsid, &fattr->fsid)) - memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); - inode = nfs_fhget(sb, mntfh, fattr); if (IS_ERR(inode)) { dprintk("nfs_get_root: get root inode failed\n"); diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index 57bb31ad7a5e..01768e5e2c9b 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -254,9 +254,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) struct inode *inode = ERR_PTR(-ENOENT); unsigned long hash; - nfs_attr_check_mountpoint(sb, fattr); - - if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) + if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) goto out_no_inode; if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) goto out_no_inode; @@ -300,8 +298,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); /* Deal with crossing mountpoints */ - if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT || - fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { + if ((fattr->valid & NFS_ATTR_FATTR_FSID) + && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) inode->i_op = &nfs_referral_inode_operations; else @@ -641,6 +639,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cr ctx->mode = f_mode; ctx->flags = 0; ctx->error = 0; + ctx->dir_cookie = 0; nfs_init_lock_context(&ctx->lock_context); ctx->lock_context.open_context = ctx; INIT_LIST_HEAD(&ctx->list); @@ -1472,7 +1471,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi) nfsi->delegation_state = 0; init_rwsem(&nfsi->rwsem); nfsi->layout = NULL; - atomic_set(&nfsi->commits_outstanding, 0); #endif } diff --git a/trunk/fs/nfs/internal.h b/trunk/fs/nfs/internal.h index ce118ce885dd..72e0bddf7a2f 100644 --- a/trunk/fs/nfs/internal.h +++ b/trunk/fs/nfs/internal.h @@ -39,12 +39,6 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) return 0; } -static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) -{ - if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) - fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; -} - struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; @@ -220,7 +214,6 @@ extern const u32 nfs41_maxwrite_overhead; /* nfs4proc.c */ #ifdef CONFIG_NFS_V4 extern struct rpc_procinfo nfs4_procedures[]; -void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); #endif extern int nfs4_init_ds_session(struct nfs_client *clp); @@ -283,25 +276,11 @@ extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, extern void nfs_read_prepare(struct rpc_task *task, void *calldata); /* write.c */ -extern void nfs_commit_free(struct nfs_write_data *p); extern int nfs_initiate_write(struct nfs_write_data *data, struct rpc_clnt *clnt, const struct rpc_call_ops *call_ops, int how); extern void nfs_write_prepare(struct rpc_task *task, void *calldata); -extern int nfs_initiate_commit(struct nfs_write_data *data, - struct rpc_clnt *clnt, - const struct rpc_call_ops *call_ops, - int how); -extern void nfs_init_commit(struct nfs_write_data *data, - struct list_head *head, - struct pnfs_layout_segment *lseg); -void nfs_retry_commit(struct list_head *page_list, - struct pnfs_layout_segment *lseg); -void nfs_commit_clear_lock(struct nfs_inode *nfsi); -void nfs_commitdata_release(void *data); -void nfs_commit_release_pages(struct nfs_write_data *data); - #ifdef CONFIG_MIGRATION extern int nfs_migrate_page(struct address_space *, struct page *, struct page *); @@ -317,14 +296,12 @@ extern int nfs4_init_client(struct nfs_client *clp, rpc_authflavor_t authflavour, int noresvport); extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data); -extern int _nfs4_call_sync(struct rpc_clnt *clnt, - struct nfs_server *server, +extern int _nfs4_call_sync(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply); -extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, - struct nfs_server *server, +extern int _nfs4_call_sync_session(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, diff --git a/trunk/fs/nfs/namespace.c b/trunk/fs/nfs/namespace.c index ad92bf731ff5..bf1c68009ffd 100644 --- a/trunk/fs/nfs/namespace.c +++ b/trunk/fs/nfs/namespace.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "internal.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -28,8 +27,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; static struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, - struct nfs_fattr *fattr, - rpc_authflavor_t authflavor); + struct nfs_fattr *fattr); /* * nfs_path - reconstruct the path given an arbitrary dentry @@ -118,100 +116,6 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) return ERR_PTR(-ENAMETOOLONG); } -#ifdef CONFIG_NFS_V4 -static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode) -{ - struct gss_api_mech *mech; - struct xdr_netobj oid; - int i; - rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; - - for (i = 0; i < flavors->num_flavors; i++) { - struct nfs4_secinfo_flavor *flavor; - flavor = &flavors->flavors[i]; - - if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) { - pseudoflavor = flavor->flavor; - break; - } else if (flavor->flavor == RPC_AUTH_GSS) { - oid.len = flavor->gss.sec_oid4.len; - oid.data = flavor->gss.sec_oid4.data; - mech = gss_mech_get_by_OID(&oid); - if (!mech) - continue; - pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service); - gss_mech_put(mech); - break; - } - } - - return pseudoflavor; -} - -static rpc_authflavor_t nfs_negotiate_security(const struct dentry *parent, const struct dentry *dentry) -{ - int status = 0; - struct page *page; - struct nfs4_secinfo_flavors *flavors; - int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); - rpc_authflavor_t flavor = RPC_AUTH_UNIX; - - secinfo = NFS_PROTO(parent->d_inode)->secinfo; - if (secinfo != NULL) { - page = alloc_page(GFP_KERNEL); - if (!page) { - status = -ENOMEM; - goto out; - } - flavors = page_address(page); - status = secinfo(parent->d_inode, &dentry->d_name, flavors); - flavor = nfs_find_best_sec(flavors, dentry->d_inode); - put_page(page); - } - - return flavor; - -out: - status = -ENOMEM; - return status; -} - -static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, - struct dentry *dentry, struct path *path, - struct nfs_fh *fh, struct nfs_fattr *fattr) -{ - rpc_authflavor_t flavor; - struct rpc_clnt *clone; - struct rpc_auth *auth; - int err; - - flavor = nfs_negotiate_security(parent, path->dentry); - if (flavor < 0) - goto out; - clone = rpc_clone_client(server->client); - auth = rpcauth_create(flavor, clone); - if (!auth) { - flavor = -EIO; - goto out; - } - err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, - &path->dentry->d_name, - fh, fattr); - if (err < 0) - flavor = err; -out: - return flavor; -} -#else /* CONFIG_NFS_V4 */ -static inline rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, - struct dentry *parent, struct dentry *dentry, - struct path *path, struct nfs_fh *fh, - struct nfs_fattr *fattr) -{ - return -EPERM; -} -#endif /* CONFIG_NFS_V4 */ - /* * nfs_d_automount - Handle crossing a mountpoint on the server * @path - The mountpoint @@ -232,7 +136,6 @@ struct vfsmount *nfs_d_automount(struct path *path) struct nfs_fh *fh = NULL; struct nfs_fattr *fattr = NULL; int err; - rpc_authflavor_t flavor = 1; dprintk("--> nfs_d_automount()\n"); @@ -250,16 +153,9 @@ struct vfsmount *nfs_d_automount(struct path *path) /* Look it up again to get its attributes */ parent = dget_parent(path->dentry); - err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, + err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &path->dentry->d_name, fh, fattr); - if (err == -EPERM) { - flavor = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr); - if (flavor < 0) - err = flavor; - else - err = 0; - } dput(parent); if (err != 0) { mnt = ERR_PTR(err); @@ -269,7 +165,7 @@ struct vfsmount *nfs_d_automount(struct path *path) if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) mnt = nfs_do_refmount(path->dentry); else - mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); + mnt = nfs_do_submount(path->dentry, fh, fattr); if (IS_ERR(mnt)) goto out; @@ -336,20 +232,17 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, * @dentry - parent directory * @fh - filehandle for new root dentry * @fattr - attributes for new root inode - * @authflavor - security flavor to use when performing the mount * */ static struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, - struct nfs_fattr *fattr, - rpc_authflavor_t authflavor) + struct nfs_fattr *fattr) { struct nfs_clone_mount mountdata = { .sb = dentry->d_sb, .dentry = dentry, .fh = fh, .fattr = fattr, - .authflavor = authflavor, }; struct vfsmount *mnt = ERR_PTR(-ENOMEM); char *page = (char *) __get_free_page(GFP_USER); diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index 38053d823eb0..d0c80d8b3f96 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -141,7 +141,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs3_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, +nfs3_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs3_diropargs arg = { diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index e1c261ddd65d..c64be1cff080 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -57,8 +57,7 @@ enum nfs4_session_state { struct nfs4_minor_version_ops { u32 minor_version; - int (*call_sync)(struct rpc_clnt *clnt, - struct nfs_server *server, + int (*call_sync)(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -263,8 +262,6 @@ extern int nfs4_proc_destroy_session(struct nfs4_session *); extern int nfs4_init_session(struct nfs_server *server); extern int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo); -extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, - bool sync); static inline bool is_ds_only_client(struct nfs_client *clp) diff --git a/trunk/fs/nfs/nfs4filelayout.c b/trunk/fs/nfs/nfs4filelayout.c index 6f8192f4cfc7..428558464817 100644 --- a/trunk/fs/nfs/nfs4filelayout.c +++ b/trunk/fs/nfs/nfs4filelayout.c @@ -153,23 +153,6 @@ static int filelayout_read_done_cb(struct rpc_task *task, return 0; } -/* - * We reference the rpc_cred of the first WRITE that triggers the need for - * a LAYOUTCOMMIT, and use it to send the layoutcommit compound. - * rfc5661 is not clear about which credential should be used. - */ -static void -filelayout_set_layoutcommit(struct nfs_write_data *wdata) -{ - if (FILELAYOUT_LSEG(wdata->lseg)->commit_through_mds || - wdata->res.verf->committed == NFS_FILE_SYNC) - return; - - pnfs_set_layoutcommit(wdata); - dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, wdata->inode->i_ino, - (unsigned long) wdata->lseg->pls_end_pos); -} - /* * Call ops for the async read/write cases * In the case of dense layouts, the offset needs to be reset to its @@ -227,38 +210,6 @@ static int filelayout_write_done_cb(struct rpc_task *task, return -EAGAIN; } - filelayout_set_layoutcommit(data); - return 0; -} - -/* Fake up some data that will cause nfs_commit_release to retry the writes. */ -static void prepare_to_resend_writes(struct nfs_write_data *data) -{ - struct nfs_page *first = nfs_list_entry(data->pages.next); - - data->task.tk_status = 0; - memcpy(data->verf.verifier, first->wb_verf.verifier, - sizeof(first->wb_verf.verifier)); - data->verf.verifier[0]++; /* ensure verifier mismatch */ -} - -static int filelayout_commit_done_cb(struct rpc_task *task, - struct nfs_write_data *data) -{ - int reset = 0; - - if (filelayout_async_handle_error(task, data->args.context->state, - data->ds_clp, &reset) == -EAGAIN) { - dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", - __func__, data->ds_clp, data->ds_clp->cl_session); - if (reset) { - prepare_to_resend_writes(data); - filelayout_set_lo_fail(data->lseg); - } else - nfs_restart_rpc(task, data->ds_clp); - return -EAGAIN; - } - return 0; } @@ -289,16 +240,6 @@ static void filelayout_write_release(void *data) wdata->mds_ops->rpc_release(data); } -static void filelayout_commit_release(void *data) -{ - struct nfs_write_data *wdata = (struct nfs_write_data *)data; - - nfs_commit_release_pages(wdata); - if (atomic_dec_and_test(&NFS_I(wdata->inode)->commits_outstanding)) - nfs_commit_clear_lock(NFS_I(wdata->inode)); - nfs_commitdata_release(wdata); -} - struct rpc_call_ops filelayout_read_call_ops = { .rpc_call_prepare = filelayout_read_prepare, .rpc_call_done = filelayout_read_call_done, @@ -311,12 +252,6 @@ struct rpc_call_ops filelayout_write_call_ops = { .rpc_release = filelayout_write_release, }; -struct rpc_call_ops filelayout_commit_call_ops = { - .rpc_call_prepare = filelayout_write_prepare, - .rpc_call_done = filelayout_write_call_done, - .rpc_release = filelayout_commit_release, -}; - static enum pnfs_try_status filelayout_read_pagelist(struct nfs_read_data *data) { @@ -385,6 +320,10 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) data->inode->i_ino, sync, (size_t) data->args.count, offset, ntohl(ds->ds_ip_addr), ntohs(ds->ds_port)); + /* We can't handle commit to ds yet */ + if (!FILELAYOUT_LSEG(lseg)->commit_through_mds) + data->args.stable = NFS_FILE_SYNC; + data->write_done_cb = filelayout_write_done_cb; data->ds_clp = ds->ds_clp; fh = nfs4_fl_select_ds_fh(lseg, j); @@ -502,33 +441,12 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, struct nfs4_layoutget_res *lgr, struct nfs4_deviceid *id) { - struct xdr_stream stream; - struct xdr_buf buf = { - .pages = lgr->layoutp->pages, - .page_len = lgr->layoutp->len, - .buflen = lgr->layoutp->len, - .len = lgr->layoutp->len, - }; - struct page *scratch; - __be32 *p; + uint32_t *p = (uint32_t *)lgr->layout.buf; uint32_t nfl_util; int i; dprintk("%s: set_layout_map Begin\n", __func__); - scratch = alloc_page(GFP_KERNEL); - if (!scratch) - return -ENOMEM; - - xdr_init_decode(&stream, &buf, NULL); - xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); - - /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8), - * num_fh (4) */ - p = xdr_inline_decode(&stream, NFS4_DEVICEID4_SIZE + 20); - if (unlikely(!p)) - goto out_err; - memcpy(id, p, sizeof(*id)); p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); print_deviceid(id); @@ -550,57 +468,32 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, __func__, nfl_util, fl->num_fh, fl->first_stripe_index, fl->pattern_offset); - if (!fl->num_fh) - goto out_err; - fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), GFP_KERNEL); if (!fl->fh_array) - goto out_err; + return -ENOMEM; for (i = 0; i < fl->num_fh; i++) { /* Do we want to use a mempool here? */ fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); - if (!fl->fh_array[i]) - goto out_err_free; - - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free; + if (!fl->fh_array[i]) { + filelayout_free_fh_array(fl); + return -ENOMEM; + } fl->fh_array[i]->size = be32_to_cpup(p++); if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) { printk(KERN_ERR "Too big fh %d received %d\n", i, fl->fh_array[i]->size); - goto out_err_free; + filelayout_free_fh_array(fl); + return -EIO; } - - p = xdr_inline_decode(&stream, fl->fh_array[i]->size); - if (unlikely(!p)) - goto out_err_free; memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size); + p += XDR_QUADLEN(fl->fh_array[i]->size); dprintk("DEBUG: %s: fh len %d\n", __func__, fl->fh_array[i]->size); } - __free_page(scratch); return 0; - -out_err_free: - filelayout_free_fh_array(fl); -out_err: - __free_page(scratch); - return -EIO; -} - -static void -filelayout_free_lseg(struct pnfs_layout_segment *lseg) -{ - struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); - - dprintk("--> %s\n", __func__); - nfs4_fl_put_deviceid(fl->dsaddr); - kfree(fl->commit_buckets); - _filelayout_free_lseg(fl); } static struct pnfs_layout_segment * @@ -621,30 +514,19 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, _filelayout_free_lseg(fl); return NULL; } - - /* This assumes there is only one IOMODE_RW lseg. What - * we really want to do is have a layout_hdr level - * dictionary of keys, each - * associated with a struct list_head, populated by calls - * to filelayout_write_pagelist(). - * */ - if ((!fl->commit_through_mds) && (lgr->range.iomode == IOMODE_RW)) { - int i; - int size = (fl->stripe_type == STRIPE_SPARSE) ? - fl->dsaddr->ds_num : fl->dsaddr->stripe_count; - - fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); - if (!fl->commit_buckets) { - filelayout_free_lseg(&fl->generic_hdr); - return NULL; - } - fl->number_of_buckets = size; - for (i = 0; i < size; i++) - INIT_LIST_HEAD(&fl->commit_buckets[i]); - } return &fl->generic_hdr; } +static void +filelayout_free_lseg(struct pnfs_layout_segment *lseg) +{ + struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); + + dprintk("--> %s\n", __func__); + nfs4_fl_put_deviceid(fl->dsaddr); + _filelayout_free_lseg(fl); +} + /* * filelayout_pg_test(). Called by nfs_can_coalesce_requests() * @@ -670,191 +552,6 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, return (p_stripe == r_stripe); } -static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) -{ - return !FILELAYOUT_LSEG(lseg)->commit_through_mds; -} - -static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) -{ - if (fl->stripe_type == STRIPE_SPARSE) - return nfs4_fl_calc_ds_index(&fl->generic_hdr, j); - else - return j; -} - -struct list_head *filelayout_choose_commit_list(struct nfs_page *req) -{ - struct pnfs_layout_segment *lseg = req->wb_commit_lseg; - struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); - u32 i, j; - struct list_head *list; - - /* Note that we are calling nfs4_fl_calc_j_index on each page - * that ends up being committed to a data server. An attractive - * alternative is to add a field to nfs_write_data and nfs_page - * to store the value calculated in filelayout_write_pagelist - * and just use that here. - */ - j = nfs4_fl_calc_j_index(lseg, - (loff_t)req->wb_index << PAGE_CACHE_SHIFT); - i = select_bucket_index(fl, j); - list = &fl->commit_buckets[i]; - if (list_empty(list)) { - /* Non-empty buckets hold a reference on the lseg */ - get_lseg(lseg); - } - return list; -} - -static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) -{ - struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); - - if (flseg->stripe_type == STRIPE_SPARSE) - return i; - else - return nfs4_fl_calc_ds_index(lseg, i); -} - -static struct nfs_fh * -select_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i) -{ - struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); - - if (flseg->stripe_type == STRIPE_SPARSE) { - if (flseg->num_fh == 1) - i = 0; - else if (flseg->num_fh == 0) - /* Use the MDS OPEN fh set in nfs_read_rpcsetup */ - return NULL; - } - return flseg->fh_array[i]; -} - -static int filelayout_initiate_commit(struct nfs_write_data *data, int how) -{ - struct pnfs_layout_segment *lseg = data->lseg; - struct nfs4_pnfs_ds *ds; - u32 idx; - struct nfs_fh *fh; - - idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); - ds = nfs4_fl_prepare_ds(lseg, idx); - if (!ds) { - printk(KERN_ERR "%s: prepare_ds failed, use MDS\n", __func__); - set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); - set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); - prepare_to_resend_writes(data); - data->mds_ops->rpc_release(data); - return -EAGAIN; - } - dprintk("%s ino %lu, how %d\n", __func__, data->inode->i_ino, how); - data->write_done_cb = filelayout_commit_done_cb; - data->ds_clp = ds->ds_clp; - fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); - if (fh) - data->args.fh = fh; - return nfs_initiate_commit(data, ds->ds_clp->cl_rpcclient, - &filelayout_commit_call_ops, how); -} - -/* - * This is only useful while we are using whole file layouts. - */ -static struct pnfs_layout_segment *find_only_write_lseg(struct inode *inode) -{ - struct pnfs_layout_segment *lseg, *rv = NULL; - - spin_lock(&inode->i_lock); - list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) - if (lseg->pls_range.iomode == IOMODE_RW) - rv = get_lseg(lseg); - spin_unlock(&inode->i_lock); - return rv; -} - -static int alloc_ds_commits(struct inode *inode, struct list_head *list) -{ - struct pnfs_layout_segment *lseg; - struct nfs4_filelayout_segment *fl; - struct nfs_write_data *data; - int i, j; - - /* Won't need this when non-whole file layout segments are supported - * instead we will use a pnfs_layout_hdr structure */ - lseg = find_only_write_lseg(inode); - if (!lseg) - return 0; - fl = FILELAYOUT_LSEG(lseg); - for (i = 0; i < fl->number_of_buckets; i++) { - if (list_empty(&fl->commit_buckets[i])) - continue; - data = nfs_commitdata_alloc(); - if (!data) - goto out_bad; - data->ds_commit_index = i; - data->lseg = lseg; - list_add(&data->pages, list); - } - put_lseg(lseg); - return 0; - -out_bad: - for (j = i; j < fl->number_of_buckets; j++) { - if (list_empty(&fl->commit_buckets[i])) - continue; - nfs_retry_commit(&fl->commit_buckets[i], lseg); - put_lseg(lseg); /* associated with emptying bucket */ - } - put_lseg(lseg); - /* Caller will clean up entries put on list */ - return -ENOMEM; -} - -/* This follows nfs_commit_list pretty closely */ -static int -filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, - int how) -{ - struct nfs_write_data *data, *tmp; - LIST_HEAD(list); - - if (!list_empty(mds_pages)) { - data = nfs_commitdata_alloc(); - if (!data) - goto out_bad; - data->lseg = NULL; - list_add(&data->pages, &list); - } - - if (alloc_ds_commits(inode, &list)) - goto out_bad; - - list_for_each_entry_safe(data, tmp, &list, pages) { - list_del_init(&data->pages); - atomic_inc(&NFS_I(inode)->commits_outstanding); - if (!data->lseg) { - nfs_init_commit(data, mds_pages, NULL); - nfs_initiate_commit(data, NFS_CLIENT(inode), - data->mds_ops, how); - } else { - nfs_init_commit(data, &FILELAYOUT_LSEG(data->lseg)->commit_buckets[data->ds_commit_index], data->lseg); - filelayout_initiate_commit(data, how); - } - } - return 0; - out_bad: - list_for_each_entry_safe(data, tmp, &list, pages) { - nfs_retry_commit(&data->pages, data->lseg); - list_del_init(&data->pages); - nfs_commit_free(data); - } - nfs_retry_commit(mds_pages, NULL); - nfs_commit_clear_lock(NFS_I(inode)); - return -ENOMEM; -} - static struct pnfs_layoutdriver_type filelayout_type = { .id = LAYOUT_NFSV4_1_FILES, .name = "LAYOUT_NFSV4_1_FILES", @@ -862,9 +559,6 @@ static struct pnfs_layoutdriver_type filelayout_type = { .alloc_lseg = filelayout_alloc_lseg, .free_lseg = filelayout_free_lseg, .pg_test = filelayout_pg_test, - .mark_pnfs_commit = filelayout_mark_pnfs_commit, - .choose_commit_list = filelayout_choose_commit_list, - .commit_pagelist = filelayout_commit_pagelist, .read_pagelist = filelayout_read_pagelist, .write_pagelist = filelayout_write_pagelist, }; diff --git a/trunk/fs/nfs/nfs4filelayout.h b/trunk/fs/nfs/nfs4filelayout.h index 085a354e0f08..ee0c907742b5 100644 --- a/trunk/fs/nfs/nfs4filelayout.h +++ b/trunk/fs/nfs/nfs4filelayout.h @@ -79,8 +79,6 @@ struct nfs4_filelayout_segment { struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */ unsigned int num_fh; struct nfs_fh **fh_array; - struct list_head *commit_buckets; /* Sort commits to ds */ - int number_of_buckets; }; static inline struct nfs4_filelayout_segment * diff --git a/trunk/fs/nfs/nfs4filelayoutdev.c b/trunk/fs/nfs/nfs4filelayoutdev.c index de5350f2b249..68143c162e3b 100644 --- a/trunk/fs/nfs/nfs4filelayoutdev.c +++ b/trunk/fs/nfs/nfs4filelayoutdev.c @@ -261,7 +261,7 @@ nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) * Currently only support ipv4, and one multi-path address. */ static struct nfs4_pnfs_ds * -decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) +decode_and_add_ds(__be32 **pp, struct inode *inode) { struct nfs4_pnfs_ds *ds = NULL; char *buf; @@ -269,34 +269,25 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) u32 ip_addr, port; int nlen, rlen, i; int tmp[2]; - __be32 *p; + __be32 *r_netid, *r_addr, *p = *pp; /* r_netid */ - p = xdr_inline_decode(streamp, 4); - if (unlikely(!p)) - goto out_err; nlen = be32_to_cpup(p++); + r_netid = p; + p += XDR_QUADLEN(nlen); - p = xdr_inline_decode(streamp, nlen); - if (unlikely(!p)) - goto out_err; + /* r_addr */ + rlen = be32_to_cpup(p++); + r_addr = p; + p += XDR_QUADLEN(rlen); + *pp = p; /* Check that netid is "tcp" */ - if (nlen != 3 || memcmp((char *)p, "tcp", 3)) { + if (nlen != 3 || memcmp((char *)r_netid, "tcp", 3)) { dprintk("%s: ERROR: non ipv4 TCP r_netid\n", __func__); goto out_err; } - /* r_addr */ - p = xdr_inline_decode(streamp, 4); - if (unlikely(!p)) - goto out_err; - rlen = be32_to_cpup(p); - - p = xdr_inline_decode(streamp, rlen); - if (unlikely(!p)) - goto out_err; - /* ipv6 length plus port is legal */ if (rlen > INET6_ADDRSTRLEN + 8) { dprintk("%s: Invalid address, length %d\n", __func__, @@ -309,7 +300,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) goto out_err; } buf[rlen] = '\0'; - memcpy(buf, p, rlen); + memcpy(buf, r_addr, rlen); /* replace the port dots with dashes for the in4_pton() delimiter*/ for (i = 0; i < 2; i++) { @@ -345,154 +336,90 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) static struct nfs4_file_layout_dsaddr* decode_device(struct inode *ino, struct pnfs_device *pdev) { - int i; + int i, dummy; u32 cnt, num; u8 *indexp; - __be32 *p; - u8 *stripe_indices; - u8 max_stripe_index; - struct nfs4_file_layout_dsaddr *dsaddr = NULL; - struct xdr_stream stream; - struct xdr_buf buf = { - .pages = pdev->pages, - .page_len = pdev->pglen, - .buflen = pdev->pglen, - .len = pdev->pglen, - }; - struct page *scratch; - - /* set up xdr stream */ - scratch = alloc_page(GFP_KERNEL); - if (!scratch) - goto out_err; - - xdr_init_decode(&stream, &buf, NULL); - xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); + __be32 *p = (__be32 *)pdev->area, *indicesp; + struct nfs4_file_layout_dsaddr *dsaddr; /* Get the stripe count (number of stripe index) */ - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free_scratch; - - cnt = be32_to_cpup(p); + cnt = be32_to_cpup(p++); dprintk("%s stripe count %d\n", __func__, cnt); if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) { printk(KERN_WARNING "%s: stripe count %d greater than " "supported maximum %d\n", __func__, cnt, NFS4_PNFS_MAX_STRIPE_CNT); - goto out_err_free_scratch; - } - - /* read stripe indices */ - stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL); - if (!stripe_indices) - goto out_err_free_scratch; - - p = xdr_inline_decode(&stream, cnt << 2); - if (unlikely(!p)) - goto out_err_free_stripe_indices; - - indexp = &stripe_indices[0]; - max_stripe_index = 0; - for (i = 0; i < cnt; i++) { - *indexp = be32_to_cpup(p++); - max_stripe_index = max(max_stripe_index, *indexp); - indexp++; + goto out_err; } /* Check the multipath list count */ - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free_stripe_indices; - - num = be32_to_cpup(p); + indicesp = p; + p += XDR_QUADLEN(cnt << 2); + num = be32_to_cpup(p++); dprintk("%s ds_num %u\n", __func__, num); if (num > NFS4_PNFS_MAX_MULTI_CNT) { printk(KERN_WARNING "%s: multipath count %d greater than " "supported maximum %d\n", __func__, num, NFS4_PNFS_MAX_MULTI_CNT); - goto out_err_free_stripe_indices; - } - - /* validate stripe indices are all < num */ - if (max_stripe_index >= num) { - printk(KERN_WARNING "%s: stripe index %u >= num ds %u\n", - __func__, max_stripe_index, num); - goto out_err_free_stripe_indices; + goto out_err; } - dsaddr = kzalloc(sizeof(*dsaddr) + (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), GFP_KERNEL); if (!dsaddr) - goto out_err_free_stripe_indices; + goto out_err; + + dsaddr->stripe_indices = kzalloc(sizeof(u8) * cnt, GFP_KERNEL); + if (!dsaddr->stripe_indices) + goto out_err_free; dsaddr->stripe_count = cnt; - dsaddr->stripe_indices = stripe_indices; - stripe_indices = NULL; dsaddr->ds_num = num; memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id)); + /* Go back an read stripe indices */ + p = indicesp; + indexp = &dsaddr->stripe_indices[0]; + for (i = 0; i < dsaddr->stripe_count; i++) { + *indexp = be32_to_cpup(p++); + if (*indexp >= num) + goto out_err_free; + indexp++; + } + /* Skip already read multipath list count */ + p++; + for (i = 0; i < dsaddr->ds_num; i++) { int j; - u32 mp_count; - - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free_deviceid; - mp_count = be32_to_cpup(p); /* multipath count */ - if (mp_count > 1) { + dummy = be32_to_cpup(p++); /* multipath count */ + if (dummy > 1) { printk(KERN_WARNING "%s: Multipath count %d not supported, " "skipping all greater than 1\n", __func__, - mp_count); + dummy); } - for (j = 0; j < mp_count; j++) { + for (j = 0; j < dummy; j++) { if (j == 0) { - dsaddr->ds_list[i] = decode_and_add_ds(&stream, - ino); + dsaddr->ds_list[i] = decode_and_add_ds(&p, ino); if (dsaddr->ds_list[i] == NULL) - goto out_err_free_deviceid; + goto out_err_free; } else { u32 len; /* skip extra multipath */ - - /* read len, skip */ - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free_deviceid; - len = be32_to_cpup(p); - - p = xdr_inline_decode(&stream, len); - if (unlikely(!p)) - goto out_err_free_deviceid; - - /* read len, skip */ - p = xdr_inline_decode(&stream, 4); - if (unlikely(!p)) - goto out_err_free_deviceid; - len = be32_to_cpup(p); - - p = xdr_inline_decode(&stream, len); - if (unlikely(!p)) - goto out_err_free_deviceid; + len = be32_to_cpup(p++); + p += XDR_QUADLEN(len); + len = be32_to_cpup(p++); + p += XDR_QUADLEN(len); + continue; } } } - - __free_page(scratch); return dsaddr; -out_err_free_deviceid: +out_err_free: nfs4_fl_free_deviceid(dsaddr); - /* stripe_indicies was part of dsaddr */ - goto out_err_free_scratch; -out_err_free_stripe_indices: - kfree(stripe_indices); -out_err_free_scratch: - __free_page(scratch); out_err: dprintk("%s ERROR: returning NULL\n", __func__); return NULL; @@ -571,6 +498,11 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) goto out_free; } + /* set pdev->area */ + pdev->area = vmap(pages, max_pages, VM_MAP, PAGE_KERNEL); + if (!pdev->area) + goto out_free; + memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id)); pdev->layout_type = LAYOUT_NFSV4_1_FILES; pdev->pages = pages; @@ -589,6 +521,8 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) */ dsaddr = decode_and_add_device(inode, pdev); out_free: + if (pdev->area != NULL) + vunmap(pdev->area); for (i = 0; i < max_pages; i++) __free_page(pages[i]); kfree(pages); diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index dfd1e6d7e6c3..1d84e7088af9 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -72,9 +71,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data); static int _nfs4_recover_proc_open(struct nfs4_opendata *data); static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); -static int _nfs4_proc_lookup(struct rpc_clnt *client, struct inode *dir, - const struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr); +static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, struct iattr *sattr, @@ -88,8 +85,6 @@ static int nfs4_map_errors(int err) switch (err) { case -NFS4ERR_RESOURCE: return -EREMOTEIO; - case -NFS4ERR_WRONGSEC: - return -EPERM; case -NFS4ERR_BADOWNER: case -NFS4ERR_BADNAME: return -EINVAL; @@ -662,8 +657,7 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { .rpc_call_done = nfs41_call_sync_done, }; -static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, - struct nfs_server *server, +static int nfs4_call_sync_sequence(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -679,7 +673,7 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, .cache_reply = cache_reply, }; struct rpc_task_setup task_setup = { - .rpc_client = clnt, + .rpc_client = server->client, .rpc_message = msg, .callback_ops = &nfs41_call_sync_ops, .callback_data = &data @@ -698,14 +692,13 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, return ret; } -int _nfs4_call_sync_session(struct rpc_clnt *clnt, - struct nfs_server *server, +int _nfs4_call_sync_session(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - return nfs4_call_sync_sequence(clnt, server, msg, args, res, cache_reply, 0); + return nfs4_call_sync_sequence(server, msg, args, res, cache_reply, 0); } #else @@ -716,28 +709,19 @@ static int nfs4_sequence_done(struct rpc_task *task, } #endif /* CONFIG_NFS_V4_1 */ -int _nfs4_call_sync(struct rpc_clnt *clnt, - struct nfs_server *server, +int _nfs4_call_sync(struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { args->sa_session = res->sr_session = NULL; - return rpc_call_sync(clnt, msg, 0); + return rpc_call_sync(server->client, msg, 0); } -static inline -int nfs4_call_sync(struct rpc_clnt *clnt, - struct nfs_server *server, - struct rpc_message *msg, - struct nfs4_sequence_args *args, - struct nfs4_sequence_res *res, - int cache_reply) -{ - return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, - args, res, cache_reply); -} +#define nfs4_call_sync(server, msg, args, res, cache_reply) \ + (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ + &(res)->seq_res, (cache_reply)) static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) { @@ -1847,7 +1831,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); - status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server, &msg, &arg, &res, 1); if (status == 0 && state != NULL) renew_lease(server, timestamp); return status; @@ -2106,7 +2090,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f }; int status; - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server, &msg, &args, &res, 0); if (status == 0) { memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| @@ -2176,7 +2160,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(info->fattr); - return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server, &msg, &args, &res, 0); } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, @@ -2192,43 +2176,15 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, return err; } -static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info, rpc_authflavor_t flavor) -{ - struct rpc_auth *auth; - int ret; - - auth = rpcauth_create(flavor, server->client); - if (!auth) { - ret = -EIO; - goto out; - } - ret = nfs4_lookup_root(server, fhandle, info); - if (ret < 0) - ret = -EAGAIN; -out: - return ret; -} - /* * get the file handle for the "/" directory on the server */ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { - int i, len, status = 0; - rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; - - flav_array[0] = RPC_AUTH_UNIX; - len = gss_mech_list_pseudoflavors(&flav_array[1]); - flav_array[1+len] = RPC_AUTH_NULL; - len += 2; + int status; - for (i = 0; i < len; i++) { - status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); - if (status == 0) - break; - } + status = nfs4_lookup_root(server, fhandle, info); if (status == 0) status = nfs4_server_capabilities(server, fhandle); if (status == 0) @@ -2293,7 +2249,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fattr); - return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server, &msg, &args, &res, 0); } static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) @@ -2353,9 +2309,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, return status; } -static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, - const struct nfs_fh *dirfh, const struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, + const struct qstr *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { int status; struct nfs4_lookup_arg args = { @@ -2377,7 +2333,7 @@ static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, nfs_fattr_init(fattr); dprintk("NFS call lookupfh %s\n", name->name); - status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server, &msg, &args, &res, 0); dprintk("NFS reply lookupfh: %d\n", status); return status; } @@ -2389,7 +2345,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, struct nfs4_exception exception = { }; int err; do { - err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); + err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); /* FIXME: !!!! */ if (err == -NFS4ERR_MOVED) { err = -EREMOTE; @@ -2400,41 +2356,27 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, return err; } -static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, - const struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) +static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int status; dprintk("NFS call lookup %s\n", name->name); - status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); + status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); if (status == -NFS4ERR_MOVED) status = nfs4_get_referral(dir, name, fattr, fhandle); dprintk("NFS reply lookup: %d\n", status); return status; } -void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) -{ - memset(fh, 0, sizeof(struct nfs_fh)); - fattr->fsid.major = 1; - fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | - NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; - fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; - fattr->nlink = 2; -} - -static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), - _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), + _nfs4_proc_lookup(dir, name, fhandle, fattr), &exception); - if (err == -EPERM) - nfs_fixup_secinfo_attributes(fattr, fhandle); } while (exception.retry); return err; } @@ -2479,7 +2421,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry if (res.fattr == NULL) return -ENOMEM; - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server, &msg, &args, &res, 0); if (!status) { entry->mask = 0; if (res.access & NFS4_ACCESS_READ) @@ -2546,7 +2488,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, .rpc_resp = &res, }; - return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); } static int nfs4_proc_readlink(struct inode *inode, struct page *page, @@ -2635,7 +2577,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) if (res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server, &msg, &args, &res, 1); if (status == 0) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2736,7 +2678,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, if (res.old_fattr == NULL || res.new_fattr == NULL) goto out; - status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server, &msg, &arg, &res, 1); if (!status) { update_changeattr(old_dir, &res.old_cinfo); nfs_post_op_update_inode(old_dir, res.old_fattr); @@ -2787,7 +2729,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * if (res.fattr == NULL || res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server, &msg, &arg, &res, 1); if (!status) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2850,8 +2792,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) { - int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, - &data->arg.seq_args, &data->res.seq_res, 1); + int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, + &data->arg, &data->res, 1); if (status == 0) { update_changeattr(dir, &data->res.dir_cinfo); nfs_post_op_update_inode(dir, data->res.dir_fattr); @@ -2963,7 +2905,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; - status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); if (status >= 0) { memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; @@ -3055,7 +2997,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fsstat->fattr); - return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server, &msg, &args, &res, 0); } static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) @@ -3086,7 +3028,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_resp = &res, }; - return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server, &msg, &args, &res, 0); } static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) @@ -3131,7 +3073,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle } nfs_fattr_init(pathconf->fattr); - return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server, &msg, &args, &res, 0); } static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, @@ -3253,9 +3195,12 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; } -static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) +static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) { struct inode *inode = data->inode; + + if (!nfs4_sequence_done(task, &data->res.seq_res)) + return -EAGAIN; if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); @@ -3265,24 +3210,11 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *dat return 0; } -static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) -{ - if (!nfs4_sequence_done(task, &data->res.seq_res)) - return -EAGAIN; - return data->write_done_cb(task, data); -} - static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { struct nfs_server *server = NFS_SERVER(data->inode); - - if (data->lseg) { - data->args.bitmask = NULL; - data->res.fattr = NULL; - } else - data->args.bitmask = server->cache_consistency_bitmask; - if (!data->write_done_cb) - data->write_done_cb = nfs4_commit_done_cb; + + data->args.bitmask = server->cache_consistency_bitmask; data->res.server = server; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; } @@ -3520,7 +3452,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu resp_buf = buf; buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); } - ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); if (ret) goto out_free; if (res.acl_len > args.acl_len) @@ -3595,7 +3527,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl if (i < 0) return i; nfs_inode_return_delegation(inode); - ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + ret = nfs4_call_sync(server, &msg, &arg, &res, 1); /* * Free each page after tx, so the only ref left is @@ -3958,7 +3890,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock lsp = request->fl_u.nfs4_fl.owner; arg.lock_owner.id = lsp->ls_id.id; arg.lock_owner.s_dev = server->s_dev; - status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server, &msg, &arg, &res, 1); switch (status) { case 0: request->fl_type = F_UNLCK; @@ -4686,46 +4618,12 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, nfs_fattr_init(&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server, &msg, &args, &res, 0); nfs_fixup_referral_attributes(&fs_locations->fattr); dprintk("%s: returned status = %d\n", __func__, status); return status; } -static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) -{ - int status; - struct nfs4_secinfo_arg args = { - .dir_fh = NFS_FH(dir), - .name = name, - }; - struct nfs4_secinfo_res res = { - .flavors = flavors, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO], - .rpc_argp = &args, - .rpc_resp = &res, - }; - - dprintk("NFS call secinfo %s\n", name->name); - status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); - dprintk("NFS reply secinfo: %d\n", status); - return status; -} - -int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) -{ - struct nfs4_exception exception = { }; - int err; - do { - err = nfs4_handle_exception(NFS_SERVER(dir), - _nfs4_proc_secinfo(dir, name, flavors), - &exception); - } while (exception.retry); - return err; -} - #ifdef CONFIG_NFS_V4_1 /* * Check the exchange flags returned by the server for invalid flags, having @@ -5618,6 +5516,8 @@ static void nfs4_layoutget_release(void *calldata) struct nfs4_layoutget *lgp = calldata; dprintk("--> %s\n", __func__); + if (lgp->res.layout.buf != NULL) + free_page((unsigned long) lgp->res.layout.buf); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -5649,7 +5549,12 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) dprintk("--> %s\n", __func__); - lgp->res.layoutp = &lgp->args.layout; + lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS); + if (lgp->res.layout.buf == NULL) { + nfs4_layoutget_release(lgp); + return -ENOMEM; + } + lgp->res.seq_res.sr_slot = NULL; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) @@ -5681,7 +5586,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) int status; dprintk("--> %s\n", __func__); - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server, &msg, &args, &res, 0); dprintk("<-- %s status=%d\n", __func__, status); return status; @@ -5701,100 +5606,6 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) } EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); -static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) -{ - struct nfs4_layoutcommit_data *data = calldata; - struct nfs_server *server = NFS_SERVER(data->args.inode); - - if (nfs4_setup_sequence(server, &data->args.seq_args, - &data->res.seq_res, 1, task)) - return; - rpc_call_start(task); -} - -static void -nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) -{ - struct nfs4_layoutcommit_data *data = calldata; - struct nfs_server *server = NFS_SERVER(data->args.inode); - - if (!nfs4_sequence_done(task, &data->res.seq_res)) - return; - - switch (task->tk_status) { /* Just ignore these failures */ - case NFS4ERR_DELEG_REVOKED: /* layout was recalled */ - case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */ - case NFS4ERR_BADLAYOUT: /* no layout */ - case NFS4ERR_GRACE: /* loca_recalim always false */ - task->tk_status = 0; - } - - if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { - nfs_restart_rpc(task, server->nfs_client); - return; - } - - if (task->tk_status == 0) - nfs_post_op_update_inode_force_wcc(data->args.inode, - data->res.fattr); -} - -static void nfs4_layoutcommit_release(void *calldata) -{ - struct nfs4_layoutcommit_data *data = calldata; - - /* Matched by references in pnfs_set_layoutcommit */ - put_lseg(data->lseg); - put_rpccred(data->cred); - kfree(data); -} - -static const struct rpc_call_ops nfs4_layoutcommit_ops = { - .rpc_call_prepare = nfs4_layoutcommit_prepare, - .rpc_call_done = nfs4_layoutcommit_done, - .rpc_release = nfs4_layoutcommit_release, -}; - -int -nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) -{ - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - struct rpc_task_setup task_setup_data = { - .task = &data->task, - .rpc_client = NFS_CLIENT(data->args.inode), - .rpc_message = &msg, - .callback_ops = &nfs4_layoutcommit_ops, - .callback_data = data, - .flags = RPC_TASK_ASYNC, - }; - struct rpc_task *task; - int status = 0; - - dprintk("NFS: %4d initiating layoutcommit call. sync %d " - "lbw: %llu inode %lu\n", - data->task.tk_pid, sync, - data->args.lastbytewritten, - data->args.inode->i_ino); - - task = rpc_run_task(&task_setup_data); - if (IS_ERR(task)) - return PTR_ERR(task); - if (sync == false) - goto out; - status = nfs4_wait_for_completion_rpc_task(task); - if (status != 0) - goto out; - status = task->tk_status; -out: - dprintk("%s: status %d\n", __func__, status); - rpc_put_task(task); - return status; -} #endif /* CONFIG_NFS_V4_1 */ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { @@ -5930,7 +5741,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .close_context = nfs4_close_context, .open_context = nfs4_atomic_open, .init_client = nfs4_init_client, - .secinfo = nfs4_proc_secinfo, }; static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index dddfb5795d7b..0cf560f77884 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -113,7 +112,7 @@ static int nfs4_stat_to_errno(int); #define encode_restorefh_maxsz (op_encode_hdr_maxsz) #define decode_restorefh_maxsz (op_decode_hdr_maxsz) #define encode_fsinfo_maxsz (encode_getattr_maxsz) -#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15) +#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) #define decode_renew_maxsz (op_decode_hdr_maxsz) #define encode_setclientid_maxsz \ @@ -254,8 +253,6 @@ static int nfs4_stat_to_errno(int); (encode_getattr_maxsz) #define decode_fs_locations_maxsz \ (0) -#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) -#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) #if defined(CONFIG_NFS_V4_1) #define NFS4_MAX_MACHINE_NAME_LEN (64) @@ -327,18 +324,6 @@ static int nfs4_stat_to_errno(int); #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ decode_stateid_maxsz + \ XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) -#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ - 2 /* offset */ + \ - 2 /* length */ + \ - 1 /* reclaim */ + \ - encode_stateid_maxsz + \ - 1 /* new offset (true) */ + \ - 2 /* last byte written */ + \ - 1 /* nt_timechanged (false) */ + \ - 1 /* layoutupdate4 layout type */ + \ - 1 /* NULL filelayout layoutupdate4 payload */) -#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) - #else /* CONFIG_NFS_V4_1 */ #define encode_sequence_maxsz 0 #define decode_sequence_maxsz 0 @@ -691,14 +676,6 @@ static int nfs4_stat_to_errno(int); decode_putfh_maxsz + \ decode_lookup_maxsz + \ decode_fs_locations_maxsz) -#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ - encode_sequence_maxsz + \ - encode_putfh_maxsz + \ - encode_secinfo_maxsz) -#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ - decode_sequence_maxsz + \ - decode_putfh_maxsz + \ - decode_secinfo_maxsz) #if defined(CONFIG_NFS_V4_1) #define NFS4_enc_exchange_id_sz \ (compound_encode_hdr_maxsz + \ @@ -750,17 +727,6 @@ static int nfs4_stat_to_errno(int); decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_layoutget_maxsz) -#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ - encode_sequence_maxsz +\ - encode_putfh_maxsz + \ - encode_layoutcommit_maxsz + \ - encode_getattr_maxsz) -#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ - decode_sequence_maxsz + \ - decode_putfh_maxsz + \ - decode_layoutcommit_maxsz + \ - decode_getattr_maxsz) - const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + compound_encode_hdr_maxsz + @@ -1654,18 +1620,6 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state hdr->replen += decode_delegreturn_maxsz; } -static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) -{ - int len = name->len; - __be32 *p; - - p = reserve_space(xdr, 8 + len); - *p++ = cpu_to_be32(OP_SECINFO); - xdr_encode_opaque(p, name->name, len); - hdr->nops++; - hdr->replen += decode_secinfo_maxsz; -} - #if defined(CONFIG_NFS_V4_1) /* NFSv4.1 operations */ static void encode_exchange_id(struct xdr_stream *xdr, @@ -1862,34 +1816,6 @@ encode_layoutget(struct xdr_stream *xdr, hdr->nops++; hdr->replen += decode_layoutget_maxsz; } - -static int -encode_layoutcommit(struct xdr_stream *xdr, - const struct nfs4_layoutcommit_args *args, - struct compound_hdr *hdr) -{ - __be32 *p; - - dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, - NFS_SERVER(args->inode)->pnfs_curr_ld->id); - - p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); - *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); - /* Only whole file layouts */ - p = xdr_encode_hyper(p, 0); /* offset */ - p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ - *p++ = cpu_to_be32(0); /* reclaim */ - p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); - *p++ = cpu_to_be32(1); /* newoffset = TRUE */ - p = xdr_encode_hyper(p, args->lastbytewritten); - *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ - *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ - *p++ = cpu_to_be32(0); /* no file layout payload */ - - hdr->nops++; - hdr->replen += decode_layoutcommit_maxsz; - return 0; -} #endif /* CONFIG_NFS_V4_1 */ /* @@ -2368,8 +2294,7 @@ static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, encode_sequence(xdr, &args->seq_args, &hdr); encode_putfh(xdr, args->fh, &hdr); encode_commit(xdr, args, &hdr); - if (args->bitmask) - encode_getfattr(xdr, args->bitmask, &hdr); + encode_getfattr(xdr, args->bitmask, &hdr); encode_nops(&hdr); } @@ -2540,24 +2465,6 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, encode_nops(&hdr); } -/* - * Encode SECINFO request - */ -static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, - struct xdr_stream *xdr, - struct nfs4_secinfo_arg *args) -{ - struct compound_hdr hdr = { - .minorversion = nfs4_xdr_minorversion(&args->seq_args), - }; - - encode_compound_hdr(xdr, req, &hdr); - encode_sequence(xdr, &args->seq_args, &hdr); - encode_putfh(xdr, args->dir_fh, &hdr); - encode_secinfo(xdr, args->name, &hdr); - encode_nops(&hdr); -} - #if defined(CONFIG_NFS_V4_1) /* * EXCHANGE_ID request @@ -2697,32 +2604,8 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, encode_sequence(xdr, &args->seq_args, &hdr); encode_putfh(xdr, NFS_FH(args->inode), &hdr); encode_layoutget(xdr, args, &hdr); - - xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, - args->layout.pages, 0, args->layout.pglen); - encode_nops(&hdr); } - -/* - * Encode LAYOUTCOMMIT request - */ -static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, - struct xdr_stream *xdr, - struct nfs4_layoutcommit_args *args) -{ - struct compound_hdr hdr = { - .minorversion = nfs4_xdr_minorversion(&args->seq_args), - }; - - encode_compound_hdr(xdr, req, &hdr); - encode_sequence(xdr, &args->seq_args, &hdr); - encode_putfh(xdr, NFS_FH(args->inode), &hdr); - encode_layoutcommit(xdr, args, &hdr); - encode_getfattr(xdr, args->bitmask, &hdr); - encode_nops(&hdr); - return 0; -} #endif /* CONFIG_NFS_V4_1 */ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) @@ -3042,7 +2925,6 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) if (unlikely(!p)) goto out_overflow; bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; - return -be32_to_cpup(p); } return 0; out_overflow: @@ -4030,10 +3912,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, fattr->valid |= status; status = decode_attr_error(xdr, bitmap); - if (status == -NFS4ERR_WRONGSEC) { - nfs_fixup_secinfo_attributes(fattr, fh); - status = 0; - } if (status < 0) goto xdr_error; @@ -4802,73 +4680,6 @@ static int decode_delegreturn(struct xdr_stream *xdr) return decode_op_hdr(xdr, OP_DELEGRETURN); } -static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor) -{ - __be32 *p; - - p = xdr_inline_decode(xdr, 4); - if (unlikely(!p)) - goto out_overflow; - flavor->gss.sec_oid4.len = be32_to_cpup(p); - if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN) - goto out_err; - - p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len); - if (unlikely(!p)) - goto out_overflow; - memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len); - - p = xdr_inline_decode(xdr, 8); - if (unlikely(!p)) - goto out_overflow; - flavor->gss.qop4 = be32_to_cpup(p++); - flavor->gss.service = be32_to_cpup(p); - - return 0; - -out_overflow: - print_overflow_msg(__func__, xdr); - return -EIO; -out_err: - return -EINVAL; -} - -static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) -{ - struct nfs4_secinfo_flavor *sec_flavor; - int status; - __be32 *p; - int i; - - status = decode_op_hdr(xdr, OP_SECINFO); - p = xdr_inline_decode(xdr, 4); - if (unlikely(!p)) - goto out_overflow; - res->flavors->num_flavors = be32_to_cpup(p); - - for (i = 0; i < res->flavors->num_flavors; i++) { - sec_flavor = &res->flavors->flavors[i]; - if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE) - break; - - p = xdr_inline_decode(xdr, 4); - if (unlikely(!p)) - goto out_overflow; - sec_flavor->flavor = be32_to_cpup(p); - - if (sec_flavor->flavor == RPC_AUTH_GSS) { - if (decode_secinfo_gss(xdr, sec_flavor)) - break; - } - } - - return 0; - -out_overflow: - print_overflow_msg(__func__, xdr); - return -EIO; -} - #if defined(CONFIG_NFS_V4_1) static int decode_exchange_id(struct xdr_stream *xdr, struct nfs41_exchange_id_res *res) @@ -5139,9 +4950,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, __be32 *p; int status; u32 layout_count; - struct xdr_buf *rcvbuf = &req->rq_rcv_buf; - struct kvec *iov = rcvbuf->head; - u32 hdrlen, recvd; status = decode_op_hdr(xdr, OP_LAYOUTGET); if (status) @@ -5158,14 +4966,17 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, return -EINVAL; } - p = xdr_inline_decode(xdr, 28); + p = xdr_inline_decode(xdr, 24); if (unlikely(!p)) goto out_overflow; p = xdr_decode_hyper(p, &res->range.offset); p = xdr_decode_hyper(p, &res->range.length); res->range.iomode = be32_to_cpup(p++); res->type = be32_to_cpup(p++); - res->layoutp->len = be32_to_cpup(p); + + status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p); + if (unlikely(status)) + return status; dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", __func__, @@ -5173,18 +4984,12 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, (unsigned long)res->range.length, res->range.iomode, res->type, - res->layoutp->len); + res->layout.len); - hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; - recvd = req->rq_rcv_buf.len - hdrlen; - if (res->layoutp->len > recvd) { - dprintk("NFS: server cheating in layoutget reply: " - "layout len %u > recvd %u\n", - res->layoutp->len, recvd); - return -EINVAL; - } - - xdr_read_pages(xdr, res->layoutp->len); + /* nfs4_proc_layoutget allocated a single page */ + if (res->layout.len > PAGE_SIZE) + return -ENOMEM; + memcpy(res->layout.buf, p, res->layout.len); if (layout_count > 1) { /* We only handle a length one array at the moment. Any @@ -5201,35 +5006,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, print_overflow_msg(__func__, xdr); return -EIO; } - -static int decode_layoutcommit(struct xdr_stream *xdr, - struct rpc_rqst *req, - struct nfs4_layoutcommit_res *res) -{ - __be32 *p; - __u32 sizechanged; - int status; - - status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); - if (status) - return status; - - p = xdr_inline_decode(xdr, 4); - if (unlikely(!p)) - goto out_overflow; - sizechanged = be32_to_cpup(p); - - if (sizechanged) { - /* throw away new size */ - p = xdr_inline_decode(xdr, 8); - if (unlikely(!p)) - goto out_overflow; - } - return 0; -out_overflow: - print_overflow_msg(__func__, xdr); - return -EIO; -} #endif /* CONFIG_NFS_V4_1 */ /* @@ -5947,9 +5723,8 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_commit(xdr, res); if (status) goto out; - if (res->fattr) - decode_getfattr(xdr, res->fattr, res->server, - !RPC_IS_ASYNC(rqstp->rq_task)); + decode_getfattr(xdr, res->fattr, res->server, + !RPC_IS_ASYNC(rqstp->rq_task)); out: return status; } @@ -6144,32 +5919,6 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, return status; } -/* - * Decode SECINFO response - */ -static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, - struct xdr_stream *xdr, - struct nfs4_secinfo_res *res) -{ - struct compound_hdr hdr; - int status; - - status = decode_compound_hdr(xdr, &hdr); - if (status) - goto out; - status = decode_sequence(xdr, &res->seq_res, rqstp); - if (status) - goto out; - status = decode_putfh(xdr); - if (status) - goto out; - status = decode_secinfo(xdr, res); - if (status) - goto out; -out: - return status; -} - #if defined(CONFIG_NFS_V4_1) /* * Decode EXCHANGE_ID response @@ -6317,34 +6066,6 @@ static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, out: return status; } - -/* - * Decode LAYOUTCOMMIT response - */ -static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, - struct xdr_stream *xdr, - struct nfs4_layoutcommit_res *res) -{ - struct compound_hdr hdr; - int status; - - status = decode_compound_hdr(xdr, &hdr); - if (status) - goto out; - status = decode_sequence(xdr, &res->seq_res, rqstp); - if (status) - goto out; - status = decode_putfh(xdr); - if (status) - goto out; - status = decode_layoutcommit(xdr, rqstp, res); - if (status) - goto out; - decode_getfattr(xdr, res->fattr, res->server, - !RPC_IS_ASYNC(rqstp->rq_task)); -out: - return status; -} #endif /* CONFIG_NFS_V4_1 */ /** @@ -6459,6 +6180,10 @@ static struct { { NFS4ERR_SYMLINK, -ELOOP }, { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, { NFS4ERR_DEADLOCK, -EDEADLK }, + { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs + * to be handled by a + * middle-layer. + */ { -1, -EIO } }; @@ -6533,7 +6258,6 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(SETACL, enc_setacl, dec_setacl), PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), - PROC(SECINFO, enc_secinfo, dec_secinfo), #if defined(CONFIG_NFS_V4_1) PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), PROC(CREATE_SESSION, enc_create_session, dec_create_session), @@ -6543,7 +6267,6 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), PROC(LAYOUTGET, enc_layoutget, dec_layoutget), - PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), #endif /* CONFIG_NFS_V4_1 */ }; diff --git a/trunk/fs/nfs/pagelist.c b/trunk/fs/nfs/pagelist.c index 87a593c2b055..23e794410669 100644 --- a/trunk/fs/nfs/pagelist.c +++ b/trunk/fs/nfs/pagelist.c @@ -223,7 +223,6 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, desc->pg_count = 0; desc->pg_bsize = bsize; desc->pg_base = 0; - desc->pg_moreio = 0; desc->pg_inode = inode; desc->pg_doio = doio; desc->pg_ioflags = io_flags; @@ -336,11 +335,9 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, struct nfs_page *req) { while (!nfs_pageio_do_add_request(desc, req)) { - desc->pg_moreio = 1; nfs_pageio_doio(desc); if (desc->pg_error < 0) return 0; - desc->pg_moreio = 0; } return 1; } @@ -398,7 +395,6 @@ int nfs_scan_list(struct nfs_inode *nfsi, pgoff_t idx_end; int found, i; int res; - struct list_head *list; res = 0; if (npages == 0) @@ -419,10 +415,10 @@ int nfs_scan_list(struct nfs_inode *nfsi, idx_start = req->wb_index + 1; if (nfs_set_page_tag_locked(req)) { kref_get(&req->wb_kref); + nfs_list_remove_request(req); radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, tag); - list = pnfs_choose_commit_list(req, dst); - nfs_list_add_request(req, list); + nfs_list_add_request(req, dst); res++; if (res == INT_MAX) goto out; diff --git a/trunk/fs/nfs/pnfs.c b/trunk/fs/nfs/pnfs.c index d9ab97269ce6..f38813a0a295 100644 --- a/trunk/fs/nfs/pnfs.c +++ b/trunk/fs/nfs/pnfs.c @@ -259,7 +259,6 @@ put_lseg(struct pnfs_layout_segment *lseg) pnfs_free_lseg_list(&free_me); } } -EXPORT_SYMBOL_GPL(put_lseg); static bool should_free_lseg(u32 lseg_iomode, u32 recall_iomode) @@ -472,9 +471,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; - struct page **pages = NULL; - int i; - u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -482,21 +478,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); if (lgp == NULL) return NULL; - - /* allocate pages for xdr post processing */ - max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - max_pages = max_resp_sz >> PAGE_SHIFT; - - pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); - if (!pages) - goto out_err_free; - - for (i = 0; i < max_pages; i++) { - pages[i] = alloc_page(GFP_KERNEL); - if (!pages[i]) - goto out_err_free; - } - lgp->args.minlength = NFS4_MAX_UINT64; lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; lgp->args.range.iomode = iomode; @@ -505,8 +486,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); - lgp->args.layout.pages = pages; - lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; /* Synchronously retrieve layout information from server and @@ -517,26 +496,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(iomode), &lo->plh_flags); } - - /* free xdr pages */ - for (i = 0; i < max_pages; i++) - __free_page(pages[i]); - kfree(pages); - return lseg; - -out_err_free: - /* free any allocated xdr pages, lgp as it's not used */ - if (pages) { - for (i = 0; i < max_pages; i++) { - if (!pages[i]) - break; - __free_page(pages[i]); - } - kfree(pages); - } - kfree(lgp); - return NULL; } bool pnfs_roc(struct inode *ino) @@ -985,105 +945,3 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); return trypnfs; } - -/* - * Currently there is only one (whole file) write lseg. - */ -static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) -{ - struct pnfs_layout_segment *lseg, *rv = NULL; - - list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) - if (lseg->pls_range.iomode == IOMODE_RW) - rv = lseg; - return rv; -} - -void -pnfs_set_layoutcommit(struct nfs_write_data *wdata) -{ - struct nfs_inode *nfsi = NFS_I(wdata->inode); - loff_t end_pos = wdata->args.offset + wdata->res.count; - - spin_lock(&nfsi->vfs_inode.i_lock); - if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { - /* references matched in nfs4_layoutcommit_release */ - get_lseg(wdata->lseg); - wdata->lseg->pls_lc_cred = - get_rpccred(wdata->args.context->state->owner->so_cred); - mark_inode_dirty_sync(wdata->inode); - dprintk("%s: Set layoutcommit for inode %lu ", - __func__, wdata->inode->i_ino); - } - if (end_pos > wdata->lseg->pls_end_pos) - wdata->lseg->pls_end_pos = end_pos; - spin_unlock(&nfsi->vfs_inode.i_lock); -} -EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); - -/* - * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and - * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough - * data to disk to allow the server to recover the data if it crashes. - * LAYOUTCOMMIT is only needed when the NFL4_UFLG_COMMIT_THRU_MDS flag - * is off, and a COMMIT is sent to a data server, or - * if WRITEs to a data server return NFS_DATA_SYNC. - */ -int -pnfs_layoutcommit_inode(struct inode *inode, bool sync) -{ - struct nfs4_layoutcommit_data *data; - struct nfs_inode *nfsi = NFS_I(inode); - struct pnfs_layout_segment *lseg; - struct rpc_cred *cred; - loff_t end_pos; - int status = 0; - - dprintk("--> %s inode %lu\n", __func__, inode->i_ino); - - if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) - return 0; - - /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ - data = kzalloc(sizeof(*data), GFP_NOFS); - if (!data) { - mark_inode_dirty_sync(inode); - status = -ENOMEM; - goto out; - } - - spin_lock(&inode->i_lock); - if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { - spin_unlock(&inode->i_lock); - kfree(data); - goto out; - } - /* - * Currently only one (whole file) write lseg which is referenced - * in pnfs_set_layoutcommit and will be found. - */ - lseg = pnfs_list_write_lseg(inode); - - end_pos = lseg->pls_end_pos; - cred = lseg->pls_lc_cred; - lseg->pls_end_pos = 0; - lseg->pls_lc_cred = NULL; - - memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, - sizeof(nfsi->layout->plh_stateid.data)); - spin_unlock(&inode->i_lock); - - data->args.inode = inode; - data->lseg = lseg; - data->cred = cred; - nfs_fattr_init(&data->fattr); - data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; - data->res.fattr = &data->fattr; - data->args.lastbytewritten = end_pos - 1; - data->res.server = NFS_SERVER(inode); - - status = nfs4_proc_layoutcommit(data, sync); -out: - dprintk("<-- %s status %d\n", __func__, status); - return status; -} diff --git a/trunk/fs/nfs/pnfs.h b/trunk/fs/nfs/pnfs.h index bc4827202e7a..6380b9405bcd 100644 --- a/trunk/fs/nfs/pnfs.h +++ b/trunk/fs/nfs/pnfs.h @@ -43,8 +43,6 @@ struct pnfs_layout_segment { atomic_t pls_refcount; unsigned long pls_flags; struct pnfs_layout_hdr *pls_layout; - struct rpc_cred *pls_lc_cred; /* LAYOUTCOMMIT credential */ - loff_t pls_end_pos; /* LAYOUTCOMMIT write end */ }; enum pnfs_try_status { @@ -76,13 +74,6 @@ struct pnfs_layoutdriver_type { /* test for nfs page cache coalescing */ int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); - /* Returns true if layoutdriver wants to divert this request to - * driver's commit routine. - */ - bool (*mark_pnfs_commit)(struct pnfs_layout_segment *lseg); - struct list_head * (*choose_commit_list) (struct nfs_page *req); - int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how); - /* * Return PNFS_ATTEMPTED to indicate the layout code has attempted * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS @@ -109,6 +100,7 @@ struct pnfs_device { unsigned int layout_type; unsigned int mincount; struct page **pages; + void *area; unsigned int pgbase; unsigned int pglen; }; @@ -153,8 +145,7 @@ bool pnfs_roc(struct inode *ino); void pnfs_roc_release(struct inode *ino); void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); bool pnfs_roc_drain(struct inode *ino, u32 *barrier); -void pnfs_set_layoutcommit(struct nfs_write_data *wdata); -int pnfs_layoutcommit_inode(struct inode *inode, bool sync); + static inline int lo_fail_bit(u32 iomode) { @@ -178,51 +169,6 @@ static inline int pnfs_enabled_sb(struct nfs_server *nfss) return nfss->pnfs_curr_ld != NULL; } -static inline void -pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) -{ - if (lseg) { - struct pnfs_layoutdriver_type *ld; - - ld = NFS_SERVER(req->wb_page->mapping->host)->pnfs_curr_ld; - if (ld->mark_pnfs_commit && ld->mark_pnfs_commit(lseg)) { - set_bit(PG_PNFS_COMMIT, &req->wb_flags); - req->wb_commit_lseg = get_lseg(lseg); - } - } -} - -static inline int -pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) -{ - if (!test_and_clear_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags)) - return PNFS_NOT_ATTEMPTED; - return NFS_SERVER(inode)->pnfs_curr_ld->commit_pagelist(inode, mds_pages, how); -} - -static inline struct list_head * -pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds) -{ - struct list_head *rv; - - if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags)) { - struct inode *inode = req->wb_commit_lseg->pls_layout->plh_inode; - - set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags); - rv = NFS_SERVER(inode)->pnfs_curr_ld->choose_commit_list(req); - /* matched by ref taken when PG_PNFS_COMMIT is set */ - put_lseg(req->wb_commit_lseg); - } else - rv = mds; - return rv; -} - -static inline void pnfs_clear_request_commit(struct nfs_page *req) -{ - if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags)) - put_lseg(req->wb_commit_lseg); -} - #else /* CONFIG_NFS_V4_1 */ static inline void pnfs_destroy_all_layouts(struct nfs_client *clp) @@ -306,31 +252,6 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *ino) pgio->pg_test = NULL; } -static inline void -pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) -{ -} - -static inline int -pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) -{ - return PNFS_NOT_ATTEMPTED; -} - -static inline struct list_head * -pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds) -{ - return mds; -} - -static inline void pnfs_clear_request_commit(struct nfs_page *req) -{ -} - -static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) -{ - return 0; -} #endif /* CONFIG_NFS_V4_1 */ #endif /* FS_NFS_PNFS_H */ diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index ac40b8535d7e..b8ec170f2a0f 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -177,7 +177,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, +nfs_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_diropargs arg = { diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 85d75254328e..47a3ad63e0d5 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -59,7 +59,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void) } return p; } -EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); void nfs_commit_free(struct nfs_write_data *p) { @@ -67,7 +66,6 @@ void nfs_commit_free(struct nfs_write_data *p) kfree(p->pagevec); mempool_free(p, nfs_commit_mempool); } -EXPORT_SYMBOL_GPL(nfs_commit_free); struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) { @@ -181,8 +179,8 @@ static int wb_priority(struct writeback_control *wbc) if (wbc->for_reclaim) return FLUSH_HIGHPRI | FLUSH_STABLE; if (wbc->for_kupdate || wbc->for_background) - return FLUSH_LOWPRI | FLUSH_COND_STABLE; - return FLUSH_COND_STABLE; + return FLUSH_LOWPRI; + return 0; } /* @@ -443,7 +441,7 @@ nfs_mark_request_dirty(struct nfs_page *req) * Add a request to the inode's commit list. */ static void -nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) +nfs_mark_request_commit(struct nfs_page *req) { struct inode *inode = req->wb_context->path.dentry->d_inode; struct nfs_inode *nfsi = NFS_I(inode); @@ -455,7 +453,6 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) NFS_PAGE_TAG_COMMIT); nfsi->ncommit++; spin_unlock(&inode->i_lock); - pnfs_mark_request_commit(req, lseg); inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); __mark_inode_dirty(inode, I_DIRTY_DATASYNC); @@ -477,18 +474,14 @@ nfs_clear_request_commit(struct nfs_page *req) static inline int nfs_write_need_commit(struct nfs_write_data *data) { - if (data->verf.committed == NFS_DATA_SYNC) - return data->lseg == NULL; - else - return data->verf.committed != NFS_FILE_SYNC; + return data->verf.committed != NFS_FILE_SYNC; } static inline -int nfs_reschedule_unstable_write(struct nfs_page *req, - struct nfs_write_data *data) +int nfs_reschedule_unstable_write(struct nfs_page *req) { if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { - nfs_mark_request_commit(req, data->lseg); + nfs_mark_request_commit(req); return 1; } if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { @@ -499,7 +492,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req, } #else static inline void -nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) +nfs_mark_request_commit(struct nfs_page *req) { } @@ -516,8 +509,7 @@ int nfs_write_need_commit(struct nfs_write_data *data) } static inline -int nfs_reschedule_unstable_write(struct nfs_page *req, - struct nfs_write_data *data) +int nfs_reschedule_unstable_write(struct nfs_page *req) { return 0; } @@ -620,11 +612,9 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, } if (nfs_clear_request_commit(req) && - radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { + radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, + req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) NFS_I(inode)->ncommit--; - pnfs_clear_request_commit(req); - } /* Okay, the request matches. Update the region */ if (offset < req->wb_offset) { @@ -772,12 +762,11 @@ int nfs_updatepage(struct file *file, struct page *page, return status; } -static void nfs_writepage_release(struct nfs_page *req, - struct nfs_write_data *data) +static void nfs_writepage_release(struct nfs_page *req) { struct page *page = req->wb_page; - if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) + if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) nfs_inode_remove_request(req); nfs_clear_page_tag_locked(req); nfs_end_page_writeback(page); @@ -874,7 +863,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, data->args.context = get_nfs_open_context(req->wb_context); data->args.lock_context = req->wb_lock_context; data->args.stable = NFS_UNSTABLE; - if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { + if (how & FLUSH_STABLE) { data->args.stable = NFS_DATA_SYNC; if (!nfs_need_commit(NFS_I(inode))) data->args.stable = NFS_FILE_SYNC; @@ -923,12 +912,6 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) nfs_list_remove_request(req); - if ((desc->pg_ioflags & FLUSH_COND_STABLE) && - (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || - desc->pg_count > wsize)) - desc->pg_ioflags &= ~FLUSH_COND_STABLE; - - nbytes = desc->pg_count; do { size_t len = min(nbytes, wsize); @@ -1019,10 +1002,6 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) if ((!lseg) && list_is_singular(&data->pages)) lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); - if ((desc->pg_ioflags & FLUSH_COND_STABLE) && - (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) - desc->pg_ioflags &= ~FLUSH_COND_STABLE; - /* Set up the argument struct */ ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); out: @@ -1095,7 +1074,7 @@ static void nfs_writeback_release_partial(void *calldata) out: if (atomic_dec_and_test(&req->wb_complete)) - nfs_writepage_release(req, data); + nfs_writepage_release(req); nfs_writedata_release(calldata); } @@ -1162,7 +1141,7 @@ static void nfs_writeback_release_full(void *calldata) if (nfs_write_need_commit(data)) { memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); - nfs_mark_request_commit(req, data->lseg); + nfs_mark_request_commit(req); dprintk(" marked for commit\n"); goto next; } @@ -1272,82 +1251,57 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) { - int ret; - if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) return 1; - if (!may_wait) - return 0; - ret = out_of_line_wait_on_bit_lock(&nfsi->flags, - NFS_INO_COMMIT, - nfs_wait_bit_killable, - TASK_KILLABLE); - return (ret < 0) ? ret : 1; + if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, + NFS_INO_COMMIT, nfs_wait_bit_killable, + TASK_KILLABLE)) + return 1; + return 0; } -void nfs_commit_clear_lock(struct nfs_inode *nfsi) +static void nfs_commit_clear_lock(struct nfs_inode *nfsi) { clear_bit(NFS_INO_COMMIT, &nfsi->flags); smp_mb__after_clear_bit(); wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); } -EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); -void nfs_commitdata_release(void *data) + +static void nfs_commitdata_release(void *data) { struct nfs_write_data *wdata = data; - put_lseg(wdata->lseg); put_nfs_open_context(wdata->args.context); nfs_commit_free(wdata); } -EXPORT_SYMBOL_GPL(nfs_commitdata_release); -int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, - const struct rpc_call_ops *call_ops, - int how) +/* + * Set up the argument/result storage required for the RPC call. + */ +static int nfs_commit_rpcsetup(struct list_head *head, + struct nfs_write_data *data, + int how) { - struct rpc_task *task; + struct nfs_page *first = nfs_list_entry(head->next); + struct inode *inode = first->wb_context->path.dentry->d_inode; int priority = flush_task_priority(how); + struct rpc_task *task; struct rpc_message msg = { .rpc_argp = &data->args, .rpc_resp = &data->res, - .rpc_cred = data->cred, + .rpc_cred = first->wb_context->cred, }; struct rpc_task_setup task_setup_data = { .task = &data->task, - .rpc_client = clnt, + .rpc_client = NFS_CLIENT(inode), .rpc_message = &msg, - .callback_ops = call_ops, + .callback_ops = &nfs_commit_ops, .callback_data = data, .workqueue = nfsiod_workqueue, .flags = RPC_TASK_ASYNC, .priority = priority, }; - /* Set up the initial task struct. */ - NFS_PROTO(data->inode)->commit_setup(data, &msg); - - dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); - - task = rpc_run_task(&task_setup_data); - if (IS_ERR(task)) - return PTR_ERR(task); - if (how & FLUSH_SYNC) - rpc_wait_for_completion_task(task); - rpc_put_task(task); - return 0; -} -EXPORT_SYMBOL_GPL(nfs_initiate_commit); - -/* - * Set up the argument/result storage required for the RPC call. - */ -void nfs_init_commit(struct nfs_write_data *data, - struct list_head *head, - struct pnfs_layout_segment *lseg) -{ - struct nfs_page *first = nfs_list_entry(head->next); - struct inode *inode = first->wb_context->path.dentry->d_inode; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ @@ -1355,9 +1309,7 @@ void nfs_init_commit(struct nfs_write_data *data, list_splice_init(head, &data->pages); data->inode = inode; - data->cred = first->wb_context->cred; - data->lseg = lseg; /* reference transferred */ - data->mds_ops = &nfs_commit_ops; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(data->inode); /* Note: we always request a commit of the entire inode */ @@ -1368,25 +1320,20 @@ void nfs_init_commit(struct nfs_write_data *data, data->res.fattr = &data->fattr; data->res.verf = &data->verf; nfs_fattr_init(&data->fattr); -} -EXPORT_SYMBOL_GPL(nfs_init_commit); -void nfs_retry_commit(struct list_head *page_list, - struct pnfs_layout_segment *lseg) -{ - struct nfs_page *req; + /* Set up the initial task struct. */ + NFS_PROTO(inode)->commit_setup(data, &msg); - while (!list_empty(page_list)) { - req = nfs_list_entry(page_list->next); - nfs_list_remove_request(req); - nfs_mark_request_commit(req, lseg); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - dec_bdi_stat(req->wb_page->mapping->backing_dev_info, - BDI_RECLAIMABLE); - nfs_clear_page_tag_locked(req); - } + dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); + + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return PTR_ERR(task); + if (how & FLUSH_SYNC) + rpc_wait_for_completion_task(task); + rpc_put_task(task); + return 0; } -EXPORT_SYMBOL_GPL(nfs_retry_commit); /* * Commit dirty pages @@ -1395,6 +1342,7 @@ static int nfs_commit_list(struct inode *inode, struct list_head *head, int how) { struct nfs_write_data *data; + struct nfs_page *req; data = nfs_commitdata_alloc(); @@ -1402,10 +1350,17 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) goto out_bad; /* Set up the argument struct */ - nfs_init_commit(data, head, NULL); - return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); + return nfs_commit_rpcsetup(head, data, how); out_bad: - nfs_retry_commit(head, NULL); + while (!list_empty(head)) { + req = nfs_list_entry(head->next); + nfs_list_remove_request(req); + nfs_mark_request_commit(req); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, + BDI_RECLAIMABLE); + nfs_clear_page_tag_locked(req); + } nfs_commit_clear_lock(NFS_I(inode)); return -ENOMEM; } @@ -1425,9 +1380,10 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) return; } -void nfs_commit_release_pages(struct nfs_write_data *data) +static void nfs_commit_release(void *calldata) { - struct nfs_page *req; + struct nfs_write_data *data = calldata; + struct nfs_page *req; int status = data->task.tk_status; while (!list_empty(&data->pages)) { @@ -1461,14 +1417,6 @@ void nfs_commit_release_pages(struct nfs_write_data *data) next: nfs_clear_page_tag_locked(req); } -} -EXPORT_SYMBOL_GPL(nfs_commit_release_pages); - -static void nfs_commit_release(void *calldata) -{ - struct nfs_write_data *data = calldata; - - nfs_commit_release_pages(data); nfs_commit_clear_lock(NFS_I(data->inode)); nfs_commitdata_release(calldata); } @@ -1485,30 +1433,23 @@ int nfs_commit_inode(struct inode *inode, int how) { LIST_HEAD(head); int may_wait = how & FLUSH_SYNC; - int res; + int res = 0; - res = nfs_commit_set_lock(NFS_I(inode), may_wait); - if (res <= 0) + if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) goto out_mark_dirty; spin_lock(&inode->i_lock); res = nfs_scan_commit(inode, &head, 0, 0); spin_unlock(&inode->i_lock); if (res) { - int error; - - error = pnfs_commit_list(inode, &head, how); - if (error == PNFS_NOT_ATTEMPTED) - error = nfs_commit_list(inode, &head, how); + int error = nfs_commit_list(inode, &head, how); if (error < 0) return error; - if (!may_wait) + if (may_wait) + wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, + nfs_wait_bit_killable, + TASK_KILLABLE); + else goto out_mark_dirty; - error = wait_on_bit(&NFS_I(inode)->flags, - NFS_INO_COMMIT, - nfs_wait_bit_killable, - TASK_KILLABLE); - if (error < 0) - return error; } else nfs_commit_clear_lock(NFS_I(inode)); return res; @@ -1562,22 +1503,7 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) { - int ret; - - ret = nfs_commit_unstable_pages(inode, wbc); - if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { - int status; - bool sync = true; - - if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking || - wbc->for_background) - sync = false; - - status = pnfs_layoutcommit_inode(inode, sync); - if (status < 0) - return status; - } - return ret; + return nfs_commit_unstable_pages(inode, wbc); } /* diff --git a/trunk/fs/nfs_common/nfsacl.c b/trunk/fs/nfs_common/nfsacl.c index ec0f277be7f5..84c27d69d421 100644 --- a/trunk/fs/nfs_common/nfsacl.c +++ b/trunk/fs/nfs_common/nfsacl.c @@ -117,6 +117,7 @@ int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, * invoked in contexts where a memory allocation failure is * fatal. Fortunately this fake ACL is small enough to * construct on the stack. */ + memset(acl2, 0, sizeof(acl2)); posix_acl_init(acl2, 4); /* Insert entries in canonical order: other orders seem diff --git a/trunk/include/linux/jbd2.h b/trunk/include/linux/jbd2.h index a32dcaec04e1..27e79c27ba08 100644 --- a/trunk/include/linux/jbd2.h +++ b/trunk/include/linux/jbd2.h @@ -432,35 +432,13 @@ struct jbd2_journal_handle int h_err; /* Flags [no locking] */ - unsigned int h_sync:1; /* sync-on-close */ - unsigned int h_jdata:1; /* force data journaling */ - unsigned int h_aborted:1; /* fatal error on handle */ - unsigned int h_cowing:1; /* COWing block to snapshot */ - - /* Number of buffers requested by user: - * (before adding the COW credits factor) */ - unsigned int h_base_credits:14; - - /* Number of buffers the user is allowed to dirty: - * (counts only buffers dirtied when !h_cowing) */ - unsigned int h_user_credits:14; - + unsigned int h_sync: 1; /* sync-on-close */ + unsigned int h_jdata: 1; /* force data journaling */ + unsigned int h_aborted: 1; /* fatal error on handle */ #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map h_lockdep_map; #endif - -#ifdef CONFIG_JBD2_DEBUG - /* COW debugging counters: */ - unsigned int h_cow_moved; /* blocks moved to snapshot */ - unsigned int h_cow_copied; /* blocks copied to snapshot */ - unsigned int h_cow_ok_jh; /* blocks already COWed during current - transaction */ - unsigned int h_cow_ok_bitmap; /* blocks not set in COW bitmap */ - unsigned int h_cow_ok_mapped;/* blocks already mapped in snapshot */ - unsigned int h_cow_bitmaps; /* COW bitmaps created */ - unsigned int h_cow_excluded; /* blocks set in exclude bitmap */ -#endif }; diff --git a/trunk/include/linux/journal-head.h b/trunk/include/linux/journal-head.h index 44e95d0a721f..525aac3c97df 100644 --- a/trunk/include/linux/journal-head.h +++ b/trunk/include/linux/journal-head.h @@ -40,13 +40,6 @@ struct journal_head { */ unsigned b_modified; - /* - * This feild tracks the last transaction id in which this buffer - * has been cowed - * [jbd_lock_bh_state()] - */ - unsigned b_cow_tid; - /* * Copy of the buffer data frozen for writing to the log. * [jbd_lock_bh_state()] diff --git a/trunk/include/linux/nfs4.h b/trunk/include/linux/nfs4.h index b528f6d4b860..134716e5e350 100644 --- a/trunk/include/linux/nfs4.h +++ b/trunk/include/linux/nfs4.h @@ -550,7 +550,6 @@ enum { NFSPROC4_CLNT_SETACL, NFSPROC4_CLNT_FS_LOCATIONS, NFSPROC4_CLNT_RELEASE_LOCKOWNER, - NFSPROC4_CLNT_SECINFO, /* nfs41 */ NFSPROC4_CLNT_EXCHANGE_ID, @@ -561,7 +560,6 @@ enum { NFSPROC4_CLNT_RECLAIM_COMPLETE, NFSPROC4_CLNT_LAYOUTGET, NFSPROC4_CLNT_GETDEVICEINFO, - NFSPROC4_CLNT_LAYOUTCOMMIT, }; /* nfs41 types */ diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 1b93b9c60e55..f88522b10a38 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -33,8 +33,6 @@ #define FLUSH_STABLE 4 /* commit to stable storage */ #define FLUSH_LOWPRI 8 /* low priority background flush */ #define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */ -#define FLUSH_COND_STABLE 32 /* conditional stable write - only stable - * if everything fits in one RPC */ #ifdef __KERNEL__ @@ -95,13 +93,8 @@ struct nfs_open_context { int error; struct list_head list; -}; -struct nfs_open_dir_context { - struct rpc_cred *cred; __u64 dir_cookie; - __u64 dup_cookie; - int duped; }; /* @@ -198,7 +191,6 @@ struct nfs_inode { /* pNFS layout information */ struct pnfs_layout_hdr *layout; - atomic_t commits_outstanding; #endif /* CONFIG_NFS_V4*/ #ifdef CONFIG_NFS_FSCACHE struct fscache_cookie *fscache; @@ -227,8 +219,6 @@ struct nfs_inode { #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ #define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ #define NFS_INO_COMMIT (7) /* inode is committing unstable writes */ -#define NFS_INO_PNFS_COMMIT (8) /* use pnfs code for commit */ -#define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */ static inline struct nfs_inode *NFS_I(const struct inode *inode) { diff --git a/trunk/include/linux/nfs_page.h b/trunk/include/linux/nfs_page.h index 8023e4e25133..90907ada6d52 100644 --- a/trunk/include/linux/nfs_page.h +++ b/trunk/include/linux/nfs_page.h @@ -33,15 +33,11 @@ enum { PG_CLEAN, PG_NEED_COMMIT, PG_NEED_RESCHED, - PG_PNFS_COMMIT, }; struct nfs_inode; struct nfs_page { - union { - struct list_head wb_list; /* Defines state of page: */ - struct pnfs_layout_segment *wb_commit_lseg; /* Used when PG_PNFS_COMMIT set */ - }; + struct list_head wb_list; /* Defines state of page: */ struct page *wb_page; /* page to read in/write out */ struct nfs_open_context *wb_context; /* File state context info */ struct nfs_lock_context *wb_lock_context; /* lock context info */ @@ -61,7 +57,6 @@ struct nfs_pageio_descriptor { size_t pg_count; size_t pg_bsize; unsigned int pg_base; - char pg_moreio; struct inode *pg_inode; int (*pg_doio)(struct nfs_pageio_descriptor *); diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index 78b101e487ea..2c2c67d2eb42 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -3,7 +3,6 @@ #include #include -#include /* * To change the maximum rsize and wsize supported by the NFS client, adjust @@ -15,9 +14,6 @@ #define NFS_DEF_FILE_IO_SIZE (4096U) #define NFS_MIN_FILE_IO_SIZE (1024U) -/* Forward declaration for NFS v3 */ -struct nfs4_secinfo_flavors; - struct nfs_fsid { uint64_t major; uint64_t minor; @@ -82,7 +78,6 @@ struct nfs_fattr { #define NFS_ATTR_FATTR_CHANGE (1U << 17) #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ -#define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | NFS_ATTR_FATTR_MODE \ @@ -195,9 +190,8 @@ struct nfs4_get_lease_time_res { #define PNFS_LAYOUT_MAXSIZE 4096 struct nfs4_layoutdriver_data { - struct page **pages; - __u32 pglen; __u32 len; + void *buf; }; struct pnfs_layout_range { @@ -215,7 +209,6 @@ struct nfs4_layoutget_args { struct nfs_open_context *ctx; struct nfs4_sequence_args seq_args; nfs4_stateid stateid; - struct nfs4_layoutdriver_data layout; }; struct nfs4_layoutget_res { @@ -223,8 +216,8 @@ struct nfs4_layoutget_res { struct pnfs_layout_range range; __u32 type; nfs4_stateid stateid; + struct nfs4_layoutdriver_data layout; struct nfs4_sequence_res seq_res; - struct nfs4_layoutdriver_data *layoutp; }; struct nfs4_layoutget { @@ -243,29 +236,6 @@ struct nfs4_getdeviceinfo_res { struct nfs4_sequence_res seq_res; }; -struct nfs4_layoutcommit_args { - nfs4_stateid stateid; - __u64 lastbytewritten; - struct inode *inode; - const u32 *bitmask; - struct nfs4_sequence_args seq_args; -}; - -struct nfs4_layoutcommit_res { - struct nfs_fattr *fattr; - const struct nfs_server *server; - struct nfs4_sequence_res seq_res; -}; - -struct nfs4_layoutcommit_data { - struct rpc_task task; - struct nfs_fattr fattr; - struct pnfs_layout_segment *lseg; - struct rpc_cred *cred; - struct nfs4_layoutcommit_args args; - struct nfs4_layoutcommit_res res; -}; - /* * Arguments to the open call. */ @@ -966,38 +936,6 @@ struct nfs4_fs_locations_res { struct nfs4_sequence_res seq_res; }; -struct nfs4_secinfo_oid { - unsigned int len; - char data[GSS_OID_MAX_LEN]; -}; - -struct nfs4_secinfo_gss { - struct nfs4_secinfo_oid sec_oid4; - unsigned int qop4; - unsigned int service; -}; - -struct nfs4_secinfo_flavor { - unsigned int flavor; - struct nfs4_secinfo_gss gss; -}; - -struct nfs4_secinfo_flavors { - unsigned int num_flavors; - struct nfs4_secinfo_flavor flavors[0]; -}; - -struct nfs4_secinfo_arg { - const struct nfs_fh *dir_fh; - const struct qstr *name; - struct nfs4_sequence_args seq_args; -}; - -struct nfs4_secinfo_res { - struct nfs4_secinfo_flavors *flavors; - struct nfs4_sequence_res seq_res; -}; - #endif /* CONFIG_NFS_V4 */ struct nfstime4 { @@ -1102,7 +1040,6 @@ struct nfs_write_data { struct nfs_writeres res; /* result struct */ struct pnfs_layout_segment *lseg; struct nfs_client *ds_clp; /* pNFS data server */ - int ds_commit_index; const struct rpc_call_ops *mds_ops; int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); #ifdef CONFIG_NFS_V4 @@ -1134,7 +1071,7 @@ struct nfs_rpc_ops { struct nfs_fattr *); int (*setattr) (struct dentry *, struct nfs_fattr *, struct iattr *); - int (*lookup) (struct rpc_clnt *clnt, struct inode *, struct qstr *, + int (*lookup) (struct inode *, struct qstr *, struct nfs_fh *, struct nfs_fattr *); int (*access) (struct inode *, struct nfs_access_entry *); int (*readlink)(struct inode *, struct page *, unsigned int, @@ -1181,7 +1118,6 @@ struct nfs_rpc_ops { struct iattr *iattr); int (*init_client) (struct nfs_client *, const struct rpc_timeout *, const char *, rpc_authflavor_t, int); - int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); }; /* diff --git a/trunk/include/linux/sunrpc/gss_api.h b/trunk/include/linux/sunrpc/gss_api.h index 332da61cf8b7..5d8048beb051 100644 --- a/trunk/include/linux/sunrpc/gss_api.h +++ b/trunk/include/linux/sunrpc/gss_api.h @@ -126,9 +126,6 @@ struct gss_api_mech *gss_mech_get_by_name(const char *); /* Similar, but get by pseudoflavor. */ struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32); -/* Fill in an array with a list of supported pseudoflavors */ -int gss_mech_list_pseudoflavors(u32 *); - /* Just increments the mechanism's reference count and returns its input: */ struct gss_api_mech * gss_mech_get(struct gss_api_mech *); diff --git a/trunk/include/trace/events/ext4.h b/trunk/include/trace/events/ext4.h index e09592d2f916..e5e345fb2a5c 100644 --- a/trunk/include/trace/events/ext4.h +++ b/trunk/include/trace/events/ext4.h @@ -21,7 +21,8 @@ TRACE_EVENT(ext4_free_inode, TP_ARGS(inode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( uid_t, uid ) @@ -30,7 +31,8 @@ TRACE_EVENT(ext4_free_inode, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->uid = inode->i_uid; @@ -39,9 +41,9 @@ TRACE_EVENT(ext4_free_inode, ), TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->mode, __entry->uid, __entry->gid, + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->mode, + __entry->uid, __entry->gid, (unsigned long long) __entry->blocks) ); @@ -51,19 +53,21 @@ TRACE_EVENT(ext4_request_inode, TP_ARGS(dir, mode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, dir ) __field( umode_t, mode ) ), TP_fast_assign( - __entry->dev = dir->i_sb->s_dev; + __entry->dev_major = MAJOR(dir->i_sb->s_dev); + __entry->dev_minor = MINOR(dir->i_sb->s_dev); __entry->dir = dir->i_ino; __entry->mode = mode; ), TP_printk("dev %d,%d dir %lu mode 0%o", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->dir, __entry->mode) ); @@ -73,21 +77,23 @@ TRACE_EVENT(ext4_allocate_inode, TP_ARGS(inode, dir, mode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( ino_t, dir ) __field( umode_t, mode ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->dir = dir->i_ino; __entry->mode = mode; ), TP_printk("dev %d,%d ino %lu dir %lu mode 0%o", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, (unsigned long) __entry->dir, __entry->mode) ); @@ -98,19 +104,21 @@ TRACE_EVENT(ext4_evict_inode, TP_ARGS(inode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( int, nlink ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->nlink = inode->i_nlink; ), TP_printk("dev %d,%d ino %lu nlink %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->nlink) ); @@ -120,19 +128,21 @@ TRACE_EVENT(ext4_drop_inode, TP_ARGS(inode, drop), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( int, drop ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->drop = drop; ), TP_printk("dev %d,%d ino %lu drop %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->drop) ); @@ -142,19 +152,21 @@ TRACE_EVENT(ext4_mark_inode_dirty, TP_ARGS(inode, IP), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field(unsigned long, ip ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->ip = IP; ), TP_printk("dev %d,%d ino %lu caller %pF", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, (void *)__entry->ip) ); @@ -164,19 +176,21 @@ TRACE_EVENT(ext4_begin_ordered_truncate, TP_ARGS(inode, new_size), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( loff_t, new_size ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->new_size = new_size; ), TP_printk("dev %d,%d ino %lu new_size %lld", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, (long long) __entry->new_size) ); @@ -189,7 +203,8 @@ DECLARE_EVENT_CLASS(ext4__write_begin, TP_ARGS(inode, pos, len, flags), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( loff_t, pos ) __field( unsigned int, len ) @@ -197,7 +212,8 @@ DECLARE_EVENT_CLASS(ext4__write_begin, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->pos = pos; __entry->len = len; @@ -205,7 +221,7 @@ DECLARE_EVENT_CLASS(ext4__write_begin, ), TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->pos, __entry->len, __entry->flags) ); @@ -233,7 +249,8 @@ DECLARE_EVENT_CLASS(ext4__write_end, TP_ARGS(inode, pos, len, copied), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( loff_t, pos ) __field( unsigned int, len ) @@ -241,7 +258,8 @@ DECLARE_EVENT_CLASS(ext4__write_end, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->pos = pos; __entry->len = len; @@ -249,9 +267,9 @@ DECLARE_EVENT_CLASS(ext4__write_end, ), TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->pos, __entry->len, __entry->copied) + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->pos, + __entry->len, __entry->copied) ); DEFINE_EVENT(ext4__write_end, ext4_ordered_write_end, @@ -292,20 +310,22 @@ TRACE_EVENT(ext4_writepage, TP_ARGS(inode, page), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( pgoff_t, index ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->index = page->index; ), TP_printk("dev %d,%d ino %lu page_index %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->index) ); @@ -315,39 +335,43 @@ TRACE_EVENT(ext4_da_writepages, TP_ARGS(inode, wbc), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( long, nr_to_write ) __field( long, pages_skipped ) __field( loff_t, range_start ) __field( loff_t, range_end ) - __field( int, sync_mode ) __field( char, for_kupdate ) + __field( char, for_reclaim ) __field( char, range_cyclic ) __field( pgoff_t, writeback_index ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->nr_to_write = wbc->nr_to_write; __entry->pages_skipped = wbc->pages_skipped; __entry->range_start = wbc->range_start; __entry->range_end = wbc->range_end; - __entry->sync_mode = wbc->sync_mode; __entry->for_kupdate = wbc->for_kupdate; + __entry->for_reclaim = wbc->for_reclaim; __entry->range_cyclic = wbc->range_cyclic; __entry->writeback_index = inode->i_mapping->writeback_index; ), TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld " - "range_start %llu range_end %llu sync_mode %d" - "for_kupdate %d range_cyclic %d writeback_index %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), + "range_start %llu range_end %llu " + "for_kupdate %d for_reclaim %d " + "range_cyclic %d writeback_index %lu", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->nr_to_write, __entry->pages_skipped, __entry->range_start, - __entry->range_end, __entry->sync_mode, - __entry->for_kupdate, __entry->range_cyclic, + __entry->range_end, + __entry->for_kupdate, __entry->for_reclaim, + __entry->range_cyclic, (unsigned long) __entry->writeback_index) ); @@ -357,7 +381,8 @@ TRACE_EVENT(ext4_da_write_pages, TP_ARGS(inode, mpd), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u64, b_blocknr ) __field( __u32, b_size ) @@ -365,11 +390,11 @@ TRACE_EVENT(ext4_da_write_pages, __field( unsigned long, first_page ) __field( int, io_done ) __field( int, pages_written ) - __field( int, sync_mode ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->b_blocknr = mpd->b_blocknr; __entry->b_size = mpd->b_size; @@ -377,18 +402,14 @@ TRACE_EVENT(ext4_da_write_pages, __entry->first_page = mpd->first_page; __entry->io_done = mpd->io_done; __entry->pages_written = mpd->pages_written; - __entry->sync_mode = mpd->wbc->sync_mode; ), - TP_printk("dev %d,%d ino %lu b_blocknr %llu b_size %u b_state 0x%04x " - "first_page %lu io_done %d pages_written %d sync_mode %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + TP_printk("dev %d,%d ino %lu b_blocknr %llu b_size %u b_state 0x%04x first_page %lu io_done %d pages_written %d", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->b_blocknr, __entry->b_size, __entry->b_state, __entry->first_page, - __entry->io_done, __entry->pages_written, - __entry->sync_mode - ) + __entry->io_done, __entry->pages_written) ); TRACE_EVENT(ext4_da_writepages_result, @@ -398,100 +419,35 @@ TRACE_EVENT(ext4_da_writepages_result, TP_ARGS(inode, wbc, ret, pages_written), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( int, ret ) __field( int, pages_written ) __field( long, pages_skipped ) - __field( int, sync_mode ) __field( char, more_io ) __field( pgoff_t, writeback_index ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->ret = ret; __entry->pages_written = pages_written; __entry->pages_skipped = wbc->pages_skipped; - __entry->sync_mode = wbc->sync_mode; __entry->more_io = wbc->more_io; __entry->writeback_index = inode->i_mapping->writeback_index; ), - TP_printk("dev %d,%d ino %lu ret %d pages_written %d pages_skipped %ld " - " more_io %d sync_mode %d writeback_index %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), + TP_printk("dev %d,%d ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->ret, __entry->pages_written, __entry->pages_skipped, - __entry->more_io, __entry->sync_mode, + __entry->more_io, (unsigned long) __entry->writeback_index) ); -DECLARE_EVENT_CLASS(ext4__page_op, - TP_PROTO(struct page *page), - - TP_ARGS(page), - - TP_STRUCT__entry( - __field( pgoff_t, index ) - __field( ino_t, ino ) - __field( dev_t, dev ) - - ), - - TP_fast_assign( - __entry->index = page->index; - __entry->ino = page->mapping->host->i_ino; - __entry->dev = page->mapping->host->i_sb->s_dev; - ), - - TP_printk("dev %d,%d ino %lu page_index %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->index) -); - -DEFINE_EVENT(ext4__page_op, ext4_readpage, - - TP_PROTO(struct page *page), - - TP_ARGS(page) -); - -DEFINE_EVENT(ext4__page_op, ext4_releasepage, - - TP_PROTO(struct page *page), - - TP_ARGS(page) -); - -TRACE_EVENT(ext4_invalidatepage, - TP_PROTO(struct page *page, unsigned long offset), - - TP_ARGS(page, offset), - - TP_STRUCT__entry( - __field( pgoff_t, index ) - __field( unsigned long, offset ) - __field( ino_t, ino ) - __field( dev_t, dev ) - - ), - - TP_fast_assign( - __entry->index = page->index; - __entry->offset = offset; - __entry->ino = page->mapping->host->i_ino; - __entry->dev = page->mapping->host->i_sb->s_dev; - ), - - TP_printk("dev %d,%d ino %lu page_index %lu offset %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->index, __entry->offset) -); - TRACE_EVENT(ext4_discard_blocks, TP_PROTO(struct super_block *sb, unsigned long long blk, unsigned long long count), @@ -499,20 +455,22 @@ TRACE_EVENT(ext4_discard_blocks, TP_ARGS(sb, blk, count), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( __u64, blk ) __field( __u64, count ) ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->blk = blk; __entry->count = count; ), TP_printk("dev %d,%d blk %llu count %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, __entry->blk, __entry->count) ); @@ -523,7 +481,8 @@ DECLARE_EVENT_CLASS(ext4__mb_new_pa, TP_ARGS(ac, pa), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u64, pa_pstart ) __field( __u32, pa_len ) @@ -532,7 +491,8 @@ DECLARE_EVENT_CLASS(ext4__mb_new_pa, ), TP_fast_assign( - __entry->dev = ac->ac_sb->s_dev; + __entry->dev_major = MAJOR(ac->ac_sb->s_dev); + __entry->dev_minor = MINOR(ac->ac_sb->s_dev); __entry->ino = ac->ac_inode->i_ino; __entry->pa_pstart = pa->pa_pstart; __entry->pa_len = pa->pa_len; @@ -540,9 +500,9 @@ DECLARE_EVENT_CLASS(ext4__mb_new_pa, ), TP_printk("dev %d,%d ino %lu pstart %llu len %u lstart %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->pa_pstart, __entry->pa_len, __entry->pa_lstart) + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->pa_pstart, + __entry->pa_len, __entry->pa_lstart) ); DEFINE_EVENT(ext4__mb_new_pa, ext4_mb_new_inode_pa, @@ -570,7 +530,8 @@ TRACE_EVENT(ext4_mb_release_inode_pa, TP_ARGS(sb, inode, pa, block, count), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u64, block ) __field( __u32, count ) @@ -578,16 +539,16 @@ TRACE_EVENT(ext4_mb_release_inode_pa, ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->ino = inode->i_ino; __entry->block = block; __entry->count = count; ), TP_printk("dev %d,%d ino %lu block %llu count %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->block, __entry->count) + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->block, __entry->count) ); TRACE_EVENT(ext4_mb_release_group_pa, @@ -597,20 +558,22 @@ TRACE_EVENT(ext4_mb_release_group_pa, TP_ARGS(sb, pa), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( __u64, pa_pstart ) __field( __u32, pa_len ) ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->pa_pstart = pa->pa_pstart; __entry->pa_len = pa->pa_len; ), TP_printk("dev %d,%d pstart %llu len %u", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, __entry->pa_pstart, __entry->pa_len) ); @@ -620,18 +583,20 @@ TRACE_EVENT(ext4_discard_preallocations, TP_ARGS(inode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; ), TP_printk("dev %d,%d ino %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino) ); @@ -641,19 +606,20 @@ TRACE_EVENT(ext4_mb_discard_preallocations, TP_ARGS(sb, needed), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( int, needed ) ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->needed = needed; ), TP_printk("dev %d,%d needed %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->needed) + __entry->dev_major, __entry->dev_minor, __entry->needed) ); TRACE_EVENT(ext4_request_blocks, @@ -662,7 +628,8 @@ TRACE_EVENT(ext4_request_blocks, TP_ARGS(ar), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( unsigned int, flags ) __field( unsigned int, len ) @@ -675,7 +642,8 @@ TRACE_EVENT(ext4_request_blocks, ), TP_fast_assign( - __entry->dev = ar->inode->i_sb->s_dev; + __entry->dev_major = MAJOR(ar->inode->i_sb->s_dev); + __entry->dev_minor = MINOR(ar->inode->i_sb->s_dev); __entry->ino = ar->inode->i_ino; __entry->flags = ar->flags; __entry->len = ar->len; @@ -687,9 +655,8 @@ TRACE_EVENT(ext4_request_blocks, __entry->pright = ar->pright; ), - TP_printk("dev %d,%d ino %lu flags %u len %u lblk %llu goal %llu " - "lleft %llu lright %llu pleft %llu pright %llu ", - MAJOR(__entry->dev), MINOR(__entry->dev), + TP_printk("dev %d,%d ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->flags, __entry->len, (unsigned long long) __entry->logical, @@ -706,7 +673,8 @@ TRACE_EVENT(ext4_allocate_blocks, TP_ARGS(ar, block), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u64, block ) __field( unsigned int, flags ) @@ -720,7 +688,8 @@ TRACE_EVENT(ext4_allocate_blocks, ), TP_fast_assign( - __entry->dev = ar->inode->i_sb->s_dev; + __entry->dev_major = MAJOR(ar->inode->i_sb->s_dev); + __entry->dev_minor = MINOR(ar->inode->i_sb->s_dev); __entry->ino = ar->inode->i_ino; __entry->block = block; __entry->flags = ar->flags; @@ -733,11 +702,10 @@ TRACE_EVENT(ext4_allocate_blocks, __entry->pright = ar->pright; ), - TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %llu " - "goal %llu lleft %llu lright %llu pleft %llu pright %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->flags, __entry->len, __entry->block, + TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->flags, + __entry->len, __entry->block, (unsigned long long) __entry->logical, (unsigned long long) __entry->goal, (unsigned long long) __entry->lleft, @@ -753,7 +721,8 @@ TRACE_EVENT(ext4_free_blocks, TP_ARGS(inode, block, count, flags), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( __u64, block ) @@ -762,7 +731,8 @@ TRACE_EVENT(ext4_free_blocks, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->block = block; @@ -771,19 +741,20 @@ TRACE_EVENT(ext4_free_blocks, ), TP_printk("dev %d,%d ino %lu mode 0%o block %llu count %lu flags %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->mode, __entry->block, __entry->count, __entry->flags) ); -TRACE_EVENT(ext4_sync_file_enter, +TRACE_EVENT(ext4_sync_file, TP_PROTO(struct file *file, int datasync), TP_ARGS(file, datasync), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( ino_t, parent ) __field( int, datasync ) @@ -792,60 +763,39 @@ TRACE_EVENT(ext4_sync_file_enter, TP_fast_assign( struct dentry *dentry = file->f_path.dentry; - __entry->dev = dentry->d_inode->i_sb->s_dev; + __entry->dev_major = MAJOR(dentry->d_inode->i_sb->s_dev); + __entry->dev_minor = MINOR(dentry->d_inode->i_sb->s_dev); __entry->ino = dentry->d_inode->i_ino; __entry->datasync = datasync; __entry->parent = dentry->d_parent->d_inode->i_ino; ), TP_printk("dev %d,%d ino %ld parent %ld datasync %d ", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, (unsigned long) __entry->parent, __entry->datasync) ); -TRACE_EVENT(ext4_sync_file_exit, - TP_PROTO(struct inode *inode, int ret), - - TP_ARGS(inode, ret), - - TP_STRUCT__entry( - __field( int, ret ) - __field( ino_t, ino ) - __field( dev_t, dev ) - ), - - TP_fast_assign( - __entry->ret = ret; - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - ), - - TP_printk("dev %d,%d ino %ld ret %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->ret) -); - TRACE_EVENT(ext4_sync_fs, TP_PROTO(struct super_block *sb, int wait), TP_ARGS(sb, wait), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( int, wait ) ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->wait = wait; ), - TP_printk("dev %d,%d wait %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->wait) + TP_printk("dev %d,%d wait %d", __entry->dev_major, + __entry->dev_minor, __entry->wait) ); TRACE_EVENT(ext4_alloc_da_blocks, @@ -854,21 +804,23 @@ TRACE_EVENT(ext4_alloc_da_blocks, TP_ARGS(inode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( unsigned int, data_blocks ) __field( unsigned int, meta_blocks ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->data_blocks = EXT4_I(inode)->i_reserved_data_blocks; __entry->meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks; ), TP_printk("dev %d,%d ino %lu data_blocks %u meta_blocks %u", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->data_blocks, __entry->meta_blocks) ); @@ -879,7 +831,8 @@ TRACE_EVENT(ext4_mballoc_alloc, TP_ARGS(ac), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u16, found ) __field( __u16, groups ) @@ -902,7 +855,8 @@ TRACE_EVENT(ext4_mballoc_alloc, ), TP_fast_assign( - __entry->dev = ac->ac_inode->i_sb->s_dev; + __entry->dev_major = MAJOR(ac->ac_inode->i_sb->s_dev); + __entry->dev_minor = MINOR(ac->ac_inode->i_sb->s_dev); __entry->ino = ac->ac_inode->i_ino; __entry->found = ac->ac_found; __entry->flags = ac->ac_flags; @@ -927,7 +881,7 @@ TRACE_EVENT(ext4_mballoc_alloc, TP_printk("dev %d,%d inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u " "result %u/%d/%u@%u blks %u grps %u cr %u flags 0x%04x " "tail %u broken %u", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->orig_group, __entry->orig_start, __entry->orig_len, __entry->orig_logical, @@ -946,7 +900,8 @@ TRACE_EVENT(ext4_mballoc_prealloc, TP_ARGS(ac), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( __u32, orig_logical ) __field( int, orig_start ) @@ -959,7 +914,8 @@ TRACE_EVENT(ext4_mballoc_prealloc, ), TP_fast_assign( - __entry->dev = ac->ac_inode->i_sb->s_dev; + __entry->dev_major = MAJOR(ac->ac_inode->i_sb->s_dev); + __entry->dev_minor = MINOR(ac->ac_inode->i_sb->s_dev); __entry->ino = ac->ac_inode->i_ino; __entry->orig_logical = ac->ac_o_ex.fe_logical; __entry->orig_start = ac->ac_o_ex.fe_start; @@ -972,7 +928,7 @@ TRACE_EVENT(ext4_mballoc_prealloc, ), TP_printk("dev %d,%d inode %lu orig %u/%d/%u@%u result %u/%d/%u@%u", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->orig_group, __entry->orig_start, __entry->orig_len, __entry->orig_logical, @@ -990,7 +946,8 @@ DECLARE_EVENT_CLASS(ext4__mballoc, TP_ARGS(sb, inode, group, start, len), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( int, result_start ) __field( __u32, result_group ) @@ -998,7 +955,8 @@ DECLARE_EVENT_CLASS(ext4__mballoc, ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->ino = inode ? inode->i_ino : 0; __entry->result_start = start; __entry->result_group = group; @@ -1006,7 +964,7 @@ DECLARE_EVENT_CLASS(ext4__mballoc, ), TP_printk("dev %d,%d inode %lu extent %u/%d/%u ", - MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->result_group, __entry->result_start, __entry->result_len) @@ -1040,7 +998,8 @@ TRACE_EVENT(ext4_forget, TP_ARGS(inode, is_metadata, block), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( int, is_metadata ) @@ -1048,7 +1007,8 @@ TRACE_EVENT(ext4_forget, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->is_metadata = is_metadata; @@ -1056,9 +1016,9 @@ TRACE_EVENT(ext4_forget, ), TP_printk("dev %d,%d ino %lu mode 0%o is_metadata %d block %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->mode, __entry->is_metadata, __entry->block) + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->mode, + __entry->is_metadata, __entry->block) ); TRACE_EVENT(ext4_da_update_reserve_space, @@ -1067,7 +1027,8 @@ TRACE_EVENT(ext4_da_update_reserve_space, TP_ARGS(inode, used_blocks), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( __u64, i_blocks ) @@ -1078,7 +1039,8 @@ TRACE_EVENT(ext4_da_update_reserve_space, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->i_blocks = inode->i_blocks; @@ -1088,12 +1050,10 @@ TRACE_EVENT(ext4_da_update_reserve_space, __entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks; ), - TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu used_blocks %d " - "reserved_data_blocks %d reserved_meta_blocks %d " - "allocated_meta_blocks %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->mode, (unsigned long long) __entry->i_blocks, + TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu used_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->mode, + (unsigned long long) __entry->i_blocks, __entry->used_blocks, __entry->reserved_data_blocks, __entry->reserved_meta_blocks, __entry->allocated_meta_blocks) ); @@ -1104,7 +1064,8 @@ TRACE_EVENT(ext4_da_reserve_space, TP_ARGS(inode, md_needed), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( __u64, i_blocks ) @@ -1114,7 +1075,8 @@ TRACE_EVENT(ext4_da_reserve_space, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->i_blocks = inode->i_blocks; @@ -1123,9 +1085,8 @@ TRACE_EVENT(ext4_da_reserve_space, __entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks; ), - TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu md_needed %d " - "reserved_data_blocks %d reserved_meta_blocks %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu md_needed %d reserved_data_blocks %d reserved_meta_blocks %d", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->mode, (unsigned long long) __entry->i_blocks, __entry->md_needed, __entry->reserved_data_blocks, @@ -1138,7 +1099,8 @@ TRACE_EVENT(ext4_da_release_space, TP_ARGS(inode, freed_blocks), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) __field( umode_t, mode ) __field( __u64, i_blocks ) @@ -1149,7 +1111,8 @@ TRACE_EVENT(ext4_da_release_space, ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; __entry->mode = inode->i_mode; __entry->i_blocks = inode->i_blocks; @@ -1159,10 +1122,8 @@ TRACE_EVENT(ext4_da_release_space, __entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks; ), - TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu freed_blocks %d " - "reserved_data_blocks %d reserved_meta_blocks %d " - "allocated_meta_blocks %d", - MAJOR(__entry->dev), MINOR(__entry->dev), + TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu freed_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d", + __entry->dev_major, __entry->dev_minor, (unsigned long) __entry->ino, __entry->mode, (unsigned long long) __entry->i_blocks, __entry->freed_blocks, __entry->reserved_data_blocks, @@ -1175,19 +1136,20 @@ DECLARE_EVENT_CLASS(ext4__bitmap_load, TP_ARGS(sb, group), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( __u32, group ) ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev_major = MAJOR(sb->s_dev); + __entry->dev_minor = MINOR(sb->s_dev); __entry->group = group; ), TP_printk("dev %d,%d group %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->group) + __entry->dev_major, __entry->dev_minor, __entry->group) ); DEFINE_EVENT(ext4__bitmap_load, ext4_mb_bitmap_load, @@ -1204,349 +1166,6 @@ DEFINE_EVENT(ext4__bitmap_load, ext4_mb_buddy_bitmap_load, TP_ARGS(sb, group) ); -DEFINE_EVENT(ext4__bitmap_load, ext4_read_block_bitmap_load, - - TP_PROTO(struct super_block *sb, unsigned long group), - - TP_ARGS(sb, group) -); - -DEFINE_EVENT(ext4__bitmap_load, ext4_load_inode_bitmap, - - TP_PROTO(struct super_block *sb, unsigned long group), - - TP_ARGS(sb, group) -); - -TRACE_EVENT(ext4_direct_IO_enter, - TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw), - - TP_ARGS(inode, offset, len, rw), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( loff_t, pos ) - __field( unsigned long, len ) - __field( int, rw ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->pos = offset; - __entry->len = len; - __entry->rw = rw; - ), - - TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->len, __entry->rw) -); - -TRACE_EVENT(ext4_direct_IO_exit, - TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw, int ret), - - TP_ARGS(inode, offset, len, rw, ret), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( loff_t, pos ) - __field( unsigned long, len ) - __field( int, rw ) - __field( int, ret ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->pos = offset; - __entry->len = len; - __entry->rw = rw; - __entry->ret = ret; - ), - - TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d ret %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->len, - __entry->rw, __entry->ret) -); - -TRACE_EVENT(ext4_fallocate_enter, - TP_PROTO(struct inode *inode, loff_t offset, loff_t len, int mode), - - TP_ARGS(inode, offset, len, mode), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( loff_t, pos ) - __field( loff_t, len ) - __field( int, mode ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->pos = offset; - __entry->len = len; - __entry->mode = mode; - ), - - TP_printk("dev %d,%d ino %ld pos %llu len %llu mode %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, - (unsigned long long) __entry->len, __entry->mode) -); - -TRACE_EVENT(ext4_fallocate_exit, - TP_PROTO(struct inode *inode, loff_t offset, unsigned int max_blocks, int ret), - - TP_ARGS(inode, offset, max_blocks, ret), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( loff_t, pos ) - __field( unsigned, blocks ) - __field( int, ret ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->pos = offset; - __entry->blocks = max_blocks; - __entry->ret = ret; - ), - - TP_printk("dev %d,%d ino %ld pos %llu blocks %d ret %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->blocks, - __entry->ret) -); - -TRACE_EVENT(ext4_unlink_enter, - TP_PROTO(struct inode *parent, struct dentry *dentry), - - TP_ARGS(parent, dentry), - - TP_STRUCT__entry( - __field( ino_t, parent ) - __field( ino_t, ino ) - __field( loff_t, size ) - __field( dev_t, dev ) - ), - - TP_fast_assign( - __entry->parent = parent->i_ino; - __entry->ino = dentry->d_inode->i_ino; - __entry->size = dentry->d_inode->i_size; - __entry->dev = dentry->d_inode->i_sb->s_dev; - ), - - TP_printk("dev %d,%d ino %ld size %lld parent %ld", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, __entry->size, - (unsigned long) __entry->parent) -); - -TRACE_EVENT(ext4_unlink_exit, - TP_PROTO(struct dentry *dentry, int ret), - - TP_ARGS(dentry, ret), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( int, ret ) - ), - - TP_fast_assign( - __entry->ino = dentry->d_inode->i_ino; - __entry->dev = dentry->d_inode->i_sb->s_dev; - __entry->ret = ret; - ), - - TP_printk("dev %d,%d ino %ld ret %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->ret) -); - -DECLARE_EVENT_CLASS(ext4__truncate, - TP_PROTO(struct inode *inode), - - TP_ARGS(inode), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( blkcnt_t, blocks ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->blocks = inode->i_blocks; - ), - - TP_printk("dev %d,%d ino %lu blocks %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, (unsigned long) __entry->blocks) -); - -DEFINE_EVENT(ext4__truncate, ext4_truncate_enter, - - TP_PROTO(struct inode *inode), - - TP_ARGS(inode) -); - -DEFINE_EVENT(ext4__truncate, ext4_truncate_exit, - - TP_PROTO(struct inode *inode), - - TP_ARGS(inode) -); - -DECLARE_EVENT_CLASS(ext4__map_blocks_enter, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - unsigned len, unsigned flags), - - TP_ARGS(inode, lblk, len, flags), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( ext4_lblk_t, lblk ) - __field( unsigned, len ) - __field( unsigned, flags ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->lblk = lblk; - __entry->len = len; - __entry->flags = flags; - ), - - TP_printk("dev %d,%d ino %lu lblk %u len %u flags %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned) __entry->lblk, __entry->len, __entry->flags) -); - -DEFINE_EVENT(ext4__map_blocks_enter, ext4_ext_map_blocks_enter, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - unsigned len, unsigned flags), - - TP_ARGS(inode, lblk, len, flags) -); - -DEFINE_EVENT(ext4__map_blocks_enter, ext4_ind_map_blocks_enter, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - unsigned len, unsigned flags), - - TP_ARGS(inode, lblk, len, flags) -); - -DECLARE_EVENT_CLASS(ext4__map_blocks_exit, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - ext4_fsblk_t pblk, unsigned len, int ret), - - TP_ARGS(inode, lblk, pblk, len, ret), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( ext4_lblk_t, lblk ) - __field( ext4_fsblk_t, pblk ) - __field( unsigned, len ) - __field( int, ret ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->lblk = lblk; - __entry->pblk = pblk; - __entry->len = len; - __entry->ret = ret; - ), - - TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u ret %d", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned) __entry->lblk, (unsigned long long) __entry->pblk, - __entry->len, __entry->ret) -); - -DEFINE_EVENT(ext4__map_blocks_exit, ext4_ext_map_blocks_exit, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - ext4_fsblk_t pblk, unsigned len, int ret), - - TP_ARGS(inode, lblk, pblk, len, ret) -); - -DEFINE_EVENT(ext4__map_blocks_exit, ext4_ind_map_blocks_exit, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - ext4_fsblk_t pblk, unsigned len, int ret), - - TP_ARGS(inode, lblk, pblk, len, ret) -); - -TRACE_EVENT(ext4_ext_load_extent, - TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk), - - TP_ARGS(inode, lblk, pblk), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - __field( ext4_lblk_t, lblk ) - __field( ext4_fsblk_t, pblk ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - __entry->lblk = lblk; - __entry->pblk = pblk; - ), - - TP_printk("dev %d,%d ino %lu lblk %u pblk %llu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned) __entry->lblk, (unsigned long long) __entry->pblk) -); - -TRACE_EVENT(ext4_load_inode, - TP_PROTO(struct inode *inode), - - TP_ARGS(inode), - - TP_STRUCT__entry( - __field( ino_t, ino ) - __field( dev_t, dev ) - ), - - TP_fast_assign( - __entry->ino = inode->i_ino; - __entry->dev = inode->i_sb->s_dev; - ), - - TP_printk("dev %d,%d ino %ld", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino) -); - #endif /* _TRACE_EXT4_H */ /* This part must be outside protection */ diff --git a/trunk/include/trace/events/jbd2.h b/trunk/include/trace/events/jbd2.h index bf16545cc977..7447ea9305b5 100644 --- a/trunk/include/trace/events/jbd2.h +++ b/trunk/include/trace/events/jbd2.h @@ -17,17 +17,19 @@ TRACE_EVENT(jbd2_checkpoint, TP_ARGS(journal, result), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( int, result ) ), TP_fast_assign( - __entry->dev = journal->j_fs_dev->bd_dev; + __entry->dev_major = MAJOR(journal->j_fs_dev->bd_dev); + __entry->dev_minor = MINOR(journal->j_fs_dev->bd_dev); __entry->result = result; ), - TP_printk("dev %s result %d", - jbd2_dev_to_name(__entry->dev), __entry->result) + TP_printk("dev %d,%d result %d", + __entry->dev_major, __entry->dev_minor, __entry->result) ); DECLARE_EVENT_CLASS(jbd2_commit, @@ -37,20 +39,22 @@ DECLARE_EVENT_CLASS(jbd2_commit, TP_ARGS(journal, commit_transaction), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( char, sync_commit ) __field( int, transaction ) ), TP_fast_assign( - __entry->dev = journal->j_fs_dev->bd_dev; + __entry->dev_major = MAJOR(journal->j_fs_dev->bd_dev); + __entry->dev_minor = MINOR(journal->j_fs_dev->bd_dev); __entry->sync_commit = commit_transaction->t_synchronous_commit; __entry->transaction = commit_transaction->t_tid; ), - TP_printk("dev %s transaction %d sync %d", - jbd2_dev_to_name(__entry->dev), __entry->transaction, - __entry->sync_commit) + TP_printk("dev %d,%d transaction %d sync %d", + __entry->dev_major, __entry->dev_minor, + __entry->transaction, __entry->sync_commit) ); DEFINE_EVENT(jbd2_commit, jbd2_start_commit, @@ -87,22 +91,24 @@ TRACE_EVENT(jbd2_end_commit, TP_ARGS(journal, commit_transaction), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( char, sync_commit ) __field( int, transaction ) __field( int, head ) ), TP_fast_assign( - __entry->dev = journal->j_fs_dev->bd_dev; + __entry->dev_major = MAJOR(journal->j_fs_dev->bd_dev); + __entry->dev_minor = MINOR(journal->j_fs_dev->bd_dev); __entry->sync_commit = commit_transaction->t_synchronous_commit; __entry->transaction = commit_transaction->t_tid; __entry->head = journal->j_tail_sequence; ), - TP_printk("dev %s transaction %d sync %d head %d", - jbd2_dev_to_name(__entry->dev), __entry->transaction, - __entry->sync_commit, __entry->head) + TP_printk("dev %d,%d transaction %d sync %d head %d", + __entry->dev_major, __entry->dev_minor, + __entry->transaction, __entry->sync_commit, __entry->head) ); TRACE_EVENT(jbd2_submit_inode_data, @@ -111,17 +117,20 @@ TRACE_EVENT(jbd2_submit_inode_data, TP_ARGS(inode), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( ino_t, ino ) ), TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); __entry->ino = inode->i_ino; ), - TP_printk("dev %s ino %lu", - jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino) + TP_printk("dev %d,%d ino %lu", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino) ); TRACE_EVENT(jbd2_run_stats, @@ -131,7 +140,8 @@ TRACE_EVENT(jbd2_run_stats, TP_ARGS(dev, tid, stats), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( unsigned long, tid ) __field( unsigned long, wait ) __field( unsigned long, running ) @@ -144,7 +154,8 @@ TRACE_EVENT(jbd2_run_stats, ), TP_fast_assign( - __entry->dev = dev; + __entry->dev_major = MAJOR(dev); + __entry->dev_minor = MINOR(dev); __entry->tid = tid; __entry->wait = stats->rs_wait; __entry->running = stats->rs_running; @@ -156,9 +167,9 @@ TRACE_EVENT(jbd2_run_stats, __entry->blocks_logged = stats->rs_blocks_logged; ), - TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u " + TP_printk("dev %d,%d tid %lu wait %u running %u locked %u flushing %u " "logging %u handle_count %u blocks %u blocks_logged %u", - jbd2_dev_to_name(__entry->dev), __entry->tid, + __entry->dev_major, __entry->dev_minor, __entry->tid, jiffies_to_msecs(__entry->wait), jiffies_to_msecs(__entry->running), jiffies_to_msecs(__entry->locked), @@ -175,7 +186,8 @@ TRACE_EVENT(jbd2_checkpoint_stats, TP_ARGS(dev, tid, stats), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( unsigned long, tid ) __field( unsigned long, chp_time ) __field( __u32, forced_to_close ) @@ -184,7 +196,8 @@ TRACE_EVENT(jbd2_checkpoint_stats, ), TP_fast_assign( - __entry->dev = dev; + __entry->dev_major = MAJOR(dev); + __entry->dev_minor = MINOR(dev); __entry->tid = tid; __entry->chp_time = stats->cs_chp_time; __entry->forced_to_close= stats->cs_forced_to_close; @@ -192,9 +205,9 @@ TRACE_EVENT(jbd2_checkpoint_stats, __entry->dropped = stats->cs_dropped; ), - TP_printk("dev %s tid %lu chp_time %u forced_to_close %u " + TP_printk("dev %d,%d tid %lu chp_time %u forced_to_close %u " "written %u dropped %u", - jbd2_dev_to_name(__entry->dev), __entry->tid, + __entry->dev_major, __entry->dev_minor, __entry->tid, jiffies_to_msecs(__entry->chp_time), __entry->forced_to_close, __entry->written, __entry->dropped) ); @@ -207,7 +220,8 @@ TRACE_EVENT(jbd2_cleanup_journal_tail, TP_ARGS(journal, first_tid, block_nr, freed), TP_STRUCT__entry( - __field( dev_t, dev ) + __field( int, dev_major ) + __field( int, dev_minor ) __field( tid_t, tail_sequence ) __field( tid_t, first_tid ) __field(unsigned long, block_nr ) @@ -215,16 +229,18 @@ TRACE_EVENT(jbd2_cleanup_journal_tail, ), TP_fast_assign( - __entry->dev = journal->j_fs_dev->bd_dev; + __entry->dev_major = MAJOR(journal->j_fs_dev->bd_dev); + __entry->dev_minor = MINOR(journal->j_fs_dev->bd_dev); __entry->tail_sequence = journal->j_tail_sequence; __entry->first_tid = first_tid; __entry->block_nr = block_nr; __entry->freed = freed; ), - TP_printk("dev %s from %u to %u offset %lu freed %lu", - jbd2_dev_to_name(__entry->dev), __entry->tail_sequence, - __entry->first_tid, __entry->block_nr, __entry->freed) + TP_printk("dev %d,%d from %u to %u offset %lu freed %lu", + __entry->dev_major, __entry->dev_minor, + __entry->tail_sequence, __entry->first_tid, + __entry->block_nr, __entry->freed) ); #endif /* _TRACE_JBD2_H */ diff --git a/trunk/ipc/namespace.c b/trunk/ipc/namespace.c index 8054c8e5faf1..3c3e5223e7e5 100644 --- a/trunk/ipc/namespace.c +++ b/trunk/ipc/namespace.c @@ -104,6 +104,7 @@ static void free_ipc_ns(struct ipc_namespace *ns) sem_exit_ns(ns); msg_exit_ns(ns); shm_exit_ns(ns); + kfree(ns); atomic_dec(&nr_ipc_ns); /* @@ -112,7 +113,6 @@ static void free_ipc_ns(struct ipc_namespace *ns) */ ipcns_notify(IPCNS_REMOVED); put_user_ns(ns->user_ns); - kfree(ns); } /* diff --git a/trunk/net/sunrpc/auth_gss/gss_mech_switch.c b/trunk/net/sunrpc/auth_gss/gss_mech_switch.c index e3c36a274412..8b4061049d76 100644 --- a/trunk/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/trunk/net/sunrpc/auth_gss/gss_mech_switch.c @@ -160,28 +160,6 @@ gss_mech_get_by_name(const char *name) EXPORT_SYMBOL_GPL(gss_mech_get_by_name); -struct gss_api_mech * -gss_mech_get_by_OID(struct xdr_netobj *obj) -{ - struct gss_api_mech *pos, *gm = NULL; - - spin_lock(®istered_mechs_lock); - list_for_each_entry(pos, ®istered_mechs, gm_list) { - if (obj->len == pos->gm_oid.len) { - if (0 == memcmp(obj->data, pos->gm_oid.data, obj->len)) { - if (try_module_get(pos->gm_owner)) - gm = pos; - break; - } - } - } - spin_unlock(®istered_mechs_lock); - return gm; - -} - -EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); - static inline int mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) { @@ -215,22 +193,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); -int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) -{ - struct gss_api_mech *pos = NULL; - int i = 0; - - spin_lock(®istered_mechs_lock); - list_for_each_entry(pos, ®istered_mechs, gm_list) { - array_ptr[i] = pos->gm_pfs->pseudoflavor; - i++; - } - spin_unlock(®istered_mechs_lock); - return i; -} - -EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors); - u32 gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) { diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index 1e336a06d3e6..be96d429b475 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -710,8 +710,6 @@ static void xs_reset_transport(struct sock_xprt *transport) if (sk == NULL) return; - transport->srcport = 0; - write_lock_bh(&sk->sk_callback_lock); transport->inet = NULL; transport->sock = NULL;