From 026c215c94b8a1dd5017c4fd6cdcbc8fa94527f9 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sun, 16 Sep 2007 20:53:24 +1000 Subject: [PATCH] --- yaml --- r: 70888 b: refs/heads/master c: d4697af4f3cc63f9f4d62022d79021138ecc0499 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/CREDITS | 10 +- trunk/Documentation/DMA-mapping.txt | 4 +- trunk/Documentation/HOWTO | 2 +- trunk/Documentation/block/00-INDEX | 20 - trunk/Documentation/block/as-iosched.txt | 21 +- trunk/Documentation/block/biodoc.txt | 4 +- .../Documentation/block/deadline-iosched.txt | 25 +- trunk/Documentation/block/ioprio.txt | 2 +- trunk/Documentation/block/request.txt | 2 +- trunk/Documentation/block/switching-sched.txt | 21 - trunk/Documentation/cachetlb.txt | 6 + trunk/Documentation/cpusets.txt | 24 +- trunk/Documentation/fb/00-INDEX | 46 +- trunk/Documentation/fb/uvesafb.txt | 188 -- trunk/Documentation/filesystems/Locking | 9 +- trunk/Documentation/filesystems/vfs.txt | 51 +- trunk/Documentation/ide.txt | 6 +- trunk/Documentation/kbuild/makefiles.txt | 62 +- trunk/Documentation/kernel-parameters.txt | 10 - .../sound/alsa/ALSA-Configuration.txt | 115 +- trunk/Documentation/sound/alsa/CMIPCI.txt | 17 +- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 184 +- .../sound/alsa/OSS-Emulation.txt | 7 + trunk/Documentation/sound/alsa/hda_codec.txt | 49 +- trunk/Documentation/sound/alsa/powersave.txt | 41 - trunk/Documentation/spi/spi-summary | 25 +- trunk/Documentation/spi/spidev_test.c | 6 +- trunk/Documentation/vm/numa_memory_policy.txt | 33 +- trunk/Documentation/x86_64/mm.txt | 1 - trunk/MAINTAINERS | 10 +- trunk/Makefile | 57 +- trunk/arch/alpha/Makefile | 81 +- trunk/arch/alpha/kernel/Makefile | 2 +- trunk/arch/alpha/kernel/entry.S | 9 + trunk/arch/alpha/kernel/ptrace.c | 46 +- trunk/arch/alpha/kernel/vmlinux.lds.S | 260 +- trunk/arch/alpha/lib/Makefile | 2 +- trunk/arch/alpha/mm/fault.c | 2 +- trunk/arch/arm/Makefile | 14 +- trunk/arch/arm/boot/compressed/Makefile | 2 +- trunk/arch/arm/kernel/ptrace.c | 4 + trunk/arch/arm/mach-s3c2410/mach-amlm5900.c | 54 +- trunk/arch/arm/mach-s3c2410/mach-bast.c | 83 +- trunk/arch/arm/mach-s3c2410/mach-h1940.c | 56 +- trunk/arch/arm/mach-s3c2410/mach-qt2410.c | 219 +- trunk/arch/arm/mach-s3c2440/mach-rx3715.c | 72 +- trunk/arch/arm/mach-s3c2440/mach-smdk2440.c | 78 +- trunk/arch/arm/mm/fault.c | 2 +- trunk/arch/arm/vfp/Makefile | 2 +- trunk/arch/avr32/Makefile | 8 +- trunk/arch/avr32/kernel/kprobes.c | 2 - trunk/arch/avr32/kernel/ptrace.c | 5 + trunk/arch/avr32/mm/fault.c | 2 +- trunk/arch/blackfin/Kconfig | 2 +- trunk/arch/blackfin/Makefile | 4 +- trunk/arch/blackfin/kernel/ptrace.c | 6 + trunk/arch/cris/Makefile | 10 +- trunk/arch/cris/arch-v10/kernel/ptrace.c | 4 + trunk/arch/cris/arch-v10/kernel/time.c | 8 +- trunk/arch/cris/arch-v32/kernel/ptrace.c | 4 + trunk/arch/cris/arch-v32/kernel/smp.c | 8 +- trunk/arch/cris/mm/fault.c | 2 +- trunk/arch/frv/Makefile | 32 +- trunk/arch/frv/kernel/time.c | 5 +- trunk/arch/frv/mm/fault.c | 2 +- trunk/arch/h8300/Makefile | 14 +- trunk/arch/h8300/lib/Makefile | 3 + trunk/arch/i386/Makefile | 16 +- trunk/arch/ia64/Kconfig | 9 - trunk/arch/ia64/Makefile | 4 +- trunk/arch/ia64/hp/common/sba_iommu.c | 14 +- trunk/arch/ia64/hp/sim/simscsi.c | 1 - trunk/arch/ia64/kernel/gate.lds.S | 135 +- trunk/arch/ia64/kernel/kprobes.c | 2 - trunk/arch/ia64/kernel/setup.c | 14 +- trunk/arch/ia64/kernel/smpboot.c | 18 +- trunk/arch/ia64/kernel/uncached.c | 4 +- trunk/arch/ia64/mm/discontig.c | 8 - trunk/arch/ia64/mm/fault.c | 2 +- trunk/arch/ia64/mm/hugetlbpage.c | 4 +- trunk/arch/ia64/mm/init.c | 20 +- trunk/arch/ia64/sn/kernel/Makefile | 2 +- trunk/arch/ia64/sn/kernel/sn2/Makefile | 2 +- trunk/arch/ia64/sn/pci/Makefile | 2 +- trunk/arch/ia64/sn/pci/pci_dma.c | 11 +- trunk/arch/ia64/sn/pci/pcibr/Makefile | 2 +- trunk/arch/m32r/Makefile | 8 +- trunk/arch/m32r/kernel/ptrace.c | 50 +- trunk/arch/m32r/kernel/time.c | 8 +- trunk/arch/m32r/mm/fault.c | 2 +- trunk/arch/m68k/Makefile | 8 +- trunk/arch/m68k/kernel/ptrace.c | 4 + trunk/arch/m68k/mm/fault.c | 2 +- trunk/arch/m68knommu/Makefile | 8 +- trunk/arch/m68knommu/platform/5206/Makefile | 2 +- trunk/arch/m68knommu/platform/5206e/Makefile | 2 +- trunk/arch/m68knommu/platform/520x/Makefile | 2 +- trunk/arch/m68knommu/platform/523x/Makefile | 2 +- trunk/arch/m68knommu/platform/5249/Makefile | 2 +- trunk/arch/m68knommu/platform/5272/Makefile | 2 +- trunk/arch/m68knommu/platform/527x/Makefile | 2 +- trunk/arch/m68knommu/platform/528x/Makefile | 2 +- trunk/arch/m68knommu/platform/5307/Makefile | 2 +- trunk/arch/m68knommu/platform/532x/Makefile | 2 +- trunk/arch/m68knommu/platform/5407/Makefile | 2 +- trunk/arch/mips/Kconfig | 2 - trunk/arch/mips/Makefile | 8 +- trunk/arch/mips/au1000/common/au1xxx_irqmap.c | 2 +- trunk/arch/mips/au1000/common/dbdma.c | 2 +- trunk/arch/mips/au1000/common/irq.c | 662 +++--- trunk/arch/mips/au1000/db1x00/irqmap.c | 2 +- trunk/arch/mips/au1000/mtx-1/irqmap.c | 2 +- trunk/arch/mips/au1000/pb1000/irqmap.c | 2 +- trunk/arch/mips/au1000/pb1100/irqmap.c | 2 +- trunk/arch/mips/au1000/pb1200/irqmap.c | 4 +- trunk/arch/mips/au1000/pb1500/irqmap.c | 2 +- trunk/arch/mips/au1000/pb1550/irqmap.c | 2 +- trunk/arch/mips/au1000/xxs1500/irqmap.c | 2 +- trunk/arch/mips/jmr3927/rbhma3100/setup.c | 2 +- trunk/arch/mips/kernel/Makefile | 2 +- trunk/arch/mips/kernel/ptrace.c | 4 + trunk/arch/mips/kernel/time.c | 2 +- trunk/arch/mips/kernel/traps.c | 21 +- trunk/arch/mips/kernel/vmlinux.lds.S | 15 +- trunk/arch/mips/kernel/vpe.c | 27 +- trunk/arch/mips/lasat/interrupt.c | 8 +- trunk/arch/mips/mipssim/sim_cmdline.c | 5 +- trunk/arch/mips/mm/c-r4k.c | 10 +- trunk/arch/mips/mm/fault.c | 2 +- trunk/arch/mips/mm/init.c | 19 +- trunk/arch/mips/pci/pci-lasat.c | 19 +- trunk/arch/mips/sgi-ip22/Makefile | 2 - trunk/arch/mips/sgi-ip22/ip22-reset.c | 9 +- trunk/arch/mips/sgi-ip32/ip32-irq.c | 162 +- trunk/arch/mips/sgi-ip32/ip32-setup.c | 2 +- .../toshiba_rbtx4927/toshiba_rbtx4927_setup.c | 2 +- trunk/arch/parisc/Makefile | 2 +- trunk/arch/parisc/kernel/ptrace.c | 4 + trunk/arch/parisc/math-emu/Makefile | 2 +- trunk/arch/parisc/mm/fault.c | 2 +- trunk/arch/powerpc/Kconfig | 1 - trunk/arch/powerpc/Kconfig.debug | 6 +- trunk/arch/powerpc/Makefile | 30 +- trunk/arch/powerpc/configs/bamboo_defconfig | 7 +- trunk/arch/powerpc/configs/celleb_defconfig | 7 +- trunk/arch/powerpc/configs/chrp32_defconfig | 7 +- trunk/arch/powerpc/configs/ebony_defconfig | 7 +- trunk/arch/powerpc/configs/g5_defconfig | 7 +- trunk/arch/powerpc/configs/holly_defconfig | 7 +- trunk/arch/powerpc/configs/iseries_defconfig | 7 +- trunk/arch/powerpc/configs/kilauea_defconfig | 7 +- .../powerpc/configs/linkstation_defconfig | 7 +- trunk/arch/powerpc/configs/lite5200_defconfig | 7 +- trunk/arch/powerpc/configs/maple_defconfig | 8 +- .../powerpc/configs/mpc7448_hpc2_defconfig | 5 +- .../powerpc/configs/mpc8272_ads_defconfig | 7 +- .../powerpc/configs/mpc8313_rdb_defconfig | 7 +- .../powerpc/configs/mpc832x_mds_defconfig | 5 +- .../powerpc/configs/mpc832x_rdb_defconfig | 5 +- .../powerpc/configs/mpc834x_itx_defconfig | 5 +- .../powerpc/configs/mpc834x_itxgp_defconfig | 5 +- .../powerpc/configs/mpc834x_mds_defconfig | 5 +- .../powerpc/configs/mpc836x_mds_defconfig | 5 +- .../powerpc/configs/mpc8540_ads_defconfig | 7 +- .../arch/powerpc/configs/mpc8544_ds_defconfig | 7 +- .../powerpc/configs/mpc8560_ads_defconfig | 7 +- .../arch/powerpc/configs/mpc8568mds_defconfig | 7 +- .../arch/powerpc/configs/mpc8572_ds_defconfig | 7 +- .../powerpc/configs/mpc85xx_cds_defconfig | 7 +- .../powerpc/configs/mpc8610_hpcd_defconfig | 7 +- .../powerpc/configs/mpc8641_hpcn_defconfig | 7 +- .../arch/powerpc/configs/mpc866_ads_defconfig | 5 +- trunk/arch/powerpc/configs/pasemi_defconfig | 7 +- trunk/arch/powerpc/configs/pmac32_defconfig | 7 +- trunk/arch/powerpc/configs/ppc64_defconfig | 11 +- trunk/arch/powerpc/configs/pq2fads_defconfig | 7 +- .../arch/powerpc/configs/prpmc2800_defconfig | 5 +- trunk/arch/powerpc/configs/ps3_defconfig | 7 +- trunk/arch/powerpc/configs/pseries_defconfig | 11 +- trunk/arch/powerpc/configs/sequoia_defconfig | 7 +- trunk/arch/powerpc/configs/walnut_defconfig | 7 +- trunk/arch/powerpc/kernel/dma_64.c | 5 +- trunk/arch/powerpc/kernel/entry_64.S | 6 - trunk/arch/powerpc/kernel/ibmebus.c | 274 ++- trunk/arch/powerpc/kernel/iommu.c | 23 +- trunk/arch/powerpc/kernel/kprobes.c | 2 - trunk/arch/powerpc/kernel/of_device.c | 80 - trunk/arch/powerpc/kernel/of_platform.c | 70 +- trunk/arch/powerpc/kernel/ptrace.c | 4 + trunk/arch/powerpc/kernel/setup-common.c | 20 +- trunk/arch/powerpc/kernel/setup_64.c | 16 +- trunk/arch/powerpc/kernel/smp.c | 4 +- trunk/arch/powerpc/kernel/time.c | 2 +- trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S | 219 +- trunk/arch/powerpc/kernel/vdso64/sigtramp.S | 11 +- trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S | 225 +- trunk/arch/powerpc/lib/rheap.c | 15 + trunk/arch/powerpc/math-emu/math.c | 13 +- trunk/arch/powerpc/mm/hash_utils_64.c | 3 +- trunk/arch/powerpc/mm/init_64.c | 68 - trunk/arch/powerpc/mm/mem.c | 45 + trunk/arch/powerpc/mm/slb.c | 3 +- trunk/arch/powerpc/platforms/Kconfig | 2 +- .../arch/powerpc/platforms/cell/cbe_cpufreq.c | 2 +- trunk/arch/powerpc/platforms/iseries/htab.c | 4 +- trunk/arch/powerpc/platforms/iseries/vio.c | 2 +- trunk/arch/powerpc/platforms/ps3/system-bus.c | 7 +- trunk/arch/powerpc/sysdev/fsl_pci.c | 2 +- trunk/arch/ppc/Makefile | 16 +- trunk/arch/ppc/boot/Makefile | 1 + trunk/arch/ppc/mm/fault.c | 2 +- trunk/arch/s390/Makefile | 14 +- trunk/arch/s390/kernel/kprobes.c | 2 - trunk/arch/s390/kernel/ptrace.c | 5 + trunk/arch/s390/mm/fault.c | 2 +- trunk/arch/sh/Makefile | 6 +- trunk/arch/sh/boot/compressed/Makefile | 2 +- trunk/arch/sh/kernel/ptrace.c | 4 + trunk/arch/sh/kernel/vsyscall/vsyscall.lds.S | 77 +- trunk/arch/sh/mm/fault.c | 2 +- trunk/arch/sh/mm/init.c | 6 + trunk/arch/sh64/Makefile | 4 +- trunk/arch/sh64/kernel/ptrace.c | 4 + trunk/arch/sh64/mm/fault.c | 2 +- trunk/arch/sparc/Makefile | 8 +- trunk/arch/sparc/kernel/ioport.c | 25 +- trunk/arch/sparc/mm/fault.c | 2 +- trunk/arch/sparc/mm/io-unit.c | 12 +- trunk/arch/sparc/mm/iommu.c | 10 +- trunk/arch/sparc/mm/sun4c.c | 10 +- trunk/arch/sparc64/Kconfig | 2 +- trunk/arch/sparc64/Makefile | 8 +- trunk/arch/sparc64/kernel/iommu.c | 39 +- trunk/arch/sparc64/kernel/kprobes.c | 2 - trunk/arch/sparc64/kernel/ktlb.S | 16 - trunk/arch/sparc64/kernel/pci_sun4v.c | 32 +- trunk/arch/sparc64/kernel/smp.c | 17 +- trunk/arch/sparc64/mm/fault.c | 2 +- trunk/arch/sparc64/mm/init.c | 57 +- trunk/arch/um/Kconfig | 244 +- trunk/arch/um/Kconfig.char | 141 +- trunk/arch/um/Kconfig.debug | 47 +- trunk/arch/um/Kconfig.i386 | 14 + trunk/arch/um/Kconfig.net | 22 - trunk/arch/um/Kconfig.x86_64 | 14 +- trunk/arch/um/Makefile | 47 +- trunk/arch/um/Makefile-i386 | 12 +- trunk/arch/um/Makefile-os-Linux | 2 +- trunk/arch/um/Makefile-x86_64 | 6 +- trunk/arch/um/defconfig | 11 +- trunk/arch/um/drivers/Makefile | 13 +- trunk/arch/um/drivers/chan_kern.c | 211 +- trunk/arch/um/drivers/chan_user.c | 211 +- trunk/arch/um/drivers/cow_user.c | 133 +- trunk/arch/um/drivers/daemon.h | 20 +- trunk/arch/um/drivers/daemon_kern.c | 34 +- trunk/arch/um/drivers/daemon_user.c | 92 +- trunk/arch/um/drivers/fd.c | 69 +- trunk/arch/um/drivers/harddog_kern.c | 2 +- trunk/arch/um/drivers/harddog_user.c | 58 +- trunk/arch/um/drivers/hostaudio_kern.c | 118 +- trunk/arch/um/drivers/line.c | 237 +- trunk/arch/um/drivers/mcast.h | 16 +- trunk/arch/um/drivers/mcast_kern.c | 56 +- trunk/arch/um/drivers/mcast_user.c | 73 +- trunk/arch/um/drivers/mconsole_kern.c | 289 +-- trunk/arch/um/drivers/mconsole_user.c | 119 +- trunk/arch/um/drivers/mmapper_kern.c | 64 +- trunk/arch/um/drivers/net_kern.c | 278 +-- trunk/arch/um/drivers/net_user.c | 126 +- trunk/arch/um/drivers/null.c | 28 +- trunk/arch/um/drivers/pcap_kern.c | 38 +- trunk/arch/um/drivers/pcap_user.c | 58 +- trunk/arch/um/drivers/port_kern.c | 86 +- trunk/arch/um/drivers/port_user.c | 73 +- trunk/arch/um/drivers/pty.c | 30 +- trunk/arch/um/drivers/slip_kern.c | 38 +- trunk/arch/um/drivers/slip_user.c | 129 +- trunk/arch/um/drivers/slirp_kern.c | 59 +- trunk/arch/um/drivers/slirp_user.c | 74 +- trunk/arch/um/drivers/tty.c | 37 +- trunk/arch/um/drivers/ubd_kern.c | 2 +- trunk/arch/um/drivers/vde.h | 32 - trunk/arch/um/drivers/vde_kern.c | 129 - trunk/arch/um/drivers/vde_user.c | 127 - trunk/arch/um/drivers/xterm.c | 28 +- trunk/arch/um/include/arch.h | 4 +- trunk/arch/um/include/as-layout.h | 27 +- trunk/arch/um/include/choose-mode.h | 38 + trunk/arch/um/include/common-offsets.h | 10 +- trunk/arch/um/include/irq_user.h | 10 +- trunk/arch/um/include/kern_util.h | 30 +- trunk/arch/um/include/mconsole.h | 15 +- trunk/arch/um/include/mem.h | 21 +- trunk/arch/um/include/mode.h | 30 + trunk/arch/um/include/mode_kern.h | 17 + trunk/arch/um/include/net_kern.h | 13 +- trunk/arch/um/include/net_user.h | 4 +- trunk/arch/um/include/os.h | 69 +- trunk/arch/um/include/registers.h | 10 +- trunk/arch/um/include/skas/mmu-skas.h | 23 + trunk/arch/um/include/skas/mode-skas.h | 9 +- trunk/arch/um/include/skas/mode_kern_skas.h | 41 + trunk/arch/um/include/skas/skas.h | 5 +- trunk/arch/um/include/skas/uaccess-skas.h | 21 + .../um/include/sysdep-i386/kernel-offsets.h | 1 + trunk/arch/um/include/sysdep-i386/ptrace.h | 133 +- .../arch/um/include/sysdep-i386/sigcontext.h | 30 +- trunk/arch/um/include/sysdep-i386/stub.h | 14 +- trunk/arch/um/include/sysdep-i386/thread.h | 11 + trunk/arch/um/include/sysdep-x86_64/ptrace.h | 277 ++- .../um/include/sysdep-x86_64/sigcontext.h | 28 +- trunk/arch/um/include/sysdep-x86_64/stub.h | 13 +- trunk/arch/um/include/sysdep-x86_64/thread.h | 10 + trunk/arch/um/include/task.h | 2 +- trunk/arch/um/include/tlb.h | 27 + trunk/arch/um/include/tt/debug.h | 18 + trunk/arch/um/include/tt/mmu-tt.h | 12 + trunk/arch/um/include/tt/mode-tt.h | 23 + trunk/arch/um/include/tt/mode_kern_tt.h | 40 + trunk/arch/um/include/tt/tt.h | 37 + trunk/arch/um/include/tt/uaccess-tt.h | 46 + trunk/arch/um/include/um_mmu.h | 40 +- trunk/arch/um/include/um_uaccess.h | 64 +- trunk/arch/um/include/uml_uaccess.h | 24 + trunk/arch/um/include/user.h | 8 +- trunk/arch/um/kernel/Makefile | 7 +- trunk/arch/um/kernel/dyn.lds.S | 2 + trunk/arch/um/kernel/exec.c | 58 +- trunk/arch/um/kernel/init_task.c | 13 +- trunk/arch/um/kernel/irq.c | 113 +- trunk/arch/um/kernel/ksyms.c | 41 +- trunk/arch/um/kernel/mem.c | 2 +- trunk/arch/um/kernel/physmem.c | 69 +- trunk/arch/um/kernel/process.c | 226 +- trunk/arch/um/kernel/ptrace.c | 141 +- trunk/arch/um/kernel/reboot.c | 57 +- trunk/arch/um/kernel/signal.c | 59 +- trunk/arch/um/kernel/skas/Makefile | 4 +- trunk/arch/um/kernel/skas/clone.c | 6 +- trunk/arch/um/kernel/skas/exec.c | 40 + trunk/arch/um/kernel/skas/mem.c | 22 + trunk/arch/um/kernel/skas/mmu.c | 81 +- trunk/arch/um/kernel/skas/process.c | 187 +- trunk/arch/um/kernel/skas/syscall.c | 21 +- trunk/arch/um/kernel/skas/tlb.c | 164 ++ trunk/arch/um/kernel/skas/uaccess.c | 146 +- trunk/arch/um/kernel/smp.c | 36 +- trunk/arch/um/kernel/syscall.c | 40 +- trunk/arch/um/kernel/time.c | 223 +- trunk/arch/um/kernel/tlb.c | 418 ++-- trunk/arch/um/kernel/trap.c | 129 +- trunk/arch/um/kernel/tt/Makefile | 14 + trunk/arch/um/kernel/tt/exec_kern.c | 84 + trunk/arch/um/kernel/tt/exec_user.c | 56 + trunk/arch/um/kernel/tt/gdb.c | 280 +++ trunk/arch/um/kernel/tt/gdb_kern.c | 40 + trunk/arch/um/kernel/tt/include/mode-tt.h | 34 + trunk/arch/um/kernel/tt/ksyms.c | 29 + trunk/arch/um/kernel/tt/mem.c | 34 + trunk/arch/um/kernel/tt/mem_user.c | 49 + trunk/arch/um/kernel/tt/process_kern.c | 461 ++++ trunk/arch/um/kernel/tt/ptproxy/Makefile | 10 + trunk/arch/um/kernel/tt/ptproxy/proxy.c | 377 +++ trunk/arch/um/kernel/tt/ptproxy/ptproxy.h | 61 + trunk/arch/um/kernel/tt/ptproxy/ptrace.c | 237 ++ trunk/arch/um/kernel/tt/ptproxy/sysdep.c | 70 + trunk/arch/um/kernel/tt/ptproxy/sysdep.h | 25 + trunk/arch/um/kernel/tt/ptproxy/wait.c | 85 + trunk/arch/um/kernel/tt/ptproxy/wait.h | 15 + trunk/arch/um/kernel/tt/syscall_kern.c | 46 + trunk/arch/um/kernel/tt/syscall_user.c | 60 + trunk/arch/um/kernel/tt/tlb.c | 120 + trunk/arch/um/kernel/tt/tracer.c | 461 ++++ trunk/arch/um/kernel/tt/trap_user.c | 70 + trunk/arch/um/kernel/tt/uaccess.c | 73 + trunk/arch/um/kernel/tt/uaccess_user.c | 105 + trunk/arch/um/kernel/uaccess.c | 2 +- trunk/arch/um/kernel/um_arch.c | 217 +- trunk/arch/um/kernel/uml.lds.S | 7 + trunk/arch/um/os-Linux/Makefile | 15 +- trunk/arch/um/os-Linux/aio.c | 122 +- trunk/arch/um/os-Linux/drivers/etap.h | 16 +- .../arch/um/os-Linux/drivers/ethertap_kern.c | 52 +- .../arch/um/os-Linux/drivers/ethertap_user.c | 132 +- trunk/arch/um/os-Linux/drivers/tuntap.h | 13 +- trunk/arch/um/os-Linux/drivers/tuntap_kern.c | 35 +- trunk/arch/um/os-Linux/drivers/tuntap_user.c | 102 +- trunk/arch/um/os-Linux/file.c | 130 +- trunk/arch/um/os-Linux/helper.c | 8 +- trunk/arch/um/os-Linux/irq.c | 6 +- trunk/arch/um/os-Linux/main.c | 120 +- trunk/arch/um/os-Linux/mem.c | 6 +- trunk/arch/um/os-Linux/process.c | 175 +- trunk/arch/um/os-Linux/registers.c | 57 - trunk/arch/um/os-Linux/signal.c | 131 +- trunk/arch/um/os-Linux/skas/mem.c | 109 +- trunk/arch/um/os-Linux/skas/process.c | 316 ++- trunk/arch/um/os-Linux/skas/trap.c | 51 +- trunk/arch/um/os-Linux/start_up.c | 218 +- trunk/arch/um/os-Linux/sys-i386/Makefile | 4 +- trunk/arch/um/os-Linux/sys-i386/registers.c | 129 +- trunk/arch/um/os-Linux/sys-x86_64/Makefile | 4 +- trunk/arch/um/os-Linux/sys-x86_64/registers.c | 75 +- trunk/arch/um/os-Linux/time.c | 111 +- trunk/arch/um/os-Linux/tls.c | 40 + trunk/arch/um/os-Linux/trap.c | 23 +- trunk/arch/um/os-Linux/tt.c | 196 ++ trunk/arch/um/os-Linux/uaccess.c | 2 +- trunk/arch/um/os-Linux/umid.c | 137 +- trunk/arch/um/os-Linux/util.c | 38 - trunk/arch/um/scripts/Makefile.rules | 2 +- trunk/arch/um/sys-i386/Makefile | 14 +- trunk/arch/um/sys-i386/bugs.c | 108 +- trunk/arch/um/sys-i386/fault.c | 10 +- trunk/arch/um/sys-i386/ldt.c | 306 ++- trunk/arch/um/sys-i386/ptrace.c | 368 ++- trunk/arch/um/sys-i386/ptrace_user.c | 100 +- trunk/arch/um/sys-i386/sigcontext.c | 71 + trunk/arch/um/sys-i386/signal.c | 409 ++-- trunk/arch/um/sys-i386/stub.S | 9 +- trunk/arch/um/sys-i386/stub_segv.c | 4 +- trunk/arch/um/sys-i386/tls.c | 101 +- trunk/arch/um/sys-i386/unmap.c | 25 + trunk/arch/um/sys-i386/user-offsets.c | 6 +- trunk/arch/um/sys-ppc/Makefile | 6 +- trunk/arch/um/sys-x86_64/Makefile | 11 +- trunk/arch/um/sys-x86_64/bugs.c | 2 +- trunk/arch/um/sys-x86_64/fault.c | 9 +- trunk/arch/um/sys-x86_64/ptrace.c | 154 +- trunk/arch/um/sys-x86_64/sigcontext.c | 39 + trunk/arch/um/sys-x86_64/signal.c | 297 ++- trunk/arch/um/sys-x86_64/stub.S | 9 +- trunk/arch/um/sys-x86_64/stub_segv.c | 3 +- trunk/arch/um/sys-x86_64/syscalls.c | 108 +- trunk/arch/um/sys-x86_64/tls.c | 4 +- trunk/arch/um/sys-x86_64/unmap.c | 25 + trunk/arch/um/sys-x86_64/user-offsets.c | 9 +- trunk/arch/v850/Makefile | 8 +- trunk/arch/v850/kernel/fpga85e2c.c | 5 +- trunk/arch/v850/kernel/time.c | 11 +- trunk/arch/x86/boot/Makefile | 10 +- trunk/arch/x86/boot/compressed/Makefile_32 | 2 +- trunk/arch/x86/boot/compressed/Makefile_64 | 4 +- .../x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 2 +- .../arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | 2 +- .../arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 10 +- .../x86/kernel/cpu/cpufreq/speedstep-ich.c | 2 +- trunk/arch/x86/kernel/cpu/proc.c | 3 +- trunk/arch/x86/kernel/io_apic_32.c | 4 +- trunk/arch/x86/kernel/kprobes_32.c | 10 +- trunk/arch/x86/kernel/kprobes_64.c | 8 +- trunk/arch/x86/kernel/mce_amd_64.c | 6 +- trunk/arch/x86/kernel/pci-calgary_64.c | 24 +- trunk/arch/x86/kernel/pci-gart_64.c | 65 +- trunk/arch/x86/kernel/pci-nommu_64.c | 5 +- trunk/arch/x86/kernel/process_64.c | 2 +- trunk/arch/x86/kernel/ptrace_32.c | 5 + trunk/arch/x86/kernel/ptrace_64.c | 5 + trunk/arch/x86/kernel/setup_64.c | 3 +- trunk/arch/x86/kernel/smpboot_32.c | 68 +- trunk/arch/x86/kernel/smpboot_64.c | 48 +- trunk/arch/x86/math-emu/Makefile | 3 +- trunk/arch/x86/mm/fault_32.c | 45 +- trunk/arch/x86/mm/fault_64.c | 44 +- trunk/arch/x86/mm/init_32.c | 5 + trunk/arch/x86/mm/init_64.c | 51 +- trunk/arch/x86/oprofile/op_model_p4.c | 2 +- trunk/arch/x86/vdso/Makefile | 4 +- trunk/arch/x86/xen/smp.c | 18 +- trunk/arch/x86_64/Kconfig | 1 - trunk/arch/x86_64/Makefile | 8 +- trunk/arch/xtensa/Makefile | 8 +- trunk/arch/xtensa/boot/Makefile | 5 +- trunk/arch/xtensa/boot/boot-redboot/Makefile | 2 +- trunk/arch/xtensa/kernel/ptrace.c | 4 + trunk/arch/xtensa/mm/fault.c | 2 +- trunk/block/blktrace.c | 2 +- trunk/block/bsg.c | 2 +- trunk/block/elevator.c | 17 +- trunk/block/ll_rw_blk.c | 320 +-- trunk/crypto/digest.c | 2 +- trunk/crypto/scatterwalk.c | 2 +- trunk/crypto/scatterwalk.h | 2 +- trunk/drivers/Kconfig | 2 - trunk/drivers/Makefile | 1 - trunk/drivers/ata/libata-core.c | 35 +- trunk/drivers/ata/libata-scsi.c | 4 +- trunk/drivers/atm/Makefile | 2 +- trunk/drivers/base/memory.c | 6 +- trunk/drivers/base/node.c | 91 +- trunk/drivers/block/cciss.c | 2 +- trunk/drivers/block/cpqarray.c | 3 +- trunk/drivers/block/loop.c | 73 +- trunk/drivers/block/pktcdvd.c | 7 - trunk/drivers/block/ps3disk.c | 21 + trunk/drivers/char/Kconfig | 4 + trunk/drivers/char/agp/Kconfig | 2 +- trunk/drivers/char/drm/Kconfig | 2 +- trunk/drivers/char/drm/radeon_irq.c | 4 +- trunk/drivers/char/mem.c | 125 +- trunk/drivers/char/mspec.c | 2 +- trunk/drivers/char/vt.c | 13 +- trunk/drivers/char/vt_ioctl.c | 15 +- trunk/drivers/dca/Kconfig | 7 - trunk/drivers/dca/Makefile | 2 - trunk/drivers/dca/dca-core.c | 200 -- trunk/drivers/dca/dca-sysfs.c | 88 - trunk/drivers/dma/Kconfig | 60 +- trunk/drivers/dma/Makefile | 1 - trunk/drivers/dma/ioat.c | 211 -- trunk/drivers/dma/ioat_dca.c | 263 --- trunk/drivers/dma/{ioat_dma.c => ioatdma.c} | 653 ++---- trunk/drivers/dma/ioatdma.h | 35 +- trunk/drivers/dma/ioatdma_hw.h | 2 +- trunk/drivers/dma/ioatdma_registers.h | 6 +- trunk/drivers/firewire/fw-cdev.c | 52 +- trunk/drivers/firewire/fw-device.h | 5 + trunk/drivers/firewire/fw-ohci.c | 41 +- trunk/drivers/firewire/fw-ohci.h | 2 - trunk/drivers/firewire/fw-sbp2.c | 647 +++-- trunk/drivers/firewire/fw-topology.c | 10 +- trunk/drivers/firewire/fw-topology.h | 6 + trunk/drivers/firewire/fw-transaction.c | 12 +- trunk/drivers/ide/Kconfig | 18 + trunk/drivers/ide/arm/icside.c | 17 + trunk/drivers/ide/cris/ide-cris.c | 18 +- trunk/drivers/ide/ide-disk.c | 29 + trunk/drivers/ide/ide-dma.c | 79 +- trunk/drivers/ide/ide-io.c | 42 +- trunk/drivers/ide/ide-iops.c | 4 +- trunk/drivers/ide/ide-lib.c | 15 + trunk/drivers/ide/ide-probe.c | 18 +- trunk/drivers/ide/ide-taskfile.c | 18 +- trunk/drivers/ide/ide.c | 19 +- trunk/drivers/ide/legacy/ide-cs.c | 12 +- trunk/drivers/ide/mips/au1xxx-ide.c | 40 +- trunk/drivers/ide/pci/aec62xx.c | 36 +- trunk/drivers/ide/pci/alim15x3.c | 34 +- trunk/drivers/ide/pci/amd74xx.c | 197 +- trunk/drivers/ide/pci/atiixp.c | 93 +- trunk/drivers/ide/pci/cmd64x.c | 27 +- trunk/drivers/ide/pci/cs5520.c | 25 +- trunk/drivers/ide/pci/cs5530.c | 45 +- trunk/drivers/ide/pci/cs5535.c | 28 +- trunk/drivers/ide/pci/cy82c693.c | 12 +- trunk/drivers/ide/pci/generic.c | 57 +- trunk/drivers/ide/pci/hpt34x.c | 28 +- trunk/drivers/ide/pci/hpt366.c | 41 +- trunk/drivers/ide/pci/it8213.c | 84 +- trunk/drivers/ide/pci/it821x.c | 50 +- trunk/drivers/ide/pci/jmicron.c | 32 +- trunk/drivers/ide/pci/ns87415.c | 11 +- trunk/drivers/ide/pci/opti621.c | 14 +- trunk/drivers/ide/pci/pdc202xx_new.c | 37 +- trunk/drivers/ide/pci/pdc202xx_old.c | 32 +- trunk/drivers/ide/pci/piix.c | 125 +- trunk/drivers/ide/pci/rz1000.c | 6 +- trunk/drivers/ide/pci/sc1200.c | 30 +- trunk/drivers/ide/pci/scc_pata.c | 33 +- trunk/drivers/ide/pci/serverworks.c | 33 +- trunk/drivers/ide/pci/sgiioc4.c | 25 +- trunk/drivers/ide/pci/siimage.c | 42 +- trunk/drivers/ide/pci/sis5513.c | 462 +++- trunk/drivers/ide/pci/sl82c105.c | 22 +- trunk/drivers/ide/pci/slc90e66.c | 67 +- trunk/drivers/ide/pci/tc86c001.c | 21 +- trunk/drivers/ide/pci/triflex.c | 21 +- trunk/drivers/ide/pci/trm290.c | 10 +- trunk/drivers/ide/pci/via82cxxx.c | 37 +- trunk/drivers/ide/ppc/pmac.c | 36 +- trunk/drivers/ide/setup-pci.c | 48 +- trunk/drivers/ieee1394/csr1212.c | 57 +- trunk/drivers/ieee1394/csr1212.h | 6 +- trunk/drivers/ieee1394/eth1394.c | 16 +- trunk/drivers/ieee1394/ieee1394_core.c | 2 +- trunk/drivers/ieee1394/nodemgr.c | 22 +- trunk/drivers/ieee1394/pcilynx.c | 29 +- trunk/drivers/ieee1394/sbp2.c | 15 - .../drivers/infiniband/hw/ehca/ehca_classes.h | 2 +- trunk/drivers/infiniband/hw/ehca/ehca_eq.c | 6 +- trunk/drivers/infiniband/hw/ehca/ehca_main.c | 32 +- trunk/drivers/infiniband/hw/ipath/ipath_dma.c | 10 +- .../drivers/infiniband/ulp/iser/iser_memory.c | 75 +- trunk/drivers/input/misc/Kconfig | 2 +- trunk/drivers/isdn/capi/capidrv.c | 5 - trunk/drivers/isdn/capi/kcapi.c | 2 - trunk/drivers/isdn/gigaset/bas-gigaset.c | 9 +- trunk/drivers/isdn/gigaset/i4l.c | 12 +- trunk/drivers/isdn/gigaset/proc.c | 8 +- trunk/drivers/isdn/gigaset/usb-gigaset.c | 7 + trunk/drivers/isdn/i4l/isdn_common.c | 26 +- trunk/drivers/leds/Kconfig | 2 +- trunk/drivers/macintosh/adbhid.c | 2 +- trunk/drivers/md/dm-crypt.c | 31 +- trunk/drivers/md/dm-table.c | 28 + trunk/drivers/md/dm.c | 16 + trunk/drivers/md/dm.h | 1 + trunk/drivers/md/linear.c | 20 + trunk/drivers/md/md.c | 1 + trunk/drivers/md/multipath.c | 30 + trunk/drivers/md/raid0.c | 21 + trunk/drivers/md/raid1.c | 31 + trunk/drivers/md/raid10.c | 31 + trunk/drivers/md/raid5.c | 31 + trunk/drivers/media/video/cx88/cx88-alsa.c | 2 +- trunk/drivers/message/fusion/mptscsih.c | 16 +- trunk/drivers/message/i2o/i2o_block.c | 24 + trunk/drivers/mmc/card/queue.c | 6 +- trunk/drivers/mmc/host/mmc_spi.c | 5 +- trunk/drivers/net/3c59x.c | 8 +- trunk/drivers/net/Kconfig | 10 - trunk/drivers/net/bonding/bond_main.c | 11 +- trunk/drivers/net/bonding/bonding.h | 4 +- trunk/drivers/net/e1000e/ethtool.c | 35 +- trunk/drivers/net/e1000e/hw.h | 2 +- trunk/drivers/net/ehea/ehea.h | 2 +- trunk/drivers/net/ehea/ehea_main.c | 72 +- trunk/drivers/net/forcedeth.c | 168 +- trunk/drivers/net/gianfar.c | 7 +- trunk/drivers/net/hp100.c | 4 +- trunk/drivers/net/ibm_newemac/mal.c | 25 +- trunk/drivers/net/skge.c | 485 +--- trunk/drivers/net/skge.h | 17 +- trunk/drivers/net/tokenring/3c359.c | 2 +- trunk/drivers/pcmcia/Kconfig | 6 +- trunk/drivers/pcmcia/au1000_xxs1500.c | 5 +- trunk/drivers/pcmcia/cistpl.c | 48 +- trunk/drivers/pcmcia/ds.c | 4 - trunk/drivers/pcmcia/pxa2xx_base.c | 2 +- trunk/drivers/pnp/interface.c | 2 +- trunk/drivers/pnp/isapnp/core.c | 4 +- trunk/drivers/pnp/isapnp/proc.c | 2 +- trunk/drivers/pnp/manager.c | 2 +- trunk/drivers/pnp/resource.c | 2 +- trunk/drivers/ps3/ps3av.c | 387 ++- trunk/drivers/ps3/ps3av_cmd.c | 83 +- trunk/drivers/rtc/Kconfig | 11 - trunk/drivers/rtc/Makefile | 1 - trunk/drivers/rtc/class.c | 1 - trunk/drivers/rtc/interface.c | 122 +- trunk/drivers/rtc/rtc-cmos.c | 64 +- trunk/drivers/rtc/rtc-dev.c | 44 +- trunk/drivers/rtc/rtc-ds1374.c | 449 ---- trunk/drivers/rtc/rtc-ds1553.c | 2 +- trunk/drivers/rtc/rtc-ds1742.c | 2 +- trunk/drivers/rtc/rtc-pcf8583.c | 3 - trunk/drivers/rtc/rtc-sysfs.c | 24 - trunk/drivers/s390/scsi/zfcp_def.h | 1 - trunk/drivers/s390/scsi/zfcp_qdio.c | 6 +- trunk/drivers/scsi/3w-9xxx.c | 1 - trunk/drivers/scsi/3w-xxxx.c | 1 - trunk/drivers/scsi/BusLogic.c | 1 - trunk/drivers/scsi/NCR53c406a.c | 3 +- trunk/drivers/scsi/a100u2w.c | 1 - trunk/drivers/scsi/aacraid/linit.c | 1 - trunk/drivers/scsi/aha1542.c | 32 +- trunk/drivers/scsi/aha1740.c | 1 - trunk/drivers/scsi/aic7xxx/aic79xx_osm.c | 1 - trunk/drivers/scsi/aic7xxx/aic7xxx_osm.c | 1 - trunk/drivers/scsi/aic7xxx_old.c | 1 - trunk/drivers/scsi/aic94xx/aic94xx_task.c | 6 +- trunk/drivers/scsi/arcmsr/arcmsr_hba.c | 1 - trunk/drivers/scsi/dc395x.c | 1 - trunk/drivers/scsi/dpt_i2o.c | 1 - trunk/drivers/scsi/eata.c | 3 +- trunk/drivers/scsi/hosts.c | 1 - trunk/drivers/scsi/hptiop.c | 1 - trunk/drivers/scsi/ibmmca.c | 1 - trunk/drivers/scsi/ibmvscsi/ibmvscsi.c | 1 - trunk/drivers/scsi/ide-scsi.c | 32 +- trunk/drivers/scsi/initio.c | 1 - trunk/drivers/scsi/ips.c | 14 +- trunk/drivers/scsi/lpfc/lpfc_scsi.c | 2 - trunk/drivers/scsi/mac53c94.c | 1 - trunk/drivers/scsi/mac_scsi.c | 9 +- trunk/drivers/scsi/megaraid.c | 1 - trunk/drivers/scsi/megaraid/megaraid_mbox.c | 1 - trunk/drivers/scsi/megaraid/megaraid_sas.c | 1 - trunk/drivers/scsi/mesh.c | 1 - trunk/drivers/scsi/nsp32.c | 1 - trunk/drivers/scsi/pcmcia/sym53c500_cs.c | 1 - trunk/drivers/scsi/qla1280.c | 70 +- trunk/drivers/scsi/qla2xxx/qla_os.c | 2 - trunk/drivers/scsi/qla4xxx/ql4_os.c | 1 - trunk/drivers/scsi/qlogicfas.c | 1 - trunk/drivers/scsi/qlogicpti.c | 15 +- trunk/drivers/scsi/scsi_debug.c | 30 +- trunk/drivers/scsi/scsi_lib.c | 238 +- trunk/drivers/scsi/scsi_tgt_lib.c | 4 +- trunk/drivers/scsi/sd.c | 22 + trunk/drivers/scsi/sg.c | 16 +- trunk/drivers/scsi/stex.c | 1 - trunk/drivers/scsi/sym53c416.c | 1 - trunk/drivers/scsi/sym53c8xx_2/sym_glue.c | 1 - trunk/drivers/scsi/u14-34f.c | 3 +- trunk/drivers/scsi/ultrastor.c | 1 - trunk/drivers/scsi/wd7000.c | 1 - trunk/drivers/serial/8250_pci.c | 120 - trunk/drivers/serial/8250_pnp.c | 2 - trunk/drivers/serial/crisv10.c | 67 +- trunk/drivers/serial/m32r_sio.c | 2 +- trunk/drivers/serial/m32r_sio.h | 6 + trunk/drivers/serial/serial_core.c | 40 +- trunk/drivers/serial/serial_cs.c | 1 - trunk/drivers/serial/serial_txx9.c | 30 +- trunk/drivers/spi/Kconfig | 13 +- trunk/drivers/spi/atmel_spi.c | 14 +- trunk/drivers/spi/mpc52xx_psc_spi.c | 2 +- trunk/drivers/spi/omap2_mcspi.c | 4 +- trunk/drivers/spi/omap_uwire.c | 9 +- trunk/drivers/spi/pxa2xx_spi.c | 14 +- trunk/drivers/spi/spi.c | 36 +- trunk/drivers/spi/spi_bfin5xx.c | 3 +- trunk/drivers/spi/spi_bitbang.c | 2 +- trunk/drivers/spi/spi_imx.c | 13 +- trunk/drivers/spi/spi_lm70llp.c | 2 +- trunk/drivers/spi/spi_mpc83xx.c | 7 +- trunk/drivers/spi/spi_s3c24xx.c | 9 +- trunk/drivers/spi/spi_txx9.c | 2 +- trunk/drivers/telephony/Kconfig | 2 +- trunk/drivers/usb/core/hub.c | 6 +- trunk/drivers/usb/misc/sisusbvga/sisusb_con.c | 3 +- trunk/drivers/usb/storage/alauda.c | 16 +- trunk/drivers/usb/storage/datafab.c | 10 +- trunk/drivers/usb/storage/jumpshot.c | 10 +- trunk/drivers/usb/storage/protocol.c | 20 +- trunk/drivers/usb/storage/protocol.h | 2 +- trunk/drivers/usb/storage/sddr09.c | 16 +- trunk/drivers/usb/storage/sddr55.c | 16 +- trunk/drivers/usb/storage/shuttle_usbat.c | 17 +- trunk/drivers/video/Kconfig | 59 +- trunk/drivers/video/Makefile | 2 - trunk/drivers/video/amifb.c | 2 +- trunk/drivers/video/arcfb.c | 2 +- trunk/drivers/video/atafb.c | 2 +- trunk/drivers/video/aty/ati_ids.h | 1 - trunk/drivers/video/aty/aty128fb.c | 2 +- trunk/drivers/video/aty/atyfb.h | 1 - trunk/drivers/video/aty/atyfb_base.c | 6 +- trunk/drivers/video/aty/mach64_cursor.c | 1 + trunk/drivers/video/aty/radeon_base.c | 5 +- trunk/drivers/video/aty/radeonfb.h | 4 +- trunk/drivers/video/backlight/cr_bllcd.c | 1 + trunk/drivers/video/backlight/progear_bl.c | 1 + trunk/drivers/video/bf54x-lq043fb.c | 786 ------- trunk/drivers/video/cfbcopyarea.c | 103 +- trunk/drivers/video/cfbfillrect.c | 20 +- trunk/drivers/video/cfbimgblt.c | 17 +- trunk/drivers/video/cirrusfb.c | 2053 ++++++++-------- trunk/drivers/video/clps711xfb.c | 2 +- trunk/drivers/video/console/fbcon.c | 5 +- trunk/drivers/video/console/font_10x18.c | 14 +- trunk/drivers/video/console/font_6x11.c | 13 +- trunk/drivers/video/console/font_7x14.c | 12 +- trunk/drivers/video/console/font_8x16.c | 14 +- trunk/drivers/video/console/font_8x8.c | 12 +- trunk/drivers/video/console/font_acorn_8x8.c | 14 +- trunk/drivers/video/console/font_mini_4x6.c | 12 +- trunk/drivers/video/console/font_pearl_8x8.c | 12 +- trunk/drivers/video/console/font_sun12x22.c | 14 +- trunk/drivers/video/console/font_sun8x16.c | 14 +- trunk/drivers/video/console/newport_con.c | 20 +- trunk/drivers/video/console/softcursor.c | 1 + trunk/drivers/video/console/vgacon.c | 7 +- trunk/drivers/video/cyber2000fb.c | 1 + trunk/drivers/video/epson1355fb.c | 2 +- trunk/drivers/video/fb_defio.c | 1 + trunk/drivers/video/fb_draw.h | 94 - trunk/drivers/video/fb_sys_fops.c | 2 +- trunk/drivers/video/fbcmap.c | 3 +- trunk/drivers/video/fbmem.c | 5 +- trunk/drivers/video/fbmon.c | 4 +- trunk/drivers/video/geode/lxfb_core.c | 7 +- trunk/drivers/video/hecubafb.c | 2 +- trunk/drivers/video/imsttfb.c | 2 +- trunk/drivers/video/imxfb.c | 4 +- trunk/drivers/video/intelfb/intelfb.h | 17 +- trunk/drivers/video/intelfb/intelfb_i2c.c | 60 +- trunk/drivers/video/intelfb/intelfbdrv.c | 178 +- trunk/drivers/video/intelfb/intelfbhw.c | 318 ++- trunk/drivers/video/intelfb/intelfbhw.h | 52 +- trunk/drivers/video/kyro/fbdev.c | 2 +- trunk/drivers/video/logo/logo.c | 7 - trunk/drivers/video/matrox/matroxfb_base.c | 2 +- trunk/drivers/video/matrox/matroxfb_crtc2.c | 2 +- trunk/drivers/video/matrox/matroxfb_g450.c | 1 + trunk/drivers/video/matrox/matroxfb_maven.c | 1 + trunk/drivers/video/mbx/mbxfb.c | 344 +-- trunk/drivers/video/mbx/reg_bits.h | 87 +- trunk/drivers/video/mbx/regs.h | 2 +- trunk/drivers/video/modedb.c | 58 +- trunk/drivers/video/neofb.c | 1 + trunk/drivers/video/nvidia/nv_i2c.c | 10 +- trunk/drivers/video/nvidia/nv_type.h | 1 - trunk/drivers/video/nvidia/nvidia.c | 6 - trunk/drivers/video/pm2fb.c | 883 ++----- trunk/drivers/video/pm3fb.c | 557 +---- trunk/drivers/video/pmag-ba-fb.c | 34 +- trunk/drivers/video/pmagb-b-fb.c | 34 +- trunk/drivers/video/pnx4008/pnxrgbfb.c | 1 + trunk/drivers/video/ps3fb.c | 511 ++-- trunk/drivers/video/pvr2fb.c | 2 +- trunk/drivers/video/pxafb.c | 65 +- trunk/drivers/video/pxafb.h | 2 - trunk/drivers/video/s3c2410fb.c | 783 +++---- trunk/drivers/video/s3c2410fb.h | 13 +- trunk/drivers/video/s3fb.c | 24 +- trunk/drivers/video/sa1100fb.c | 1 + trunk/drivers/video/savage/savagefb_driver.c | 1 + trunk/drivers/video/sis/sis_main.c | 2 +- trunk/drivers/video/skeletonfb.c | 2 +- trunk/drivers/video/sm501fb.c | 49 +- trunk/drivers/video/sstfb.c | 2 +- trunk/drivers/video/svgalib.c | 47 +- trunk/drivers/video/tdfxfb.c | 1255 +++++----- trunk/drivers/video/tgafb.c | 20 +- trunk/drivers/video/tridentfb.c | 1075 ++++----- trunk/drivers/video/uvesafb.c | 2066 ---------------- trunk/drivers/video/vermilion/vermilion.c | 1 + trunk/drivers/video/vfb.c | 79 +- trunk/fs/adfs/inode.c | 14 +- trunk/fs/affs/file.c | 101 +- trunk/fs/bfs/file.c | 12 +- trunk/fs/binfmt_elf.c | 2 +- trunk/fs/binfmt_elf_fdpic.c | 2 +- trunk/fs/bio.c | 23 +- trunk/fs/block_dev.c | 24 +- trunk/fs/buffer.c | 723 ++---- trunk/fs/configfs/inode.c | 4 +- trunk/fs/dcache.c | 2 +- trunk/fs/debugfs/file.c | 41 +- trunk/fs/direct-io.c | 4 +- trunk/fs/ecryptfs/Makefile | 2 +- trunk/fs/ecryptfs/crypto.c | 989 ++++---- trunk/fs/ecryptfs/debug.c | 2 + trunk/fs/ecryptfs/ecryptfs_kernel.h | 183 +- trunk/fs/ecryptfs/file.c | 97 +- trunk/fs/ecryptfs/inode.c | 231 +- trunk/fs/ecryptfs/keystore.c | 1078 ++++----- trunk/fs/ecryptfs/main.c | 260 +- trunk/fs/ecryptfs/messaging.c | 5 +- trunk/fs/ecryptfs/mmap.c | 704 ++++-- trunk/fs/ecryptfs/read_write.c | 358 --- trunk/fs/ecryptfs/super.c | 39 +- trunk/fs/ext2/dir.c | 55 +- trunk/fs/ext2/ext2.h | 3 - trunk/fs/ext2/inode.c | 40 +- trunk/fs/ext3/dir.c | 2 +- trunk/fs/ext3/inode.c | 163 +- trunk/fs/ext4/dir.c | 2 +- trunk/fs/ext4/inode.c | 174 +- trunk/fs/fat/inode.c | 27 +- trunk/fs/fuse/file.c | 46 +- trunk/fs/gfs2/ops_address.c | 211 +- trunk/fs/hfs/extent.c | 19 +- trunk/fs/hfs/inode.c | 18 +- trunk/fs/hfsplus/extents.c | 21 +- trunk/fs/hfsplus/inode.c | 18 +- trunk/fs/hostfs/hostfs.h | 9 +- trunk/fs/hostfs/hostfs_kern.c | 301 +-- trunk/fs/hostfs/hostfs_user.c | 141 +- trunk/fs/hpfs/file.c | 18 +- trunk/fs/hugetlbfs/inode.c | 149 +- trunk/fs/inode.c | 18 +- trunk/fs/jbd/journal.c | 4 +- trunk/fs/jbd/revoke.c | 6 +- trunk/fs/jffs2/file.c | 105 +- trunk/fs/jfs/inode.c | 16 +- trunk/fs/libfs.c | 44 - trunk/fs/minix/dir.c | 49 +- trunk/fs/minix/inode.c | 23 +- trunk/fs/minix/minix.h | 3 - trunk/fs/mpage.c | 10 +- trunk/fs/namei.c | 46 +- trunk/fs/nfs/file.c | 80 +- trunk/fs/nfsd/export.c | 17 +- trunk/fs/ocfs2/aops.c | 14 +- trunk/fs/ocfs2/aops.h | 8 + trunk/fs/ocfs2/file.c | 266 ++- trunk/fs/open.c | 4 - trunk/fs/proc/base.c | 13 +- trunk/fs/proc/generic.c | 2 +- trunk/fs/proc/proc_misc.c | 14 - trunk/fs/qnx4/inode.c | 19 +- trunk/fs/ramfs/file-mmu.c | 4 +- trunk/fs/ramfs/file-nommu.c | 4 +- trunk/fs/reiserfs/file.c | 1240 +++++++++- trunk/fs/reiserfs/inode.c | 187 +- trunk/fs/reiserfs/ioctl.c | 10 +- trunk/fs/reiserfs/xattr.c | 16 +- trunk/fs/smbfs/file.c | 32 +- trunk/fs/splice.c | 73 +- trunk/fs/sysfs/inode.c | 4 +- trunk/fs/sysv/dir.c | 50 +- trunk/fs/sysv/itree.c | 23 +- trunk/fs/sysv/sysv.h | 3 - trunk/fs/udf/file.c | 35 +- trunk/fs/udf/inode.c | 13 +- trunk/fs/ufs/dir.c | 55 +- trunk/fs/ufs/inode.c | 23 +- trunk/fs/ufs/util.h | 3 - trunk/fs/xfs/linux-2.6/xfs_aops.c | 19 +- trunk/fs/xfs/linux-2.6/xfs_lrw.c | 35 +- trunk/include/asm-alpha/page.h | 3 +- trunk/include/asm-alpha/ptrace.h | 2 + trunk/include/asm-arm/arch-imx/imxfb.h | 1 - trunk/include/asm-arm/arch-pxa/pxa-regs.h | 11 - trunk/include/asm-arm/arch-pxa/pxafb.h | 7 +- trunk/include/asm-arm/arch-s3c2410/fb.h | 42 +- trunk/include/asm-avr32/kdebug.h | 16 + trunk/include/asm-avr32/kprobes.h | 2 +- .../asm-blackfin/mach-bf548/bf54x-lq043.h | 30 - trunk/include/asm-frv/thread_info.h | 5 +- trunk/include/asm-frv/tlbflush.h | 3 +- trunk/include/asm-generic/memory_model.h | 6 - trunk/include/asm-generic/pgtable.h | 4 + trunk/include/asm-ia64/dma-mapping.h | 2 +- trunk/include/asm-ia64/kdebug.h | 15 + trunk/include/asm-ia64/kprobes.h | 2 +- trunk/include/asm-ia64/pgtable.h | 50 +- trunk/include/asm-ia64/scatterlist.h | 2 - trunk/include/asm-ia64/smp.h | 2 +- trunk/include/asm-ia64/topology.h | 2 +- trunk/include/asm-m32r/ptrace.h | 5 +- trunk/include/asm-m32r/thread_info.h | 5 +- trunk/include/asm-m68knommu/system.h | 3 +- trunk/include/asm-mips/ip32/ip32_ints.h | 158 +- trunk/include/asm-mips/lasat/lasatint.h | 9 +- trunk/include/asm-mips/mach-au1x00/au1000.h | 23 +- .../include/asm-mips/pmc-sierra/msp71xx/war.h | 28 - trunk/include/asm-mips/ptrace.h | 4 +- trunk/include/asm-mips/xxs1500.h | 35 + trunk/include/asm-powerpc/cputable.h | 3 +- trunk/include/asm-powerpc/dma-mapping.h | 17 +- trunk/include/asm-powerpc/ibmebus.h | 38 +- trunk/include/asm-powerpc/kdebug.h | 19 + trunk/include/asm-powerpc/kprobes.h | 2 +- trunk/include/asm-powerpc/of_device.h | 4 - trunk/include/asm-powerpc/pgtable-ppc64.h | 8 - trunk/include/asm-powerpc/ps3av.h | 33 +- trunk/include/asm-powerpc/scatterlist.h | 2 - trunk/include/asm-powerpc/smp.h | 4 +- trunk/include/asm-powerpc/topology.h | 2 +- trunk/include/asm-s390/kdebug.h | 15 + trunk/include/asm-s390/kprobes.h | 2 +- trunk/include/asm-sh/kdebug.h | 2 + trunk/include/asm-sparc/scatterlist.h | 2 - trunk/include/asm-sparc64/kdebug.h | 18 + trunk/include/asm-sparc64/kprobes.h | 3 +- trunk/include/asm-sparc64/pgtable.h | 3 - trunk/include/asm-sparc64/scatterlist.h | 2 - trunk/include/asm-sparc64/smp.h | 3 +- trunk/include/asm-sparc64/topology.h | 2 +- trunk/include/asm-um/a.out.h | 12 +- trunk/include/asm-um/elf-i386.h | 12 +- trunk/include/asm-um/elf-x86_64.h | 56 +- trunk/include/asm-um/ldt.h | 4 + trunk/include/asm-um/mmu_context.h | 43 +- trunk/include/asm-um/page.h | 1 - trunk/include/asm-um/pgalloc.h | 2 +- trunk/include/asm-um/pgtable-3level.h | 2 +- trunk/include/asm-um/processor-generic.h | 48 +- trunk/include/asm-um/processor-x86_64.h | 2 +- trunk/include/asm-um/ptrace-generic.h | 17 +- trunk/include/asm-um/ptrace-i386.h | 42 +- trunk/include/asm-um/ptrace-x86_64.h | 13 +- trunk/include/asm-um/smp.h | 2 +- trunk/include/asm-um/tlbflush.h | 19 +- trunk/include/asm-um/uaccess.h | 2 +- trunk/include/asm-x86/cpufeature_32.h | 1 - trunk/include/asm-x86/dma-mapping_32.h | 13 +- trunk/include/asm-x86/dma-mapping_64.h | 3 +- trunk/include/asm-x86/kdebug_32.h | 6 + trunk/include/asm-x86/kdebug_64.h | 6 +- trunk/include/asm-x86/kprobes_32.h | 4 +- trunk/include/asm-x86/kprobes_64.h | 2 +- trunk/include/asm-x86/page_64.h | 1 - trunk/include/asm-x86/pgtable_64.h | 1 - trunk/include/asm-x86/scatterlist_32.h | 2 - trunk/include/asm-x86/scatterlist_64.h | 2 - trunk/include/asm-x86/smp_32.h | 4 +- trunk/include/asm-x86/smp_64.h | 11 +- trunk/include/asm-x86/topology_32.h | 4 +- trunk/include/asm-x86/topology_64.h | 4 +- trunk/include/linux/Kbuild | 3 + trunk/include/linux/bio.h | 19 +- trunk/include/linux/bitops.h | 6 - trunk/include/linux/blkdev.h | 8 +- trunk/include/linux/buffer_head.h | 26 +- trunk/include/linux/connector.h | 7 +- trunk/include/linux/console.h | 3 +- trunk/include/linux/console_struct.h | 1 - trunk/include/linux/cpuset.h | 2 +- trunk/include/linux/dca.h | 47 - trunk/include/linux/dma-mapping.h | 7 - trunk/include/linux/fb.h | 3 - trunk/include/linux/firewire-cdev.h | 15 - trunk/include/linux/fs.h | 78 +- trunk/include/linux/gfp.h | 62 +- trunk/include/linux/hugetlb.h | 1 - trunk/include/linux/i2c-id.h | 1 - trunk/include/linux/i2o.h | 3 +- trunk/include/linux/ide.h | 18 +- trunk/include/linux/init.h | 2 - trunk/include/linux/interrupt.h | 9 - trunk/include/linux/ioport.h | 3 + trunk/include/linux/isdn.h | 3 +- trunk/include/linux/jbd.h | 1 - trunk/include/linux/jiffies.h | 2 - trunk/include/linux/kernel.h | 1 - trunk/include/linux/kprobes.h | 6 - trunk/include/linux/libata.h | 16 +- trunk/include/linux/memory_hotplug.h | 18 +- trunk/include/linux/mempolicy.h | 7 +- trunk/include/linux/mm.h | 97 +- trunk/include/linux/mm_types.h | 158 +- trunk/include/linux/mmzone.h | 68 +- trunk/include/linux/nfsd/export.h | 11 + trunk/include/linux/nodemask.h | 94 +- trunk/include/linux/of_device.h | 5 - trunk/include/linux/page-isolation.h | 37 - trunk/include/linux/pageblock-flags.h | 75 - trunk/include/linux/pagemap.h | 36 +- trunk/include/linux/pci_ids.h | 4 - trunk/include/linux/radix-tree.h | 40 +- trunk/include/linux/scatterlist.h | 84 - trunk/include/linux/sched.h | 77 +- trunk/include/linux/security.h | 18 - trunk/include/linux/selection.h | 1 - trunk/include/linux/serial_core.h | 3 +- trunk/include/linux/slab.h | 4 +- trunk/include/linux/slub_def.h | 71 +- trunk/include/linux/sm501-regs.h | 18 - trunk/include/linux/spi/at73c213.h | 25 - trunk/include/linux/spi/spi.h | 12 +- trunk/include/linux/usb/gadget.h | 4 +- trunk/include/pcmcia/ds.h | 1 - trunk/include/scsi/scsi.h | 7 + trunk/include/scsi/scsi_cmnd.h | 7 +- trunk/include/scsi/scsi_host.h | 13 - trunk/include/sound/ac97_codec.h | 8 +- trunk/include/sound/ad1848.h | 5 +- trunk/include/sound/ainstr_gf1.h | 2 +- trunk/include/sound/ainstr_iw.h | 2 +- trunk/include/sound/ainstr_simple.h | 2 +- trunk/include/sound/ak4114.h | 2 +- trunk/include/sound/ak4117.h | 2 +- trunk/include/sound/ak4531_codec.h | 2 +- trunk/include/sound/ak4xxx-adda.h | 2 +- trunk/include/sound/asequencer.h | 2 +- trunk/include/sound/asound.h | 3 +- trunk/include/sound/asound_fm.h | 2 +- trunk/include/sound/asoundef.h | 2 +- trunk/include/sound/control.h | 10 +- trunk/include/sound/core.h | 2 +- trunk/include/sound/cs4231-regs.h | 180 -- trunk/include/sound/cs4231.h | 159 +- trunk/include/sound/cs46xx.h | 2 +- trunk/include/sound/cs46xx_dsp_scb_types.h | 2 +- trunk/include/sound/cs46xx_dsp_spos.h | 2 +- trunk/include/sound/cs46xx_dsp_task_types.h | 2 +- trunk/include/sound/cs8403.h | 2 +- trunk/include/sound/cs8427.h | 2 +- trunk/include/sound/driver.h | 2 +- trunk/include/sound/emu10k1.h | 15 +- trunk/include/sound/es1688.h | 2 +- trunk/include/sound/gus.h | 2 +- trunk/include/sound/hda_hwdep.h | 44 - trunk/include/sound/hdspm.h | 16 +- trunk/include/sound/hwdep.h | 2 +- trunk/include/sound/info.h | 2 +- trunk/include/sound/initval.h | 2 +- trunk/include/sound/memalloc.h | 2 +- trunk/include/sound/mixer_oss.h | 2 +- trunk/include/sound/mpu401.h | 3 +- trunk/include/sound/opl3.h | 2 +- trunk/include/sound/pcm-indirect.h | 2 +- trunk/include/sound/pcm.h | 13 +- trunk/include/sound/pcm_oss.h | 2 +- trunk/include/sound/rawmidi.h | 2 +- trunk/include/sound/sb.h | 2 +- trunk/include/sound/seq_instr.h | 2 +- trunk/include/sound/seq_midi_event.h | 2 +- trunk/include/sound/seq_virmidi.h | 2 +- trunk/include/sound/soc.h | 3 +- trunk/include/sound/tea575x-tuner.h | 2 +- trunk/include/sound/timer.h | 2 +- trunk/include/sound/tlv.h | 2 +- trunk/include/sound/version.h | 4 +- trunk/include/sound/ymfpci.h | 2 +- trunk/include/video/Kbuild | 2 +- trunk/include/video/mbxfb.h | 53 +- trunk/include/video/permedia2.h | 17 - trunk/include/video/pm3fb.h | 1272 +++++----- trunk/include/video/tdfx.h | 270 ++- trunk/include/video/uvesafb.h | 193 -- trunk/init/Makefile | 2 +- trunk/init/calibrate.c | 2 +- trunk/kernel/cpuset.c | 142 +- trunk/kernel/kprobes.c | 62 +- trunk/kernel/printk.c | 59 - trunk/kernel/profile.c | 4 +- trunk/kernel/ptrace.c | 13 - trunk/kernel/resource.c | 26 +- trunk/kernel/sched.c | 37 +- trunk/kernel/sysctl.c | 8 - trunk/kernel/time.c | 6 +- trunk/kernel/time/timekeeping.c | 7 + trunk/lib/Kconfig.debug | 18 - trunk/lib/radix-tree.c | 132 +- trunk/lib/swiotlb.c | 19 +- trunk/mm/Kconfig | 18 - trunk/mm/Makefile | 3 +- trunk/mm/bounce.c | 6 - trunk/mm/filemap.c | 766 ++---- trunk/mm/filemap.h | 103 + trunk/mm/filemap_xip.c | 17 +- trunk/mm/hugetlb.c | 398 +--- trunk/mm/internal.h | 10 - trunk/mm/memory.c | 161 +- trunk/mm/memory_hotplug.c | 312 +-- trunk/mm/mempolicy.c | 60 +- trunk/mm/migrate.c | 4 +- trunk/mm/mprotect.c | 1 + trunk/mm/oom_kill.c | 9 +- trunk/mm/page-writeback.c | 10 +- trunk/mm/page_alloc.c | 731 +----- trunk/mm/page_isolation.c | 138 -- trunk/mm/readahead.c | 88 +- trunk/mm/rmap.c | 1 + trunk/mm/shmem.c | 62 +- trunk/mm/slab.c | 21 +- trunk/mm/slob.c | 7 +- trunk/mm/slub.c | 490 ++-- trunk/mm/sparse-vmemmap.c | 148 -- trunk/mm/sparse.c | 105 +- trunk/mm/swap.c | 106 +- trunk/mm/swap_state.c | 5 +- trunk/mm/util.c | 6 +- trunk/mm/vmalloc.c | 5 +- trunk/mm/vmscan.c | 59 +- trunk/mm/vmstat.c | 305 +-- trunk/net/sunrpc/xprtrdma/verbs.c | 3 +- trunk/scripts/Kbuild.include | 8 +- trunk/scripts/Makefile.build | 45 +- trunk/scripts/Makefile.clean | 2 +- trunk/scripts/Makefile.lib | 30 +- trunk/scripts/basic/Makefile | 8 +- trunk/scripts/basic/docproc.c | 34 +- trunk/scripts/checkkconfigsymbols.sh | 59 - trunk/scripts/export_report.pl | 10 +- trunk/scripts/gcc-version.sh | 8 +- trunk/scripts/genksyms/Makefile | 8 +- trunk/scripts/genksyms/keywords.c_shipped | 180 +- trunk/scripts/genksyms/keywords.gperf | 1 - trunk/scripts/genksyms/lex.c_shipped | 1802 +++++--------- trunk/scripts/genksyms/parse.c_shipped | 2088 +++++++---------- trunk/scripts/genksyms/parse.h_shipped | 159 +- trunk/scripts/genksyms/parse.y | 5 +- trunk/scripts/kconfig/Makefile | 10 +- trunk/scripts/kconfig/check.sh | 14 - trunk/scripts/kconfig/lex.zconf.c_shipped | 25 +- trunk/scripts/kconfig/mconf.c | 36 +- trunk/scripts/kconfig/menu.c | 35 +- trunk/scripts/kconfig/util.c | 13 +- trunk/scripts/kconfig/zconf.gperf | 2 + trunk/scripts/kconfig/zconf.hash.c_shipped | 220 +- trunk/scripts/kconfig/zconf.tab.c_shipped | 1406 +++++------ trunk/scripts/kconfig/zconf.y | 11 + trunk/scripts/makelst | 4 +- trunk/scripts/mkmakefile | 8 +- trunk/scripts/mod/file2alias.c | 40 +- trunk/scripts/mod/modpost.c | 6 - trunk/scripts/mod/modpost.h | 4 +- trunk/scripts/ver_linux | 9 +- trunk/security/dummy.c | 6 - trunk/security/selinux/avc.c | 5 - trunk/security/selinux/hooks.c | 53 +- trunk/security/selinux/include/avc.h | 2 - trunk/security/selinux/include/objsec.h | 2 - trunk/security/selinux/include/security.h | 2 - trunk/security/selinux/selinuxfs.c | 26 - trunk/security/selinux/ss/avtab.c | 91 +- trunk/security/selinux/ss/avtab.h | 16 +- trunk/security/selinux/ss/conditional.c | 4 - trunk/security/selinux/ss/ebitmap.c | 282 +-- trunk/security/selinux/ss/ebitmap.h | 89 +- trunk/security/selinux/ss/mls.c | 156 +- trunk/security/selinux/ss/policydb.c | 11 +- trunk/security/selinux/ss/policydb.h | 8 - trunk/security/selinux/ss/services.c | 91 +- trunk/sound/Kconfig | 4 - trunk/sound/Makefile | 3 +- trunk/sound/aoa/codecs/snd-aoa-codec-onyx.c | 20 +- trunk/sound/aoa/codecs/snd-aoa-codec-tas.c | 29 +- .../sound/aoa/fabrics/snd-aoa-fabric-layout.c | 10 +- trunk/sound/arm/sa11xx-uda1341.c | 35 +- trunk/sound/core/Makefile | 15 +- trunk/sound/core/control.c | 33 +- trunk/sound/core/device.c | 2 +- trunk/sound/core/hwdep.c | 4 +- trunk/sound/core/info.c | 2 +- trunk/sound/core/info_oss.c | 2 +- trunk/sound/core/init.c | 2 +- trunk/sound/core/isadma.c | 2 +- trunk/sound/core/memalloc.c | 10 +- trunk/sound/core/memory.c | 2 +- trunk/sound/core/misc.c | 2 +- trunk/sound/core/oss/Makefile | 7 +- trunk/sound/core/oss/copy.c | 5 + trunk/sound/core/oss/io.c | 7 +- trunk/sound/core/oss/linear.c | 91 +- trunk/sound/core/oss/mixer_oss.c | 4 +- trunk/sound/core/oss/mulaw.c | 90 +- trunk/sound/core/oss/pcm_oss.c | 39 +- trunk/sound/core/oss/pcm_plugin.c | 63 +- trunk/sound/core/oss/pcm_plugin.h | 2 +- trunk/sound/core/oss/plugin_ops.h | 370 +++ trunk/sound/core/oss/rate.c | 7 +- trunk/sound/core/oss/route.c | 5 + trunk/sound/core/pcm.c | 4 +- trunk/sound/core/pcm_lib.c | 2 +- trunk/sound/core/pcm_memory.c | 2 +- trunk/sound/core/pcm_misc.c | 65 +- trunk/sound/core/pcm_native.c | 10 +- trunk/sound/core/pcm_timer.c | 2 +- trunk/sound/core/rawmidi.c | 5 +- trunk/sound/core/seq/Makefile | 2 +- trunk/sound/core/seq/instr/Makefile | 2 +- trunk/sound/core/seq/instr/ainstr_gf1.c | 4 +- trunk/sound/core/seq/instr/ainstr_iw.c | 4 +- trunk/sound/core/seq/instr/ainstr_simple.c | 4 +- trunk/sound/core/seq/oss/Makefile | 2 +- trunk/sound/core/seq/oss/seq_oss_init.c | 40 +- trunk/sound/core/seq/oss/seq_oss_writeq.c | 6 +- trunk/sound/core/seq/seq.c | 2 +- trunk/sound/core/seq/seq_clientmgr.c | 2 +- trunk/sound/core/seq/seq_instr.c | 14 +- trunk/sound/core/seq/seq_memory.c | 2 +- trunk/sound/core/seq/seq_midi.c | 4 +- trunk/sound/core/seq/seq_midi_event.c | 101 +- trunk/sound/core/seq/seq_ports.c | 2 +- trunk/sound/core/seq/seq_timer.c | 2 +- trunk/sound/core/sound.c | 12 +- trunk/sound/core/sound_oss.c | 2 +- trunk/sound/core/timer.c | 4 +- trunk/sound/drivers/Makefile | 2 +- trunk/sound/drivers/dummy.c | 14 +- trunk/sound/drivers/mpu401/Makefile | 2 +- trunk/sound/drivers/mpu401/mpu401.c | 10 +- trunk/sound/drivers/mpu401/mpu401_uart.c | 7 +- trunk/sound/drivers/mts64.c | 10 +- trunk/sound/drivers/opl3/Makefile | 8 +- trunk/sound/drivers/opl3/opl3_lib.c | 4 +- trunk/sound/drivers/opl4/Makefile | 2 +- trunk/sound/drivers/serial-u16550.c | 2 +- trunk/sound/drivers/vx/Makefile | 2 +- trunk/sound/drivers/vx/vx_mixer.c | 18 +- trunk/sound/i2c/Makefile | 6 +- trunk/sound/i2c/cs8427.c | 10 +- trunk/sound/i2c/i2c.c | 4 +- trunk/sound/i2c/other/Makefile | 2 +- trunk/sound/i2c/other/ak4114.c | 14 +- trunk/sound/i2c/other/ak4117.c | 14 +- trunk/sound/i2c/other/ak4xxx-adda.c | 14 +- trunk/sound/i2c/other/pt2258.c | 10 +- trunk/sound/i2c/other/tea575x-tuner.c | 4 +- trunk/sound/i2c/tea6330t.c | 14 +- trunk/sound/isa/Kconfig | 22 +- trunk/sound/isa/Makefile | 4 +- trunk/sound/isa/ad1816a/Makefile | 2 +- trunk/sound/isa/ad1816a/ad1816a_lib.c | 2 + trunk/sound/isa/ad1848/Makefile | 9 +- trunk/sound/isa/ad1848/ad1848.c | 6 +- trunk/sound/isa/ad1848/ad1848_lib.c | 140 +- trunk/sound/isa/cs423x/Makefile | 19 +- trunk/sound/isa/cs423x/cs4231.c | 4 +- trunk/sound/isa/cs423x/cs4231_lib.c | 115 +- trunk/sound/isa/cs423x/cs4236.c | 4 +- trunk/sound/isa/cs423x/cs4236_lib.c | 4 +- trunk/sound/isa/es1688/Makefile | 2 +- trunk/sound/isa/es1688/es1688.c | 4 +- trunk/sound/isa/es1688/es1688_lib.c | 4 +- trunk/sound/isa/es18xx.c | 19 +- trunk/sound/isa/gus/Makefile | 2 +- trunk/sound/isa/gus/gus_dma.c | 2 +- trunk/sound/isa/gus/gus_dram.c | 2 +- trunk/sound/isa/gus/gus_instr.c | 2 +- trunk/sound/isa/gus/gus_io.c | 2 +- trunk/sound/isa/gus/gus_irq.c | 20 +- trunk/sound/isa/gus/gus_main.c | 22 +- trunk/sound/isa/gus/gus_mem.c | 2 +- trunk/sound/isa/gus/gus_mem_proc.c | 2 +- trunk/sound/isa/gus/gus_mixer.c | 11 +- trunk/sound/isa/gus/gus_pcm.c | 2 +- trunk/sound/isa/gus/gus_reset.c | 2 +- trunk/sound/isa/gus/gus_sample.c | 2 +- trunk/sound/isa/gus/gus_simple.c | 2 +- trunk/sound/isa/gus/gus_synth.c | 4 +- trunk/sound/isa/gus/gus_tables.h | 2 +- trunk/sound/isa/gus/gus_timer.c | 2 +- trunk/sound/isa/gus/gus_uart.c | 2 +- trunk/sound/isa/gus/gus_volume.c | 2 +- trunk/sound/isa/gus/gusclassic.c | 4 +- trunk/sound/isa/gus/gusextreme.c | 4 +- trunk/sound/isa/gus/gusmax.c | 4 +- trunk/sound/isa/gus/interwave.c | 4 +- trunk/sound/isa/opl3sa2.c | 5 +- trunk/sound/isa/opti9xx/Makefile | 2 +- trunk/sound/isa/opti9xx/miro.c | 18 +- trunk/sound/isa/opti9xx/opti92x-ad1848.c | 14 +- trunk/sound/isa/sb/Makefile | 2 +- trunk/sound/isa/sb/emu8000.c | 2 +- trunk/sound/isa/sb/emu8000_synth.c | 2 +- trunk/sound/isa/sb/sb16.c | 4 +- trunk/sound/isa/sb/sb16_csp.c | 9 +- trunk/sound/isa/sb/sb16_main.c | 4 +- trunk/sound/isa/sb/sb8.c | 4 +- trunk/sound/isa/sb/sb8_main.c | 4 +- trunk/sound/isa/sb/sb8_midi.c | 2 +- trunk/sound/isa/sb/sb_common.c | 8 +- trunk/sound/isa/sb/sb_mixer.c | 2 +- trunk/sound/isa/sc6000.c | 656 ------ trunk/sound/isa/sscape.c | 354 +-- trunk/sound/isa/wavefront/Makefile | 2 +- trunk/sound/isa/wavefront/wavefront_synth.c | 130 +- trunk/sound/last.c | 2 +- trunk/sound/pci/Kconfig | 111 +- trunk/sound/pci/Makefile | 2 +- trunk/sound/pci/ac97/Makefile | 2 +- trunk/sound/pci/ac97/ac97_codec.c | 40 +- trunk/sound/pci/ac97/ac97_id.h | 3 +- trunk/sound/pci/ac97/ac97_local.h | 2 +- trunk/sound/pci/ac97/ac97_patch.c | 162 +- trunk/sound/pci/ac97/ac97_patch.h | 2 +- trunk/sound/pci/ac97/ac97_pcm.c | 2 +- trunk/sound/pci/ac97/ac97_proc.c | 10 +- trunk/sound/pci/ac97/ak4531_codec.c | 4 +- trunk/sound/pci/ali5451/Makefile | 2 +- trunk/sound/pci/ali5451/ali5451.c | 10 +- trunk/sound/pci/als4000.c | 2 +- trunk/sound/pci/au88x0/au88x0.c | 1 - trunk/sound/pci/au88x0/au88x0_eq.c | 10 +- trunk/sound/pci/au88x0/au88x0_mpu401.c | 2 +- trunk/sound/pci/au88x0/au88x0_synth.c | 4 +- trunk/sound/pci/bt87x.c | 217 +- trunk/sound/pci/ca0106/ca0106.h | 98 +- trunk/sound/pci/ca0106/ca0106_main.c | 103 +- trunk/sound/pci/ca0106/ca0106_mixer.c | 98 +- trunk/sound/pci/ca0106/ca_midi.c | 2 +- trunk/sound/pci/ca0106/ca_midi.h | 6 +- trunk/sound/pci/cmipci.c | 537 ++--- trunk/sound/pci/cs4281.c | 28 +- trunk/sound/pci/cs46xx/Makefile | 8 +- trunk/sound/pci/cs46xx/cs46xx.c | 4 +- trunk/sound/pci/cs46xx/cs46xx_lib.c | 12 +- trunk/sound/pci/cs46xx/cs46xx_lib.h | 2 +- trunk/sound/pci/cs46xx/dsp_spos.h | 2 +- trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c | 2 +- trunk/sound/pci/cs5535audio/Makefile | 7 +- trunk/sound/pci/cs5535audio/cs5535audio.c | 24 +- trunk/sound/pci/cs5535audio/cs5535audio.h | 42 +- trunk/sound/pci/cs5535audio/cs5535audio_pcm.c | 10 +- trunk/sound/pci/cs5535audio/cs5535audio_pm.c | 26 +- trunk/sound/pci/echoaudio/echoaudio.c | 33 +- trunk/sound/pci/echoaudio/echoaudio_dsp.c | 4 +- trunk/sound/pci/echoaudio/echoaudio_dsp.h | 15 +- trunk/sound/pci/emu10k1/Makefile | 2 +- trunk/sound/pci/emu10k1/emu10k1.c | 4 +- trunk/sound/pci/emu10k1/emu10k1_main.c | 130 +- trunk/sound/pci/emu10k1/emu10k1x.c | 9 +- trunk/sound/pci/emu10k1/emufx.c | 251 +- trunk/sound/pci/emu10k1/emumixer.c | 86 +- trunk/sound/pci/emu10k1/emumpu401.c | 2 +- trunk/sound/pci/emu10k1/emupcm.c | 2 +- trunk/sound/pci/emu10k1/emuproc.c | 58 +- trunk/sound/pci/emu10k1/io.c | 12 +- trunk/sound/pci/emu10k1/irq.c | 2 +- trunk/sound/pci/emu10k1/memory.c | 2 +- trunk/sound/pci/emu10k1/p16v.c | 19 +- trunk/sound/pci/emu10k1/voice.c | 2 +- trunk/sound/pci/ens1370.c | 44 +- trunk/sound/pci/es1938.c | 22 +- trunk/sound/pci/es1968.c | 28 +- trunk/sound/pci/fm801.c | 4 +- trunk/sound/pci/hda/Makefile | 27 +- trunk/sound/pci/hda/hda_codec.c | 735 ++---- trunk/sound/pci/hda/hda_codec.h | 113 +- trunk/sound/pci/hda/hda_generic.c | 100 +- trunk/sound/pci/hda/hda_hwdep.c | 122 - trunk/sound/pci/hda/hda_intel.c | 382 +-- trunk/sound/pci/hda/hda_local.h | 193 +- trunk/sound/pci/hda/hda_patch.h | 16 - trunk/sound/pci/hda/hda_proc.c | 30 +- trunk/sound/pci/hda/patch_analog.c | 524 ++--- trunk/sound/pci/hda/patch_atihdmi.c | 16 + trunk/sound/pci/hda/patch_cmedia.c | 24 + trunk/sound/pci/hda/patch_conexant.c | 156 +- trunk/sound/pci/hda/patch_realtek.c | 1840 ++++----------- trunk/sound/pci/hda/patch_si3054.c | 20 +- trunk/sound/pci/hda/patch_sigmatel.c | 1000 ++------ trunk/sound/pci/hda/patch_via.c | 80 +- trunk/sound/pci/ice1712/Makefile | 2 +- trunk/sound/pci/ice1712/ak4xxx.c | 4 +- trunk/sound/pci/ice1712/amp.c | 2 +- trunk/sound/pci/ice1712/amp.h | 2 +- trunk/sound/pci/ice1712/aureon.c | 45 +- trunk/sound/pci/ice1712/delta.c | 13 +- trunk/sound/pci/ice1712/delta.h | 2 +- trunk/sound/pci/ice1712/envy24ht.h | 2 +- trunk/sound/pci/ice1712/ews.c | 20 +- trunk/sound/pci/ice1712/ews.h | 2 +- trunk/sound/pci/ice1712/hoontech.c | 2 +- trunk/sound/pci/ice1712/hoontech.h | 2 +- trunk/sound/pci/ice1712/ice1712.c | 52 +- trunk/sound/pci/ice1712/ice1712.h | 5 +- trunk/sound/pci/ice1712/ice1724.c | 54 +- trunk/sound/pci/ice1712/juli.c | 2 +- trunk/sound/pci/ice1712/phase.c | 23 +- trunk/sound/pci/ice1712/pontis.c | 27 +- trunk/sound/pci/ice1712/prodigy192.c | 27 +- trunk/sound/pci/ice1712/wtm.c | 29 +- trunk/sound/pci/intel8x0.c | 4 +- trunk/sound/pci/intel8x0m.c | 4 +- trunk/sound/pci/korg1212/Makefile | 2 +- trunk/sound/pci/korg1212/korg1212.c | 4 + trunk/sound/pci/maestro3.c | 2 + trunk/sound/pci/mixart/Makefile | 2 +- trunk/sound/pci/mixart/mixart.c | 10 +- trunk/sound/pci/mixart/mixart_mixer.c | 9 +- trunk/sound/pci/nm256/Makefile | 2 +- trunk/sound/pci/nm256/nm256.c | 1 + trunk/sound/pci/pcxhr/pcxhr.c | 5 - trunk/sound/pci/pcxhr/pcxhr_mixer.c | 15 +- trunk/sound/pci/rme32.c | 33 +- trunk/sound/pci/rme96.c | 41 +- trunk/sound/pci/rme9652/Makefile | 2 +- trunk/sound/pci/rme9652/hdsp.c | 90 +- trunk/sound/pci/rme9652/hdspm.c | 723 +++--- trunk/sound/pci/rme9652/rme9652.c | 27 +- trunk/sound/pci/sonicvibes.c | 4 +- trunk/sound/pci/trident/Makefile | 2 +- trunk/sound/pci/trident/trident.c | 2 +- trunk/sound/pci/trident/trident_main.c | 22 +- trunk/sound/pci/trident/trident_memory.c | 2 +- trunk/sound/pci/via82xx.c | 19 +- trunk/sound/pci/via82xx_modem.c | 8 +- trunk/sound/pci/vx222/Makefile | 2 +- trunk/sound/pci/ymfpci/Makefile | 2 +- trunk/sound/pci/ymfpci/ymfpci.c | 4 +- trunk/sound/pci/ymfpci/ymfpci_main.c | 108 +- trunk/sound/pcmcia/Makefile | 2 +- trunk/sound/pcmcia/pdaudiocf/Makefile | 2 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c | 4 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf.h | 2 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 2 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | 2 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 2 +- trunk/sound/pcmcia/vx/Makefile | 2 +- trunk/sound/pcmcia/vx/vxp_mixer.c | 9 +- trunk/sound/ppc/Makefile | 2 +- trunk/sound/ppc/daca.c | 10 +- trunk/sound/ppc/pmac.c | 57 +- trunk/sound/ppc/pmac.h | 4 +- trunk/sound/ppc/snd_ps3.c | 1 + trunk/sound/sh/aica.c | 10 +- trunk/sound/soc/codecs/Kconfig | 20 - trunk/sound/soc/codecs/Makefile | 2 - trunk/sound/soc/codecs/cs4270.c | 805 ------- trunk/sound/soc/codecs/cs4270.h | 28 - trunk/sound/soc/pxa/spitz.c | 1 + trunk/sound/soc/s3c24xx/Kconfig | 2 +- trunk/sound/soc/s3c24xx/s3c24xx-i2s.c | 1 - trunk/sound/soc/s3c24xx/s3c24xx-pcm.c | 22 +- trunk/sound/soc/soc-core.c | 20 + trunk/sound/soc/soc-dapm.c | 2 +- trunk/sound/sparc/cs4231.c | 805 ++++--- trunk/sound/sparc/dbri.c | 581 +++-- trunk/sound/spi/Kconfig | 31 - trunk/sound/spi/Makefile | 5 - trunk/sound/spi/at73c213.c | 1129 --------- trunk/sound/spi/at73c213.h | 119 - trunk/sound/synth/Makefile | 2 +- trunk/sound/synth/emux/Makefile | 2 +- trunk/sound/synth/util_mem.c | 2 +- trunk/sound/usb/Kconfig | 2 - trunk/sound/usb/caiaq/caiaq-audio.c | 1 - trunk/sound/usb/caiaq/caiaq-device.c | 18 +- trunk/sound/usb/caiaq/caiaq-device.h | 1 - trunk/sound/usb/caiaq/caiaq-input.c | 28 +- trunk/sound/usb/usbaudio.c | 46 +- trunk/sound/usb/usbmidi.c | 46 +- trunk/sound/usb/usbmixer.c | 11 +- trunk/sound/usb/usbquirks.h | 100 +- 1496 files changed, 36971 insertions(+), 46844 deletions(-) delete mode 100644 trunk/Documentation/block/00-INDEX delete mode 100644 trunk/Documentation/fb/uvesafb.txt delete mode 100644 trunk/Documentation/sound/alsa/powersave.txt delete mode 100644 trunk/arch/um/drivers/vde.h delete mode 100644 trunk/arch/um/drivers/vde_kern.c delete mode 100644 trunk/arch/um/drivers/vde_user.c create mode 100644 trunk/arch/um/include/choose-mode.h create mode 100644 trunk/arch/um/include/mode.h create mode 100644 trunk/arch/um/include/mode_kern.h create mode 100644 trunk/arch/um/include/skas/mmu-skas.h create mode 100644 trunk/arch/um/include/skas/mode_kern_skas.h create mode 100644 trunk/arch/um/include/skas/uaccess-skas.h create mode 100644 trunk/arch/um/include/sysdep-i386/thread.h create mode 100644 trunk/arch/um/include/sysdep-x86_64/thread.h create mode 100644 trunk/arch/um/include/tt/debug.h create mode 100644 trunk/arch/um/include/tt/mmu-tt.h create mode 100644 trunk/arch/um/include/tt/mode-tt.h create mode 100644 trunk/arch/um/include/tt/mode_kern_tt.h create mode 100644 trunk/arch/um/include/tt/tt.h create mode 100644 trunk/arch/um/include/tt/uaccess-tt.h create mode 100644 trunk/arch/um/include/uml_uaccess.h create mode 100644 trunk/arch/um/kernel/skas/exec.c create mode 100644 trunk/arch/um/kernel/skas/mem.c create mode 100644 trunk/arch/um/kernel/skas/tlb.c create mode 100644 trunk/arch/um/kernel/tt/Makefile create mode 100644 trunk/arch/um/kernel/tt/exec_kern.c create mode 100644 trunk/arch/um/kernel/tt/exec_user.c create mode 100644 trunk/arch/um/kernel/tt/gdb.c create mode 100644 trunk/arch/um/kernel/tt/gdb_kern.c create mode 100644 trunk/arch/um/kernel/tt/include/mode-tt.h create mode 100644 trunk/arch/um/kernel/tt/ksyms.c create mode 100644 trunk/arch/um/kernel/tt/mem.c create mode 100644 trunk/arch/um/kernel/tt/mem_user.c create mode 100644 trunk/arch/um/kernel/tt/process_kern.c create mode 100644 trunk/arch/um/kernel/tt/ptproxy/Makefile create mode 100644 trunk/arch/um/kernel/tt/ptproxy/proxy.c create mode 100644 trunk/arch/um/kernel/tt/ptproxy/ptproxy.h create mode 100644 trunk/arch/um/kernel/tt/ptproxy/ptrace.c create mode 100644 trunk/arch/um/kernel/tt/ptproxy/sysdep.c create mode 100644 trunk/arch/um/kernel/tt/ptproxy/sysdep.h create mode 100644 trunk/arch/um/kernel/tt/ptproxy/wait.c create mode 100644 trunk/arch/um/kernel/tt/ptproxy/wait.h create mode 100644 trunk/arch/um/kernel/tt/syscall_kern.c create mode 100644 trunk/arch/um/kernel/tt/syscall_user.c create mode 100644 trunk/arch/um/kernel/tt/tlb.c create mode 100644 trunk/arch/um/kernel/tt/tracer.c create mode 100644 trunk/arch/um/kernel/tt/trap_user.c create mode 100644 trunk/arch/um/kernel/tt/uaccess.c create mode 100644 trunk/arch/um/kernel/tt/uaccess_user.c delete mode 100644 trunk/arch/um/os-Linux/registers.c create mode 100644 trunk/arch/um/os-Linux/tt.c create mode 100644 trunk/arch/um/sys-i386/sigcontext.c create mode 100644 trunk/arch/um/sys-i386/unmap.c create mode 100644 trunk/arch/um/sys-x86_64/sigcontext.c create mode 100644 trunk/arch/um/sys-x86_64/unmap.c delete mode 100644 trunk/drivers/dca/Kconfig delete mode 100644 trunk/drivers/dca/Makefile delete mode 100644 trunk/drivers/dca/dca-core.c delete mode 100644 trunk/drivers/dca/dca-sysfs.c delete mode 100644 trunk/drivers/dma/ioat.c delete mode 100644 trunk/drivers/dma/ioat_dca.c rename trunk/drivers/dma/{ioat_dma.c => ioatdma.c} (55%) delete mode 100644 trunk/drivers/rtc/rtc-ds1374.c delete mode 100644 trunk/drivers/video/bf54x-lq043fb.c delete mode 100644 trunk/drivers/video/uvesafb.c delete mode 100644 trunk/fs/ecryptfs/read_write.c delete mode 100644 trunk/include/asm-blackfin/mach-bf548/bf54x-lq043.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/war.h create mode 100644 trunk/include/asm-mips/xxs1500.h delete mode 100644 trunk/include/linux/dca.h delete mode 100644 trunk/include/linux/page-isolation.h delete mode 100644 trunk/include/linux/pageblock-flags.h delete mode 100644 trunk/include/linux/spi/at73c213.h delete mode 100644 trunk/include/sound/cs4231-regs.h delete mode 100644 trunk/include/sound/hda_hwdep.h delete mode 100644 trunk/include/video/uvesafb.h create mode 100644 trunk/mm/filemap.h delete mode 100644 trunk/mm/page_isolation.c delete mode 100644 trunk/mm/sparse-vmemmap.c delete mode 100755 trunk/scripts/checkkconfigsymbols.sh delete mode 100755 trunk/scripts/kconfig/check.sh create mode 100644 trunk/sound/core/oss/plugin_ops.h delete mode 100644 trunk/sound/isa/sc6000.c delete mode 100644 trunk/sound/pci/hda/hda_hwdep.c delete mode 100644 trunk/sound/soc/codecs/cs4270.c delete mode 100644 trunk/sound/soc/codecs/cs4270.h delete mode 100644 trunk/sound/spi/Kconfig delete mode 100644 trunk/sound/spi/Makefile delete mode 100644 trunk/sound/spi/at73c213.c delete mode 100644 trunk/sound/spi/at73c213.h diff --git a/[refs] b/[refs] index b479ca2051d4..efe777d72a54 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5cae826e9e54a31f06b4c11b73f4af29e2ea4932 +refs/heads/master: d4697af4f3cc63f9f4d62022d79021138ecc0499 diff --git a/trunk/CREDITS b/trunk/CREDITS index 99566b1a6eeb..550bb2b9fe8b 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -1165,12 +1165,6 @@ S: 600 North Bell Avenue, Suite 160 S: Carnegie, Pennsylvania 15106-4304 S: USA -N: Kai Germaschewski -E: kai@germaschewski.name -D: Major kbuild rework during the 2.5 cycle -D: ISDN Maintainer -S: USA - N: Philip Gladstone E: philip@gladstonefamily.net D: Kernel / timekeeping stuff @@ -1939,7 +1933,7 @@ M: seasons@makosteszta.sote.hu D: Original author of software suspend N: Jaroslav Kysela -E: perex@perex.cz +E: perex@suse.cz W: http://www.perex.cz D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters D: ISA PnP @@ -2708,7 +2702,7 @@ S: Canada K2P 0X8 N: Mikael Pettersson E: mikpe@it.uu.se -W: http://user.it.uu.se/~mikpe/linux/ +W: http://www.csd.uu.se/~mikpe/ D: Miscellaneous fixes N: Reed H. Petty diff --git a/trunk/Documentation/DMA-mapping.txt b/trunk/Documentation/DMA-mapping.txt index 3c8ae020b6a7..e07f2530326b 100644 --- a/trunk/Documentation/DMA-mapping.txt +++ b/trunk/Documentation/DMA-mapping.txt @@ -514,7 +514,7 @@ With scatterlists, you map a region gathered from several regions by: int i, count = pci_map_sg(dev, sglist, nents, direction); struct scatterlist *sg; - for_each_sg(sglist, sg, count, i) { + for (i = 0, sg = sglist; i < count; i++, sg++) { hw_address[i] = sg_dma_address(sg); hw_len[i] = sg_dma_len(sg); } @@ -782,5 +782,5 @@ following people: Jay Estabrook Thomas Sailer Andrea Arcangeli - Jens Axboe + Jens Axboe David Mosberger-Tang diff --git a/trunk/Documentation/HOWTO b/trunk/Documentation/HOWTO index dceb30921498..c64e969dc33b 100644 --- a/trunk/Documentation/HOWTO +++ b/trunk/Documentation/HOWTO @@ -330,7 +330,7 @@ Here is a list of some of the different kernel trees available: - ACPI development tree, Len Brown git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git - - Block development tree, Jens Axboe + - Block development tree, Jens Axboe git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git - DRM development tree, Dave Airlie diff --git a/trunk/Documentation/block/00-INDEX b/trunk/Documentation/block/00-INDEX deleted file mode 100644 index 961a0513f8c3..000000000000 --- a/trunk/Documentation/block/00-INDEX +++ /dev/null @@ -1,20 +0,0 @@ -00-INDEX - - This file -as-iosched.txt - - Anticipatory IO scheduler -barrier.txt - - I/O Barriers -biodoc.txt - - Notes on the Generic Block Layer Rewrite in Linux 2.5 -capability.txt - - Generic Block Device Capability (/sys/block//capability) -deadline-iosched.txt - - Deadline IO scheduler tunables -ioprio.txt - - Block io priorities (in CFQ scheduler) -request.txt - - The members of struct request (in include/linux/blkdev.h) -stat.txt - - Block layer statistics in /sys/block//stat -switching-sched.txt - - Switching I/O schedulers at runtime diff --git a/trunk/Documentation/block/as-iosched.txt b/trunk/Documentation/block/as-iosched.txt index 738b72be128e..a598fe10a297 100644 --- a/trunk/Documentation/block/as-iosched.txt +++ b/trunk/Documentation/block/as-iosched.txt @@ -20,10 +20,15 @@ actually has a head for each physical device in the logical RAID device. However, setting the antic_expire (see tunable parameters below) produces very similar behavior to the deadline IO scheduler. + Selecting IO schedulers ----------------------- -Refer to Documentation/block/switching-sched.txt for information on -selecting an io scheduler on a per-device basis. +To choose IO schedulers at boot time, use the argument 'elevator=deadline'. +'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are +assigned globally at boot time only presently. It's also possible to change +the IO scheduler for a determined device on the fly, as described in +Documentation/block/switching-sched.txt. + Anticipatory IO scheduler Policies ---------------------------------- @@ -110,7 +115,7 @@ statistics (average think time, average seek distance) on the process that submitted the just completed request are examined. If it seems likely that that process will submit another request soon, and that request is likely to be near the just completed request, then the IO -scheduler will stop dispatching more read requests for up to (antic_expire) +scheduler will stop dispatching more read requests for up time (antic_expire) milliseconds, hoping that process will submit a new request near the one that just completed. If such a request is made, then it is dispatched immediately. If the antic_expire wait time expires, then the IO scheduler @@ -160,13 +165,3 @@ The parameters are: for big seek time devices though not a linear correspondence - most processes have only a few ms thinktime. -In addition to the tunables above there is a read-only file named est_time -which, when read, will show: - - - The probability of a task exiting without a cooperating task - submitting an anticipated IO. - - - The current mean think time. - - - The seek distance used to determine if an incoming IO is better. - diff --git a/trunk/Documentation/block/biodoc.txt b/trunk/Documentation/block/biodoc.txt index 93f223b9723f..dc3f49e3e539 100644 --- a/trunk/Documentation/block/biodoc.txt +++ b/trunk/Documentation/block/biodoc.txt @@ -2,7 +2,7 @@ ===================================================== Notes Written on Jan 15, 2002: - Jens Axboe + Jens Axboe Suparna Bhattacharya Last Updated May 2, 2002 @@ -21,7 +21,7 @@ Credits: --------- 2.5 bio rewrite: - Jens Axboe + Jens Axboe Many aspects of the generic block layer redesign were driven by and evolved over discussions, prior patches and the collective experience of several diff --git a/trunk/Documentation/block/deadline-iosched.txt b/trunk/Documentation/block/deadline-iosched.txt index c23cab13c3d1..be08ffd1e9b8 100644 --- a/trunk/Documentation/block/deadline-iosched.txt +++ b/trunk/Documentation/block/deadline-iosched.txt @@ -5,10 +5,16 @@ This little file attempts to document how the deadline io scheduler works. In particular, it will clarify the meaning of the exposed tunables that may be of interest to power users. -Selecting IO schedulers ------------------------ -Refer to Documentation/block/switching-sched.txt for information on -selecting an io scheduler on a per-device basis. +Each io queue has a set of io scheduler tunables associated with it. These +tunables control how the io scheduler works. You can find these entries +in: + +/sys/block//queue/iosched + +assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted, +you can do so by typing: + +# mount none /sys -t sysfs ******************************************************************************** @@ -35,11 +41,14 @@ fifo_batch When a read request expires its deadline, we must move some requests from the sorted io scheduler list to the block device dispatch queue. fifo_batch -controls how many requests we move. +controls how many requests we move, based on the cost of each request. A +request is either qualified as a seek or a stream. The io scheduler knows +the last request that was serviced by the drive (or will be serviced right +before this one). See seek_cost and stream_unit. -writes_starved (number of dispatches) --------------- +write_starved (number of dispatches) +------------- When we have to move requests from the io scheduler queue to the block device dispatch queue, we always give a preference to reads. However, we @@ -64,6 +73,6 @@ that comes at basically 0 cost we leave that on. We simply disable the rbtree front sector lookup when the io scheduler merge function is called. -Nov 11 2002, Jens Axboe +Nov 11 2002, Jens Axboe diff --git a/trunk/Documentation/block/ioprio.txt b/trunk/Documentation/block/ioprio.txt index 8ed8c59380b4..35e516b0b8a9 100644 --- a/trunk/Documentation/block/ioprio.txt +++ b/trunk/Documentation/block/ioprio.txt @@ -180,4 +180,4 @@ int main(int argc, char *argv[]) ---> snip ionice.c tool <--- -March 11 2005, Jens Axboe +March 11 2005, Jens Axboe diff --git a/trunk/Documentation/block/request.txt b/trunk/Documentation/block/request.txt index 754e104ed369..fff58acb40a3 100644 --- a/trunk/Documentation/block/request.txt +++ b/trunk/Documentation/block/request.txt @@ -1,7 +1,7 @@ struct request documentation -Jens Axboe 27/05/02 +Jens Axboe 27/05/02 1.0 Index diff --git a/trunk/Documentation/block/switching-sched.txt b/trunk/Documentation/block/switching-sched.txt index 634c952e1964..5fa130a67531 100644 --- a/trunk/Documentation/block/switching-sched.txt +++ b/trunk/Documentation/block/switching-sched.txt @@ -1,18 +1,3 @@ -To choose IO schedulers at boot time, use the argument 'elevator=deadline'. -'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are -assigned globally at boot time only presently. - -Each io queue has a set of io scheduler tunables associated with it. These -tunables control how the io scheduler works. You can find these entries -in: - -/sys/block//queue/iosched - -assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted, -you can do so by typing: - -# mount none /sys -t sysfs - As of the Linux 2.6.10 kernel, it is now possible to change the IO scheduler for a given block device on the fly (thus making it possible, for instance, to set the CFQ scheduler for the system default, but @@ -35,9 +20,3 @@ noop anticipatory deadline [cfq] # echo anticipatory > /sys/block/hda/queue/scheduler # cat /sys/block/hda/queue/scheduler noop [anticipatory] deadline cfq - -Each io queue has a set of io scheduler tunables associated with it. These -tunables control how the io scheduler works. You can find these entries -in: - -/sys/block//queue/iosched diff --git a/trunk/Documentation/cachetlb.txt b/trunk/Documentation/cachetlb.txt index 552cabac0608..866b76139420 100644 --- a/trunk/Documentation/cachetlb.txt +++ b/trunk/Documentation/cachetlb.txt @@ -133,6 +133,12 @@ changes occur: The ia64 sn2 platform is one example of a platform that uses this interface. +8) void lazy_mmu_prot_update(pte_t pte) + This interface is called whenever the protection on + any user PTEs change. This interface provides a notification + to architecture specific code to take appropriate action. + + Next, we have the cache flushing interfaces. In general, when Linux is changing an existing virtual-->physical mapping to a new value, the sequence will be in one of the following forms: diff --git a/trunk/Documentation/cpusets.txt b/trunk/Documentation/cpusets.txt index ec9de6917f01..f2c0a6842930 100644 --- a/trunk/Documentation/cpusets.txt +++ b/trunk/Documentation/cpusets.txt @@ -35,8 +35,7 @@ CONTENTS: ---------------------- Cpusets provide a mechanism for assigning a set of CPUs and Memory -Nodes to a set of tasks. In this document "Memory Node" refers to -an on-line node that contains memory. +Nodes to a set of tasks. Cpusets constrain the CPU and Memory placement of tasks to only the resources within a tasks current cpuset. They form a nested @@ -87,6 +86,9 @@ This can be especially valuable on: and a database), or * NUMA systems running large HPC applications with demanding performance characteristics. + * Also cpu_exclusive cpusets are useful for servers running orthogonal + workloads such as RT applications requiring low latency and HPC + applications that are throughput sensitive These subsets, or "soft partitions" must be able to be dynamically adjusted, as the job mix changes, without impacting other concurrently @@ -129,6 +131,8 @@ Cpusets extends these two mechanisms as follows: - A cpuset may be marked exclusive, which ensures that no other cpuset (except direct ancestors and descendents) may contain any overlapping CPUs or Memory Nodes. + Also a cpu_exclusive cpuset would be associated with a sched + domain. - You can list all the tasks (by pid) attached to any cpuset. The implementation of cpusets requires a few, simple hooks @@ -140,6 +144,9 @@ into the rest of the kernel, none in performance critical paths: allowed in that tasks cpuset. - in sched.c migrate_all_tasks(), to keep migrating tasks within the CPUs allowed by their cpuset, if possible. + - in sched.c, a new API partition_sched_domains for handling + sched domain changes associated with cpu_exclusive cpusets + and related changes in both sched.c and arch/ia64/kernel/domain.c - in the mbind and set_mempolicy system calls, to mask the requested Memory Nodes by what's allowed in that tasks cpuset. - in page_alloc.c, to restrict memory to allowed nodes. @@ -213,8 +220,8 @@ and name space for cpusets, with a minimum of additional kernel code. The cpus and mems files in the root (top_cpuset) cpuset are read-only. The cpus file automatically tracks the value of cpu_online_map using a CPU hotplug notifier, and the mems file -automatically tracks the value of node_states[N_MEMORY]--i.e., -nodes with memory--using the cpuset_track_online_nodes() hook. +automatically tracks the value of node_online_map using the +cpuset_track_online_nodes() hook. 1.4 What are exclusive cpusets ? @@ -224,6 +231,15 @@ If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct ancestor or descendent, may share any of the same CPUs or Memory Nodes. +A cpuset that is cpu_exclusive has a scheduler (sched) domain +associated with it. The sched domain consists of all CPUs in the +current cpuset that are not part of any exclusive child cpusets. +This ensures that the scheduler load balancing code only balances +against the CPUs that are in the sched domain as defined above and +not all of the CPUs in the system. This removes any overhead due to +load balancing code trying to pull tasks outside of the cpu_exclusive +cpuset only to be prevented by the tasks' cpus_allowed mask. + A cpuset that is mem_exclusive restricts kernel allocations for page, buffer and other data commonly shared by the kernel across multiple users. All cpusets, whether mem_exclusive or not, restrict diff --git a/trunk/Documentation/fb/00-INDEX b/trunk/Documentation/fb/00-INDEX index caabbd395e61..92e89aeef52e 100644 --- a/trunk/Documentation/fb/00-INDEX +++ b/trunk/Documentation/fb/00-INDEX @@ -5,49 +5,21 @@ please mail me. 00-INDEX - this file -arkfb.txt - - info on the fbdev driver for ARK Logic chips. -aty128fb.txt - - info on the ATI Rage128 frame buffer driver. -cirrusfb.txt - - info on the driver for Cirrus Logic chipsets. -cyblafb/ - - directory with documentation files related to the cyblafb driver. -deferred_io.txt - - an introduction to deferred IO. -fbcon.txt - - intro to and usage guide for the framebuffer console (fbcon). framebuffer.txt - - introduction to frame buffer devices. -imacfb.txt - - info on the generic EFI platform driver for Intel based Macs. -intel810.txt - - documentation for the Intel 810/815 framebuffer driver. -intelfb.txt - - docs for Intel 830M/845G/852GM/855GM/865G/915G/945G fb driver. + - introduction to frame buffer devices internals.txt - - quick overview of frame buffer device internals. -matroxfb.txt - - info on the Matrox framebuffer driver for Alpha, Intel and PPC. + - quick overview of frame buffer device internals modedb.txt - - info on the video mode database. + - info on the video mode database +aty128fb.txt + - info on the ATI Rage128 frame buffer driver +clgenfb.txt + - info on the Cirrus Logic frame buffer driver matroxfb.txt - - info on the Matrox frame buffer driver. + - info on the Matrox frame buffer driver pvr2fb.txt - - info on the PowerVR 2 frame buffer driver. -pxafb.txt - - info on the driver for the PXA25x LCD controller. -s3fb.txt - - info on the fbdev driver for S3 Trio/Virge chips. -sa1100fb.txt - - information about the driver for the SA-1100 LCD controller. -sisfb.txt - - info on the framebuffer device driver for various SiS chips. -sstfb.txt - - info on the frame buffer driver for 3dfx' Voodoo Graphics boards. + - info on the PowerVR 2 frame buffer driver tgafb.txt - info on the TGA (DECChip 21030) frame buffer driver vesafb.txt - info on the VESA frame buffer device -vt8623fb.txt - - info on the fb driver for the graphics core in VIA VT8623 chipsets. diff --git a/trunk/Documentation/fb/uvesafb.txt b/trunk/Documentation/fb/uvesafb.txt deleted file mode 100644 index bcfc233a0080..000000000000 --- a/trunk/Documentation/fb/uvesafb.txt +++ /dev/null @@ -1,188 +0,0 @@ - -uvesafb - A Generic Driver for VBE2+ compliant video cards -========================================================== - -1. Requirements ---------------- - -uvesafb should work with any video card that has a Video BIOS compliant -with the VBE 2.0 standard. - -Unlike other drivers, uvesafb makes use of a userspace helper called -v86d. v86d is used to run the x86 Video BIOS code in a simulated and -controlled environment. This allows uvesafb to function on arches other -than x86. Check the v86d documentation for a list of currently supported -arches. - -v86d source code can be downloaded from the following website: - http://dev.gentoo.org/~spock/projects/uvesafb - -Please refer to the v86d documentation for detailed configuration and -installation instructions. - -Note that the v86d userspace helper has to be available at all times in -order for uvesafb to work properly. If you want to use uvesafb during -early boot, you will have to include v86d into an initramfs image, and -either compile it into the kernel or use it as an initrd. - -2. Caveats and limitations --------------------------- - -uvesafb is a _generic_ driver which supports a wide variety of video -cards, but which is ultimately limited by the Video BIOS interface. -The most important limitations are: - -- Lack of any type of acceleration. -- A strict and limited set of supported video modes. Often the native - or most optimal resolution/refresh rate for your setup will not work - with uvesafb, simply because the Video BIOS doesn't support the - video mode you want to use. This can be especially painful with - widescreen panels, where native video modes don't have the 4:3 aspect - ratio, which is what most BIOS-es are limited to. -- Adjusting the refresh rate is only possible with a VBE 3.0 compliant - Video BIOS. Note that many nVidia Video BIOS-es claim to be VBE 3.0 - compliant, while they simply ignore any refresh rate settings. - -3. Configuration ----------------- - -uvesafb can be compiled either as a module, or directly into the kernel. -In both cases it supports the same set of configuration options, which -are either given on the kernel command line or as module parameters, e.g.: - - video=uvesafb:1024x768-32,mtrr:3,ywrap (compiled into the kernel) - - # modprobe uvesafb mode=1024x768-32 mtrr=3 scroll=ywrap (module) - -Accepted options: - -ypan Enable display panning using the VESA protected mode - interface. The visible screen is just a window of the - video memory, console scrolling is done by changing the - start of the window. Available on x86 only. - -ywrap Same as ypan, but assumes your gfx board can wrap-around - the video memory (i.e. starts reading from top if it - reaches the end of video memory). Faster than ypan. - Available on x86 only. - -redraw Scroll by redrawing the affected part of the screen, this - is the safe (and slow) default. - -(If you're using uvesafb as a module, the above three options are - used a parameter of the scroll option, e.g. scroll=ypan.) - -vgapal Use the standard VGA registers for palette changes. - -pmipal Use the protected mode interface for palette changes. - This is the default if the protected mode interface is - available. Available on x86 only. - -mtrr:n Setup memory type range registers for the framebuffer - where n: - 0 - disabled (equivalent to nomtrr) (default) - 1 - uncachable - 2 - write-back - 3 - write-combining - 4 - write-through - - If you see the following in dmesg, choose the type that matches - the old one. In this example, use "mtrr:2". -... -mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining -... - -nomtrr Do not use memory type range registers. - -vremap:n - Remap 'n' MiB of video RAM. If 0 or not specified, remap memory - according to video mode. - -vtotal:n - If the video BIOS of your card incorrectly determines the total - amount of video RAM, use this option to override the BIOS (in MiB). - - The mode you want to set, in the standard modedb format. Refer to - modedb.txt for a detailed description. When uvesafb is compiled as - a module, the mode string should be provided as a value of the - 'mode' option. - -vbemode:x - Force the use of VBE mode x. The mode will only be set if it's - found in the VBE-provided list of supported modes. - NOTE: The mode number 'x' should be specified in VESA mode number - notation, not the Linux kernel one (eg. 257 instead of 769). - HINT: If you use this option because normal parameter does - not work for you and you use a X server, you'll probably want to - set the 'nocrtc' option to ensure that the video mode is properly - restored after console <-> X switches. - -nocrtc Do not use CRTC timings while setting the video mode. This option - has any effect only if the Video BIOS is VBE 3.0 compliant. Use it - if you have problems with modes set the standard way. Note that - using this option implies that any refresh rate adjustments will - be ignored and the refresh rate will stay at your BIOS default (60 Hz). - -noedid Do not try to fetch and use EDID-provided modes. - -noblank Disable hardware blanking. - -v86d:path - Set path to the v86d executable. This option is only available as - a module parameter, and not as a part of the video= string. If you - need to use it and have uvesafb built into the kernel, use - uvesafb.v86d="path". - -Additionally, the following parameters may be provided. They all override the -EDID-provided values and BIOS defaults. Refer to your monitor's specs to get -the correct values for maxhf, maxvf and maxclk for your hardware. - -maxhf:n Maximum horizontal frequency (in kHz). -maxvf:n Maximum vertical frequency (in Hz). -maxclk:n Maximum pixel clock (in MHz). - -4. The sysfs interface ----------------------- - -uvesafb provides several sysfs nodes for configurable parameters and -additional information. - -Driver attributes: - -/sys/bus/platform/drivers/uvesafb - - v86d (default: /sbin/v86d) - Path to the v86d executable. v86d is started by uvesafb - if an instance of the daemon isn't already running. - -Device attributes: - -/sys/bus/platform/drivers/uvesafb/uvesafb.0 - - nocrtc - Use the default refresh rate (60 Hz) if set to 1. - - - oem_product_name - - oem_product_rev - - oem_string - - oem_vendor - Information about the card and its maker. - - - vbe_modes - A list of video modes supported by the Video BIOS along with their - VBE mode numbers in hex. - - - vbe_version - A BCD value indicating the implemented VBE standard. - -5. Miscellaneous ----------------- - -Uvesafb will set a video mode with the default refresh rate and timings -from the Video BIOS if you set pixclock to 0 in fb_var_screeninfo. - - --- - Michal Januszewski - Last updated: 2007-06-16 - - Documentation of the uvesafb options is loosely based on vesafb.txt. - diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index fe26cc978523..f0f825808ca4 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -178,18 +178,15 @@ prototypes: locking rules: All except set_page_dirty may block - BKL PageLocked(page) i_sem + BKL PageLocked(page) writepage: no yes, unlocks (see below) readpage: no yes, unlocks sync_page: no maybe writepages: no set_page_dirty no no readpages: no -prepare_write: no yes yes -commit_write: no yes yes -write_begin: no locks the page yes -write_end: no yes, unlocks yes -perform_write: no n/a yes +prepare_write: no yes +commit_write: no yes bmap: yes invalidatepage: no yes releasepage: no yes diff --git a/trunk/Documentation/filesystems/vfs.txt b/trunk/Documentation/filesystems/vfs.txt index 6f8e16e3d6c0..045f3e055a28 100644 --- a/trunk/Documentation/filesystems/vfs.txt +++ b/trunk/Documentation/filesystems/vfs.txt @@ -537,12 +537,6 @@ struct address_space_operations { struct list_head *pages, unsigned nr_pages); int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); - int (*write_begin)(struct file *, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata); - int (*write_end)(struct file *, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata); sector_t (*bmap)(struct address_space *, sector_t); int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); @@ -621,7 +615,11 @@ struct address_space_operations { any basic-blocks on storage, then those blocks should be pre-read (if they haven't been read already) so that the updated blocks can be written out properly. - The page will be locked. + The page will be locked. If prepare_write wants to unlock the + page it, like readpage, may do so and return + AOP_TRUNCATED_PAGE. + In this case the prepare_write will be retried one the lock is + regained. Note: the page _must not_ be marked uptodate in this function (or anywhere else) unless it actually is uptodate right now. As @@ -635,45 +633,6 @@ struct address_space_operations { operations. It should avoid returning an error if possible - errors should have been handled by prepare_write. - write_begin: This is intended as a replacement for prepare_write. The - key differences being that: - - it returns a locked page (in *pagep) rather than being - given a pre locked page; - - it must be able to cope with short writes (where the - length passed to write_begin is greater than the number - of bytes copied into the page). - - Called by the generic buffered write code to ask the filesystem to - prepare to write len bytes at the given offset in the file. The - address_space should check that the write will be able to complete, - by allocating space if necessary and doing any other internal - housekeeping. If the write will update parts of any basic-blocks on - storage, then those blocks should be pre-read (if they haven't been - read already) so that the updated blocks can be written out properly. - - The filesystem must return the locked pagecache page for the specified - offset, in *pagep, for the caller to write into. - - flags is a field for AOP_FLAG_xxx flags, described in - include/linux/fs.h. - - A void * may be returned in fsdata, which then gets passed into - write_end. - - Returns 0 on success; < 0 on failure (which is the error code), in - which case write_end is not called. - - write_end: After a successful write_begin, and data copy, write_end must - be called. len is the original len passed to write_begin, and copied - is the amount that was able to be copied (copied == len is always true - if write_begin was called with the AOP_FLAG_UNINTERRUPTIBLE flag). - - The filesystem must take care of unlocking the page and releasing it - refcount, and updating i_size. - - Returns < 0 on failure, otherwise the number of bytes (<= 'copied') - that were able to be copied into pagecache. - bmap: called by the VFS to map a logical block offset within object to physical block number. This method is used by the FIBMAP ioctl and for working with swap-files. To be able to swap to diff --git a/trunk/Documentation/ide.txt b/trunk/Documentation/ide.txt index 1d50f23a5cab..3bb9f9c98611 100644 --- a/trunk/Documentation/ide.txt +++ b/trunk/Documentation/ide.txt @@ -242,8 +242,6 @@ Summary of ide driver parameters for kernel command line and quite likely to cause trouble with older/odd IDE drives. - "hdx=nodma" : disallow DMA - "hdx=swapdata" : when the drive is a disk, byte swap all data "hdx=bswap" : same as above.......... @@ -280,6 +278,8 @@ Summary of ide driver parameters for kernel command line "idex=four" : four drives on idex and ide(x^1) share same ports "idex=reset" : reset interface after probe + + "idex=dma" : automatically configure/use DMA if possible. "idex=ata66" : informs the interface that it has an 80c cable for chipsets that are ATA-66 capable, but the @@ -288,6 +288,8 @@ Summary of ide driver parameters for kernel command line "ide=reverse" : formerly called to pci sub-system, but now local. + "ide=nodma" : disable DMA globally for the IDE subsystem. + The following are valid ONLY on ide0, which usually corresponds to the first ATA interface found on the particular host, and the defaults for the base,ctl ports must not be altered. diff --git a/trunk/Documentation/kbuild/makefiles.txt b/trunk/Documentation/kbuild/makefiles.txt index f099b814d383..e08ef8759a07 100644 --- a/trunk/Documentation/kbuild/makefiles.txt +++ b/trunk/Documentation/kbuild/makefiles.txt @@ -276,39 +276,41 @@ more details, with real examples. --- 3.7 Compilation flags - ccflags-y, asflags-y and ldflags-y - The three flags listed above applies only to the kbuild makefile - where they are assigned. They are used for all the normal - cc, as and ld invocation happenign during a recursive build. - Note: Flags with the same behaviour were previously named: - EXTRA_CFLAGS, EXTRA_AFLAGS and EXTRA_LDFLAGS. - They are yet supported but their use are deprecated. + EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS - ccflags-y specifies options for compiling C files with $(CC). + All the EXTRA_ variables apply only to the kbuild makefile + where they are assigned. The EXTRA_ variables apply to all + commands executed in the kbuild makefile. + + $(EXTRA_CFLAGS) specifies options for compiling C files with + $(CC). Example: # drivers/sound/emu10k1/Makefile - ccflags-y += -I$(obj) - ccflags-$(DEBUG) += -DEMU10K1_DEBUG + EXTRA_CFLAGS += -I$(obj) + ifdef DEBUG + EXTRA_CFLAGS += -DEMU10K1_DEBUG + endif This variable is necessary because the top Makefile owns the - variable $(KBUILD_CFLAGS) and uses it for compilation flags for the + variable $(CFLAGS) and uses it for compilation flags for the entire tree. - asflags-y is a similar string for per-directory options + $(EXTRA_AFLAGS) is a similar string for per-directory options when compiling assembly language source. Example: #arch/x86_64/kernel/Makefile - asflags-y := -traditional + EXTRA_AFLAGS := -traditional - ldflags-y is a string for per-directory options to $(LD). + $(EXTRA_LDFLAGS) and $(EXTRA_ARFLAGS) are similar strings for + per-directory options to $(LD) and $(AR). Example: #arch/m68k/fpsp040/Makefile - ldflags-y := -x + EXTRA_LDFLAGS := -x CFLAGS_$@, AFLAGS_$@ @@ -423,7 +425,6 @@ more details, with real examples. as-instr checks if the assembler reports a specific instruction and then outputs either option1 or option2 C escapes are supported in the test instruction - Note: as-instr-option uses KBUILD_AFLAGS for $(AS) options cc-option cc-option is used to check if $(CC) supports a given option, and not @@ -437,7 +438,6 @@ more details, with real examples. -march=pentium-mmx if supported by $(CC), otherwise -march=i586. The second argument to cc-option is optional, and if omitted, cflags-y will be assigned no value if first option is not supported. - Note: cc-option uses KBUILD_CFLAGS for $(CC) options cc-option-yn cc-option-yn is used to check if gcc supports a given option @@ -453,7 +453,6 @@ more details, with real examples. option. When $(biarch) equals 'y', the expanded variables $(aflags-y) and $(cflags-y) will be assigned the values -a32 and -m32, respectively. - Note: cc-option-yn uses KBUILD_CFLAGS for $(CC) options cc-option-align gcc versions >= 3.0 changed the type of options used to specify @@ -465,11 +464,10 @@ more details, with real examples. cc-option-align = -falign Example: - KBUILD_CFLAGS += $(cc-option-align)-functions=4 + CFLAGS += $(cc-option-align)-functions=4 In the above example, the option -falign-functions=4 is used for gcc >= 3.00. For gcc < 3.00, -malign-functions=4 is used. - Note: cc-option-align uses KBUILD_CFLAGS for $(CC) options cc-version cc-version returns a numerical version of the $(CC) compiler version. @@ -494,9 +492,9 @@ more details, with real examples. Example: #fs/reiserfs/Makefile - ccflags-y := $(call cc-ifversion, -lt, 0402, -O1) + EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0402, -O1) - In this example, ccflags-y will be assigned the value -O1 if the + In this example, EXTRA_CFLAGS will be assigned the value -O1 if the $(CC) version is less than 4.2. cc-ifversion takes all the shell operators: -eq, -ne, -lt, -le, -gt, and -ge @@ -782,8 +780,8 @@ When kbuild executes, the following steps are followed (roughly): Example: #arch/s390/Makefile LDFLAGS := -m elf_s390 - Note: ldflags-y can be used to further customise - the flags used. See chapter 3.7. + Note: EXTRA_LDFLAGS and LDFLAGS_$@ can be used to further customise + the flags used. See chapter 7. LDFLAGS_MODULE Options for $(LD) when linking modules @@ -819,26 +817,26 @@ When kbuild executes, the following steps are followed (roughly): In this example, the binary $(obj)/image is a binary version of vmlinux. The usage of $(call if_changed,xxx) will be described later. - KBUILD_AFLAGS $(AS) assembler flags + AFLAGS $(AS) assembler flags Default value - see top level Makefile Append or modify as required per architecture. Example: #arch/sparc64/Makefile - KBUILD_AFLAGS += -m64 -mcpu=ultrasparc + AFLAGS += -m64 -mcpu=ultrasparc - KBUILD_CFLAGS $(CC) compiler flags + CFLAGS $(CC) compiler flags Default value - see top level Makefile Append or modify as required per architecture. - Often, the KBUILD_CFLAGS variable depends on the configuration. + Often, the CFLAGS variable depends on the configuration. Example: #arch/i386/Makefile cflags-$(CONFIG_M386) += -march=i386 - KBUILD_CFLAGS += $(cflags-y) + CFLAGS += $(cflags-y) Many arch Makefiles dynamically run the target C compiler to probe supported options: @@ -850,7 +848,7 @@ When kbuild executes, the following steps are followed (roughly): -march=pentium2,-march=i686) ... # Disable unit-at-a-time mode ... - KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time) + CFLAGS += $(call cc-option,-fno-unit-at-a-time) ... @@ -1098,8 +1096,8 @@ When kbuild executes, the following steps are followed (roughly): specified options when building the target vmlinux.lds. When building the *.lds target, kbuild uses the variables: - KBUILD_CPPFLAGS : Set in top-level Makefile - cppflags-y : May be set in the kbuild makefile + CPPFLAGS : Set in top-level Makefile + EXTRA_CPPFLAGS : May be set in the kbuild makefile CPPFLAGS_$(@F) : Target specific flags. Note that the full filename is used in this assignment. diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index eb247997f679..085e4a095eaa 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -349,11 +349,6 @@ and is between 256 and 4096 characters. It is defined in the file blkmtd_bs= blkmtd_count= - boot_delay= Milliseconds to delay each printk during boot. - Values larger than 10 seconds (10000) are changed to - no delay (0). - Format: integer - bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) bttv.radio= Most important insmod options are available as kernel args too. @@ -911,11 +906,6 @@ and is between 256 and 4096 characters. It is defined in the file n must be a power of two. The default size is set in the kernel config file. - logo.nologo [FB] Disables display of the built-in Linux logo. - This may be used to provide more screen space for - kernel log messages and is useful when debugging - kernel boot problems. - lp=0 [LP] Specify parallel ports to use, e.g, lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses lp=reset first parallel port). 'lp=0' disables the diff --git a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt index 4b48c2e82c3c..241e26c4ff92 100644 --- a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt @@ -365,14 +365,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-cmipci ----------------- - Module for C-Media CMI8338/8738/8768/8770 PCI sound cards. + Module for C-Media CMI8338 and 8738 PCI sound cards. - mpu_port - port address of MIDI interface (8338 only): - 0x300,0x310,0x320,0x330 = legacy port, + mpu_port - 0x300,0x310,0x320,0x330 = legacy port, + 1 = integrated PCI port, 0 = disable (default) - fm_port - port address of OPL-3 FM synthesizer (8x38 only): - 0x388 = legacy port, - 1 = integrated PCI port (default on 8738), + fm_port - 0x388 = legacy port, + 1 = integrated PCI port (default), 0 = disable soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only) (default = 1) @@ -769,10 +768,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. single_cmd - Use single immediate commands to communicate with codecs (for debugging only) enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) - power_save - Automatic power-saving timtout (in second, 0 = - disable) - power_save_controller - Reset HD-audio controller in power-saving mode - (default = on) This module supports one card and autoprobe. @@ -833,8 +828,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ALC268 3stack 3-stack model - toshiba Toshiba A205 - acer Acer laptops auto auto-config reading BIOS (default) ALC662 @@ -849,11 +842,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-dig 3-jack with SPDIF I/O 6stack-dig 6-jack digital with SPDIF I/O arima Arima W820Di1 - targa Targa T8, MSI-1049 T8 - asus-a7j ASUS A7J - asus-a7m ASUS A7M macpro MacPro support - mbp3 Macbook Pro rev3 imac24 iMac 24'' with jack detection w2jc ASUS W2JC auto auto-config reading BIOS (default) @@ -865,7 +854,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O 6stack-dig-demo 6-jack digital for Intel demo board acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) - acer-aspire Acer Aspire 9810 medion Medion Laptops medion-md2 Medion MD2 targa-dig Targa/MSI @@ -874,7 +862,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. lenovo-101e Lenovo 101E lenovo-nb0763 Lenovo NB0763 lenovo-ms7195-dig Lenovo MS7195 - haier-w66 Haier W66 6stack-hp HP machines with 6stack (Nettle boards) 3stack-hp HP machines with 3stack (Lucknow, Samba boards) auto auto-config reading BIOS (default) @@ -898,7 +885,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD) lenovo Lenovo 3000 C200 dallas Dallas laptops - hp HP TX1000 auto auto-config reading BIOS (default) CMI9880 @@ -934,7 +920,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack 3-stack, shared surrounds laptop 2-channel only (FSC V2060, Samsung M50) laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J) - laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100) ultra 2-channel with EAPD (Samsung Ultra tablet PC) AD1988 @@ -960,30 +945,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. can be adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y - STAC9200 + STAC9200/9205/9254 ref Reference board - dell-d21 Dell (unknown) - dell-d22 Dell (unknown) - dell-d23 Dell (unknown) - dell-m21 Dell Inspiron 630m, Dell Inspiron 640m - dell-m22 Dell Latitude D620, Dell Latitude D820 - dell-m23 Dell XPS M1710, Dell Precision M90 - dell-m24 Dell Latitude 120L - dell-m25 Dell Inspiron E1505n - dell-m26 Dell Inspiron 1501 - dell-m27 Dell Inspiron E1705/9400 - gateway Gateway laptops with EAPD control - - STAC9205/9254 - ref Reference board - dell-m42 Dell (unknown) - dell-m43 Dell Precision - dell-m44 Dell Inspiron STAC9220/9221 ref Reference board 3stack D945 3stack 5stack D945 5stack + SPDIF + dell Dell XPS M1210 intel-mac-v1 Intel Mac Type 1 intel-mac-v2 Intel Mac Type 2 intel-mac-v3 Intel Mac Type 3 @@ -995,10 +964,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3) imac-intel Intel iMac (eq. type 2) imac-intel-20 Intel iMac (newer version) (eq. type 3) - dell-d81 Dell (unknown) - dell-d82 Dell (unknown) - dell-m81 Dell (unknown) - dell-m82 Dell XPS M1210 STAC9202/9250/9251 ref Reference board, base config @@ -1010,7 +975,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ref Reference board 3stack D965 3stack 5stack D965 5stack + SPDIF - dell-3stack Dell Dimension E520 STAC9872 vaio Setup for VAIO FE550G/SZ110 @@ -1025,9 +989,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel ML (see the section "Links and Addresses"). - power_save and power_save_controller options are for power-saving - mode. See powersave.txt for details. - Note 2: If you get click noises on output, try the module option position_fix=1 or 2. position_fix=1 will use the SD_LPIB register value without FIFO size correction as the current @@ -1388,6 +1349,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. port - port number or -1 (disable) irq - IRQ number or -1 (disable) pnp - PnP detection - 0 = disable, 1 = enable (default) + uart_enter - Issue UART_ENTER command at open - bool, default = on This module supports multiple devices and PnP. @@ -1668,21 +1630,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. The power-management is supported. - Module snd-sc6000 - ----------------- - - Module for Gallant SC-6000 soundcard. - - port - Port # (0x220 or 0x240) - mss_port - MSS Port # (0x530 or 0xe80) - irq - IRQ # (5,7,9,10,11) - mpu_irq - MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq - dma - DMA # (1,3,0) - - This module supports multiple cards. - - This card is also known as Audio Excel DSP 16 or Zoltrix AV302. - Module snd-sgalaxy ------------------ @@ -1703,11 +1650,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for ENSONIQ SoundScape PnP cards. port - Port # (PnP setup) - wss_port - WSS Port # (PnP setup) irq - IRQ # (PnP setup) mpu_irq - MPU-401 IRQ # (PnP setup) dma - DMA # (PnP setup) - dma2 - 2nd DMA # (PnP setup, -1 to disable) This module supports multiple cards. ISA PnP must be enabled. You need sscape_ctl tool in alsa-tools package for loading @@ -1752,52 +1697,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. dma2 - DMA2 # for CS4232 PCM interface. isapnp - ISA PnP detection - 0 = disable, 1 = enable (default) - The below are options for wavefront_synth features: - wf_raw - Assume that we need to boot the OS (default:no) - If yes, then during driver loading, the state of the board is - ignored, and we reset the board and load the firmware anyway. - fx_raw - Assume that the FX process needs help (default:yes) - If false, we'll leave the FX processor in whatever state it is - when the driver is loaded. The default is to download the - microprogram and associated coefficients to set it up for - "default" operation, whatever that means. - debug_default - Debug parameters for card initialization - wait_usecs - How long to wait without sleeping, usecs - (default:150) - This magic number seems to give pretty optimal throughput - based on my limited experimentation. - If you want to play around with it and find a better value, be - my guest. Remember, the idea is to get a number that causes us - to just busy wait for as many WaveFront commands as possible, - without coming up with a number so large that we hog the whole - CPU. - Specifically, with this number, out of about 134,000 status - waits, only about 250 result in a sleep. - sleep_interval - How long to sleep when waiting for reply - (default: 100) - sleep_tries - How many times to try sleeping during a wait - (default: 50) - ospath - Pathname to processed ICS2115 OS firmware - (default:wavefront.os) - The path name of the ISC2115 OS firmware. In the recent - version, it's handled via firmware loader framework, so it - must be installed in the proper path, typically, - /lib/firmware. - reset_time - How long to wait for a reset to take effect - (default:2) - ramcheck_time - How many seconds to wait for the RAM test - (default:20) - osrun_time - How many seconds to wait for the ICS2115 OS - (default:10) - This module supports multiple cards and ISA PnP. - Note: the firmware file "wavefront.os" was located in the earlier - version in /etc. Now it's loaded via firmware loader, and - must be in the proper firmware path, such as /lib/firmware. - Copy (or symlink) the file appropriately if you get an error - regarding firmware downloading after upgrading the kernel. - Module snd-sonicvibes --------------------- diff --git a/trunk/Documentation/sound/alsa/CMIPCI.txt b/trunk/Documentation/sound/alsa/CMIPCI.txt index 16935c8561f7..4b2b15387056 100644 --- a/trunk/Documentation/sound/alsa/CMIPCI.txt +++ b/trunk/Documentation/sound/alsa/CMIPCI.txt @@ -1,5 +1,5 @@ - Brief Notes on C-Media 8338/8738/8768/8770 Driver - ================================================= + Brief Notes on C-Media 8738/8338 Driver + ======================================= Takashi Iwai @@ -209,13 +209,10 @@ In addition to the standard SB mixer, CM8x38 provides more functions. MIDI CONTROLLER --------------- -With CMI8338 chips, the MPU401-UART interface is disabled as default. -You need to set the module option "mpu_port" to a valid I/O port address -to enable MIDI support. Valid I/O ports are 0x300, 0x310, 0x320 and -0x330. Choose a value that doesn't conflict with other cards. - -With CMI8738 and newer chips, the MIDI interface is enabled by default -and the driver automatically chooses a port address. +The MPU401-UART interface is disabled as default. You need to set +module option "mpu_port" with a valid I/O port address to enable the +MIDI support. The valid I/O ports are 0x300, 0x310, 0x320 and 0x330. +Choose the value which doesn't conflict with other cards. There is _no_ hardware wavetable function on this chip (except for OPL3 synth below). @@ -233,8 +230,6 @@ Set "fm_port" module option for more cards. The output quality of FM OPL/3 is, however, very weird. I don't know why.. -CMI8768 and newer chips do not have the FM synth. - Joystick and Modem ------------------ diff --git a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 2c3fc3cb3b6b..74d3a35b59bc 100644 --- a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -18,8 +18,8 @@ - September 10, 2007 - 0.3.7 + November 17, 2005 + 0.3.6 @@ -405,9 +405,8 @@ /* definition of the chip-specific record */ struct mychip { struct snd_card *card; - /* rest of implementation will be in the section - * "PCI Resource Managements" - */ + // rest of implementation will be in the section + // "PCI Resource Managements" }; /* chip-specific destructor @@ -415,7 +414,7 @@ */ static int snd_mychip_free(struct mychip *chip) { - .... /* will be implemented later... */ + .... // will be implemented later... } /* component-destructor @@ -441,9 +440,8 @@ *rchip = NULL; - /* check PCI availability here - * (see "PCI Resource Managements") - */ + // check PCI availability here + // (see "PCI Resource Managements") .... /* allocate a chip-specific data with zero filled */ @@ -453,13 +451,12 @@ chip->card = card; - /* rest of initialization here; will be implemented - * later, see "PCI Resource Managements" - */ + // rest of initialization here; will be implemented + // later, see "PCI Resource Managements" .... - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + chip, &ops)) < 0) { snd_mychip_free(chip); return err; } @@ -493,8 +490,7 @@ return -ENOMEM; /* (3) */ - err = snd_mychip_create(card, pci, &chip); - if (err < 0) { + if ((err = snd_mychip_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; } @@ -506,11 +502,10 @@ card->shortname, chip->ioport, chip->irq); /* (5) */ - .... /* implemented later */ + .... // implemented later /* (6) */ - err = snd_card_register(card); - if (err < 0) { + if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } @@ -610,8 +605,7 @@ irq >= 0) @@ -1126,8 +1119,7 @@ *rchip = NULL; /* initialize the PCI entry */ - err = pci_enable_device(pci); - if (err < 0) + if ((err = pci_enable_device(pci)) < 0) return err; /* check PCI availability (28bit DMA) */ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || @@ -1149,8 +1141,7 @@ chip->irq = -1; /* (1) PCI resource allocation */ - err = pci_request_regions(pci, "My Chip"); - if (err < 0) { + if ((err = pci_request_regions(pci, "My Chip")) < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1165,10 +1156,10 @@ chip->irq = pci->irq; /* (2) initialization of the chip hardware */ - .... /* (not implemented in this document) */ + .... // (not implemented in this document) - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + chip, &ops)) < 0) { snd_mychip_free(chip); return err; } @@ -1242,8 +1233,7 @@ irq, snd_mychip_interrupt, - IRQF_SHARED, "My Chip", chip)) { + IRQF_DISABLED|IRQF_SHARED, "My Chip", chip)) { printk(KERN_ERR "cannot grab irq %d\n", pci->irq); snd_mychip_free(chip); return -EBUSY; @@ -1784,8 +1773,7 @@ struct snd_pcm_runtime *runtime = substream->runtime; runtime->hw = snd_mychip_playback_hw; - /* more hardware-initialization will be done here */ - .... + // more hardware-initialization will be done here return 0; } @@ -1793,8 +1781,7 @@ static int snd_mychip_playback_close(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); - /* the hardware-specific codes will be here */ - .... + // the hardware-specific codes will be here return 0; } @@ -1806,8 +1793,7 @@ struct snd_pcm_runtime *runtime = substream->runtime; runtime->hw = snd_mychip_capture_hw; - /* more hardware-initialization will be done here */ - .... + // more hardware-initialization will be done here return 0; } @@ -1815,8 +1801,7 @@ static int snd_mychip_capture_close(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); - /* the hardware-specific codes will be here */ - .... + // the hardware-specific codes will be here return 0; } @@ -1859,12 +1844,10 @@ { switch (cmd) { case SNDRV_PCM_TRIGGER_START: - /* do something to start the PCM engine */ - .... + // do something to start the PCM engine break; case SNDRV_PCM_TRIGGER_STOP: - /* do something to stop the PCM engine */ - .... + // do something to stop the PCM engine break; default: return -EINVAL; @@ -1917,8 +1900,8 @@ struct snd_pcm *pcm; int err; - err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm); - if (err < 0) + if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, + &pcm)) < 0) return err; pcm->private_data = chip; strcpy(pcm->name, "My Chip"); @@ -1956,8 +1939,8 @@ struct snd_pcm *pcm; int err; - err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm); - if (err < 0) + if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, + &pcm)) < 0) return err; pcm->private_data = chip; strcpy(pcm->name, "My Chip"); @@ -2114,7 +2097,7 @@ struct mychip *chip = snd_pcm_chip(pcm); /* free your own data */ kfree(chip->my_private_pcm_data); - /* do what you like else */ + // do what you like else .... } @@ -2901,10 +2884,10 @@ struct _snd_pcm_runtime { lock); snd_pcm_period_elapsed(chip->substream); spin_lock(&chip->lock); - /* acknowledge the interrupt if necessary */ + // acknowledge the interrupt if necessary } .... spin_unlock(&chip->lock); @@ -3151,7 +3134,7 @@ struct _snd_pcm_runtime { snd_pcm_period_elapsed(substream); spin_lock(&chip->lock); } - /* acknowledge the interrupt if necessary */ + // acknowledge the interrupt if necessary } .... spin_unlock(&chip->lock); @@ -3472,13 +3455,6 @@ struct _snd_pcm_runtime { (casted to unsigned long) of some record to this field, too. - - The tlv field can be used to provide - metadata about the control; see the - - Metadata subsection. - - The other three are @@ -3628,7 +3604,7 @@ struct _snd_pcm_runtime { Example of info callback type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; @@ -3663,7 +3639,7 @@ struct _snd_pcm_runtime { - - - Some common info callbacks are prepared for easy use: - snd_ctl_boolean_mono_info() and - snd_ctl_boolean_stereo_info(). - Obviously, the former is an info callback for a mono channel - boolean item, just like snd_myctl_mono_info - above, and the latter is for a stereo channel boolean item. - -
@@ -3828,8 +3794,7 @@ struct _snd_pcm_runtime { @@ -3878,56 +3843,6 @@ struct _snd_pcm_runtime {
-
- Metadata - - To provide information about the dB values of a mixer control, use - on of the DECLARE_TLV_xxx macros from - <sound/tlv.h> to define a variable - containing this information, set thetlv.p - field to point to this variable, and include the - SNDRV_CTL_ELEM_ACCESS_TLV_READ flag in the - access field; like this: - - - - - - - - - The DECLARE_TLV_DB_SCALE macro defines - information about a mixer control where each step in the control's - value changes the dB value by a constant dB amount. - The first parameter is the name of the variable to be defined. - The second parameter is the minimum value, in units of 0.01 dB. - The third parameter is the step size, in units of 0.01 dB. - Set the fourth parameter to 1 if the minimum value actually mutes - the control. - - - - The DECLARE_TLV_DB_LINEAR macro defines - information about a mixer control where the control's value affects - the output linearly. - The first parameter is the name of the variable to be defined. - The second parameter is the minimum value, in units of 0.01 dB. - The third parameter is the maximum value, in units of 0.01 dB. - If the minimum value mutes the control, set the second parameter to - TLV_DB_GAIN_MUTE. - -
- @@ -3965,7 +3880,7 @@ struct _snd_pcm_runtime { { struct mychip *chip = ac97->private_data; .... - /* read a register value here from the codec */ + // read a register value here from the codec return the_register_value; } @@ -3974,7 +3889,7 @@ struct _snd_pcm_runtime { { struct mychip *chip = ac97->private_data; .... - /* write the given register value to the codec */ + // write the given register value to the codec } static int snd_mychip_ac97(struct mychip *chip) @@ -3987,8 +3902,7 @@ struct _snd_pcm_runtime { .read = snd_mychip_ac97_read, }; - err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus); - if (err < 0) + if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; @@ -4533,10 +4447,10 @@ struct _snd_pcm_runtime { streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, - list { + list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { + substream = list_entry(list, struct snd_rawmidi_substream, list); sprintf(substream->name, "My MIDI Port %d", substream->number + 1); } /* same for SNDRV_RAWMIDI_STREAM_INPUT */ diff --git a/trunk/Documentation/sound/alsa/OSS-Emulation.txt b/trunk/Documentation/sound/alsa/OSS-Emulation.txt index 022aaeb0e9dd..bfa0c9aacb4b 100644 --- a/trunk/Documentation/sound/alsa/OSS-Emulation.txt +++ b/trunk/Documentation/sound/alsa/OSS-Emulation.txt @@ -303,3 +303,10 @@ ICE1712 supports only the unconventional format, interleaved the buffer as the conventional (mono or 2-channels, 8 or 16bit) format on OSS. +USB devices +----------- +Some USB devices support only 24bit format packed in 3bytes. This +format is not supported by OSS and no conversion is provided by kernel +OSS emulation. You can use the user-space OSS emulation via libaoss +instead. + diff --git a/trunk/Documentation/sound/alsa/hda_codec.txt b/trunk/Documentation/sound/alsa/hda_codec.txt index 8e1b02526698..4eaae2a45534 100644 --- a/trunk/Documentation/sound/alsa/hda_codec.txt +++ b/trunk/Documentation/sound/alsa/hda_codec.txt @@ -49,9 +49,6 @@ struct hda_bus_ops { unsigned int verb, unsigned int parm); unsigned int (*get_response)(struct hda_codec *codec); void (*private_free)(struct hda_bus *); -#ifdef CONFIG_SND_HDA_POWER_SAVE - void (*pm_notify)(struct hda_codec *codec); -#endif }; The command callback is called when the codec module needs to send a @@ -59,16 +56,9 @@ VERB to the controller. It's always a single command. The get_response callback is called when the codec requires the answer for the last command. These two callbacks are mandatory and have to be given. -The third, private_free callback, is optional. It's called in the +The last, private_free callback, is optional. It's called in the destructor to release any necessary data in the lowlevel driver. -The pm_notify callback is available only with -CONFIG_SND_HDA_POWER_SAVE kconfig. It's called when the codec needs -to power up or may power down. The controller should check the all -belonging codecs on the bus whether they are actually powered off -(check codec->power_on), and optionally the driver may power down the -contoller side, too. - The bus instance is created via snd_hda_bus_new(). You need to pass the card instance, the template, and the pointer to store the resultant bus instance. @@ -96,8 +86,10 @@ resultant codec instance (can be NULL if not needed). The codec is stored in a linked list of bus instance. You can follow the codec list like: + struct list_head *p; struct hda_codec *codec; - list_for_each_entry(codec, &bus->codec_list, list) { + list_for_each(p, &bus->codec_list) { + codec = list_entry(p, struct hda_codec, list); ... } @@ -108,15 +100,10 @@ initialization sequence is called when the controls are built later. Codec Access ============ -To access codec, use snd_hda_codec_read() and snd_hda_codec_write(). +To access codec, use snd_codec_read() and snd_codec_write(). snd_hda_param_read() is for reading parameters. For writing a sequence of verbs, use snd_hda_sequence_write(). -There are variants of cached read/write, snd_hda_codec_write_cache(), -snd_hda_sequence_write_cache(). These are used for recording the -register states for the power-mangement resume. When no PM is needed, -these are equivalent with non-cached version. - To retrieve the number of sub nodes connected to the given node, use snd_hda_get_sub_nodes(). The connection list can be obtained via snd_hda_get_connections() call. @@ -252,10 +239,6 @@ set the codec->patch_ops field. This is defined as below: int (*suspend)(struct hda_codec *codec, pm_message_t state); int (*resume)(struct hda_codec *codec); #endif - #ifdef CONFIG_SND_HDA_POWER_SAVE - int (*check_power_status)(struct hda_codec *codec, - hda_nid_t nid); - #endif }; The build_controls callback is called from snd_hda_build_controls(). @@ -268,18 +251,6 @@ The unsol_event callback is called when an unsolicited event is received. The suspend and resume callbacks are for power management. -They can be NULL if no special sequence is required. When the resume -callback is NULL, the driver calls the init callback and resumes the -registers from the cache. If other handling is needed, you'd need to -write your own resume callback. There, the amp values can be resumed -via - void snd_hda_codec_resume_amp(struct hda_codec *codec); -and the other codec registers via - void snd_hda_codec_resume_cache(struct hda_codec *codec); - -The check_power_status callback is called when the amp value of the -given widget NID is changed. The codec code can turn on/off the power -appropriately from this information. Each entry can be NULL if not necessary to be called. @@ -296,7 +267,8 @@ Digital I/O =========== Call snd_hda_create_spdif_out_ctls() from the patch to create controls -related with SPDIF out. +related with SPDIF out. In the patch resume callback, call +snd_hda_resume_spdif(). Helper Functions @@ -312,7 +284,12 @@ as a module parameter, and PCI subsystem IDs. If the matching entry is found, it returns the config field value. snd_hda_add_new_ctls() can be used to create and add control entries. -Pass the zero-terminated array of struct snd_kcontrol_new +Pass the zero-terminated array of struct snd_kcontrol_new. The same array +can be passed to snd_hda_resume_ctls() for resume. +Note that this will call control->put callback of these entries. So, +put callback should check codec->in_resume and force to restore the +given value if it's non-zero even if the value is identical with the +cached value. Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be used for the entry of struct snd_kcontrol_new. diff --git a/trunk/Documentation/sound/alsa/powersave.txt b/trunk/Documentation/sound/alsa/powersave.txt deleted file mode 100644 index 9657e8099228..000000000000 --- a/trunk/Documentation/sound/alsa/powersave.txt +++ /dev/null @@ -1,41 +0,0 @@ -Notes on Power-Saving Mode -========================== - -AC97 and HD-audio drivers have the automatic power-saving mode. -This feature is enabled via Kconfig CONFIG_SND_AC97_POWER_SAVE -and CONFIG_SND_HDA_POWER_SAVE options, respectively. - -With the automatic power-saving, the driver turns off the codec power -appropriately when no operation is required. When no applications use -the device and/or no analog loopback is set, the power disablement is -done fully or partially. It'll save a certain power consumption, thus -good for laptops (even for desktops). - -The time-out for automatic power-off can be specified via power_save -module option of snd-ac97-codec and snd-hda-intel modules. Specify -the time-out value in seconds. 0 means to disable the automatic -power-saving. The default value of timeout is given via -CONFIG_SND_AC97_POWER_SAVE_DEFAULT and -CONFIG_SND_HDA_POWER_SAVE_DEFAULT Kconfig options. Setting this to 1 -(the minimum value) isn't recommended because many applications try to -reopen the device frequently. 10 would be a good choice for normal -operations. - -The power_save option is exported as writable. This means you can -adjust the value via sysfs on the fly. For example, to turn on the -automatic power-save mode with 10 seconds, write to -/sys/modules/snd_ac97_codec/parameters/power_save (usually as root): - - # echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save - - -Note that you might hear click noise/pop when changing the power -state. Also, it often takes certain time to wake up from the -power-down to the active state. These are often hardly to fix, so -don't report extra bug reports unless you have a fix patch ;-) - -For HD-audio interface, there is another module option, -power_save_controller. This enables/disables the power-save mode of -the controller side. Setting this on may reduce a bit more power -consumption, but might result in longer wake-up time and click noise. -Try to turn it off when you experience such a thing too often. diff --git a/trunk/Documentation/spi/spi-summary b/trunk/Documentation/spi/spi-summary index 8861e47e5a2d..76ea6c837be5 100644 --- a/trunk/Documentation/spi/spi-summary +++ b/trunk/Documentation/spi/spi-summary @@ -156,29 +156,21 @@ using the driver model to connect controller and protocol drivers using device tables provided by board specific initialization code. SPI shows up in sysfs in several locations: - /sys/devices/.../CTLR ... physical node for a given SPI controller - /sys/devices/.../CTLR/spiB.C ... spi_device on bus "B", chipselect C, accessed through CTLR. - /sys/bus/spi/devices/spiB.C ... symlink to that physical - .../CTLR/spiB.C device - /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver that should be used with this device (for hotplug/coldplug) + /sys/bus/spi/devices/spiB.C ... symlink to the physical + spiB.C device + /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices - /sys/class/spi_master/spiB ... symlink (or actual device node) to - a logical node which could hold class related state for the - controller managing bus "B". All spiB.* devices share one + /sys/class/spi_master/spiB ... class device for the controller + managing bus "B". All the spiB.* devices share the same physical SPI bus segment, with SCLK, MOSI, and MISO. -Note that the actual location of the controller's class state depends -on whether you enabled CONFIG_SYSFS_DEPRECATED or not. At this time, -the only class-specific state is the bus number ("B" in "spiB"), so -those /sys/class entries are only useful to quickly identify busses. - How does board-specific init code declare SPI devices? ------------------------------------------------------ @@ -345,8 +337,7 @@ SPI protocol drivers somewhat resemble platform device drivers: The driver core will autmatically attempt to bind this driver to any SPI device whose board_info gave a modalias of "CHIP". Your probe() code -might look like this unless you're creating a device which is managing -a bus (appearing under /sys/class/spi_master). +might look like this unless you're creating a class_device: static int __devinit CHIP_probe(struct spi_device *spi) { @@ -451,7 +442,7 @@ An SPI controller will probably be registered on the platform_bus; write a driver to bind to the device, whichever bus is involved. The main task of this type of driver is to provide an "spi_master". -Use spi_alloc_master() to allocate the master, and spi_master_get_devdata() +Use spi_alloc_master() to allocate the master, and class_get_devdata() to get the driver-private data allocated for that device. struct spi_master *master; @@ -461,7 +452,7 @@ to get the driver-private data allocated for that device. if (!master) return -ENODEV; - c = spi_master_get_devdata(master); + c = class_get_devdata(&master->cdev); The driver will initialize the fields of that spi_master, including the bus number (maybe the same as the platform device ID) and three methods diff --git a/trunk/Documentation/spi/spidev_test.c b/trunk/Documentation/spi/spidev_test.c index cf0e3ce0d526..218e86215297 100644 --- a/trunk/Documentation/spi/spidev_test.c +++ b/trunk/Documentation/spi/spidev_test.c @@ -29,7 +29,7 @@ static void pabort(const char *s) abort(); } -static const char *device = "/dev/spidev1.1"; +static char *device = "/dev/spidev1.1"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; @@ -69,7 +69,7 @@ static void transfer(int fd) puts(""); } -void print_usage(const char *prog) +void print_usage(char *prog) { printf("Usage: %s [-DsbdlHOLC3]\n", prog); puts(" -D --device device to use (default /dev/spidev1.1)\n" @@ -88,7 +88,7 @@ void print_usage(const char *prog) void parse_opts(int argc, char *argv[]) { while (1) { - static const struct option lopts[] = { + static struct option lopts[] = { { "device", 1, 0, 'D' }, { "speed", 1, 0, 's' }, { "delay", 1, 0, 'd' }, diff --git a/trunk/Documentation/vm/numa_memory_policy.txt b/trunk/Documentation/vm/numa_memory_policy.txt index dd4986497996..8242f52d0f22 100644 --- a/trunk/Documentation/vm/numa_memory_policy.txt +++ b/trunk/Documentation/vm/numa_memory_policy.txt @@ -302,30 +302,31 @@ MEMORY POLICIES AND CPUSETS Memory policies work within cpusets as described above. For memory policies that require a node or set of nodes, the nodes are restricted to the set of -nodes whose memories are allowed by the cpuset constraints. If the nodemask -specified for the policy contains nodes that are not allowed by the cpuset, or -the intersection of the set of nodes specified for the policy and the set of -nodes with memory is the empty set, the policy is considered invalid -and cannot be installed. +nodes whose memories are allowed by the cpuset constraints. If the +intersection of the set of nodes specified for the policy and the set of nodes +allowed by the cpuset is the empty set, the policy is considered invalid and +cannot be installed. The interaction of memory policies and cpusets can be problematic for a couple of reasons: -1) the memory policy APIs take physical node id's as arguments. As mentioned - above, it is illegal to specify nodes that are not allowed in the cpuset. - The application must query the allowed nodes using the get_mempolicy() - API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and - restrict itself to those nodes. However, the resources available to a - cpuset can be changed by the system administrator, or a workload manager - application, at any time. So, a task may still get errors attempting to - specify policy nodes, and must query the allowed memories again. +1) the memory policy APIs take physical node id's as arguments. However, the + memory policy APIs do not provide a way to determine what nodes are valid + in the context where the application is running. An application MAY consult + the cpuset file system [directly or via an out of tree, and not generally + available, libcpuset API] to obtain this information, but then the + application must be aware that it is running in a cpuset and use what are + intended primarily as administrative APIs. + + However, as long as the policy specifies at least one node that is valid + in the controlling cpuset, the policy can be used. 2) when tasks in two cpusets share access to a memory region, such as shared memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and MAP_SHARED flags, and any of the tasks install shared policy on the region, only nodes whose memories are allowed in both cpusets may be used in the - policies. Obtaining this information requires "stepping outside" the - memory policy APIs to use the cpuset information and requires that one - know in what cpusets other task might be attaching to the shared region. + policies. Again, obtaining this information requires "stepping outside" + the memory policy APIs, as well as knowing in what cpusets other task might + be attaching to the shared region, to use the cpuset information. Furthermore, if the cpusets' allowed memory sets are disjoint, "local" allocation is the only valid policy. diff --git a/trunk/Documentation/x86_64/mm.txt b/trunk/Documentation/x86_64/mm.txt index b89b6d2bebfa..f42798ed1c54 100644 --- a/trunk/Documentation/x86_64/mm.txt +++ b/trunk/Documentation/x86_64/mm.txt @@ -9,7 +9,6 @@ ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space -ffffe20000000000 - ffffe2ffffffffff (=40 bits) virtual memory map (1TB) ... unused hole ... ffffffff80000000 - ffffffff82800000 (=40 MB) kernel text mapping, from phys 0 ... unused hole ... diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index cc3b233ccaca..c7355e7f09ff 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1769,7 +1769,7 @@ S: Maintained HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series P: Jaroslav Kysela -M: perex@perex.cz +M: perex@suse.cz S: Maintained HPET: High Precision Event Timers driver (hpet.c) @@ -2132,12 +2132,14 @@ S: Maintained ISAPNP P: Jaroslav Kysela -M: perex@perex.cz +M: perex@suse.cz S: Maintained ISDN SUBSYSTEM P: Karsten Keil M: kkeil@suse.de +P: Kai Germaschewski +M: kai.germaschewski@gmx.de L: isdn4linux@listserv.isdn4linux.de W: http://www.isdn4linux.de T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git @@ -2206,6 +2208,8 @@ L: autofs@linux.kernel.org S: Maintained KERNEL BUILD (kbuild: Makefile, scripts/Makefile.*) +P: Kai Germaschewski +M: kai@germaschewski.name P: Sam Ravnborg M: sam@ravnborg.org T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git @@ -3519,7 +3523,7 @@ S: Maintained SOUND P: Jaroslav Kysela -M: perex@perex.cz +M: perex@suse.cz L: alsa-devel@alsa-project.org (subscribers-only) S: Maintained diff --git a/trunk/Makefile b/trunk/Makefile index ed65de7078c7..1274084c9090 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -115,20 +115,13 @@ saved-output := $(KBUILD_OUTPUT) KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) $(if $(KBUILD_OUTPUT),, \ $(error output directory "$(saved-output)" does not exist)) -# Check that OUTPUT directory is not the same as where we have kernel src -$(if $(filter-out $(KBUILD_OUTPUT),$(shell /bin/pwd)),, \ - $(error Output directory (O=...) specifies kernel src dir)) -PHONY += $(MAKECMDGOALS) sub-make +PHONY += $(MAKECMDGOALS) -$(filter-out _all sub-make,$(MAKECMDGOALS)) _all: sub-make - $(Q)@: - -sub-make: FORCE +$(filter-out _all,$(MAKECMDGOALS)) _all: $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ KBUILD_SRC=$(CURDIR) \ - KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \ - $(filter-out _all sub-make,$(MAKECMDGOALS)) + KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@ # Leave processing to above invocation of make skip-makefile := 1 @@ -318,12 +311,12 @@ LINUXINCLUDE := -Iinclude \ $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ -include include/linux/autoconf.h -KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) +CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) -KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ +CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration -KBUILD_AFLAGS := -D__ASSEMBLY__ +AFLAGS := -D__ASSEMBLY__ # Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) @@ -334,9 +327,9 @@ export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS -export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS -export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE -export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE +export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS +export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE +export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE # When compiling out-of-tree modules, put MODVERDIR in the module # tree rather than in the kernel tree. The kernel tree might @@ -492,41 +485,35 @@ endif # $(dot-config) all: vmlinux ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -KBUILD_CFLAGS += -Os +CFLAGS += -Os else -KBUILD_CFLAGS += -O2 +CFLAGS += -O2 endif include $(srctree)/arch/$(ARCH)/Makefile ifdef CONFIG_FRAME_POINTER -KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls +CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls else -KBUILD_CFLAGS += -fomit-frame-pointer +CFLAGS += -fomit-frame-pointer endif ifdef CONFIG_DEBUG_INFO -KBUILD_CFLAGS += -g -KBUILD_AFLAGS += -gdwarf-2 +CFLAGS += -g endif # Force gcc to behave correct even for buggy distributions -KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) +CFLAGS += $(call cc-option, -fno-stack-protector) # arch Makefile may override CC so keep this after arch Makefile is included NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) CHECKFLAGS += $(NOSTDINC_FLAGS) # warn about C99 declaration after statement -KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) +CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 -KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) - -# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments -KBUILD_CPPFLAGS += $(CPPFLAGS) -KBUILD_AFLAGS += $(AFLAGS) -KBUILD_CFLAGS += $(CFLAGS) +CFLAGS += $(call cc-option,-Wno-pointer-sign,) # Use --build-id when available. LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ @@ -1162,7 +1149,6 @@ help: @echo 'Static analysers' @echo ' checkstack - Generate a list of stack hogs' @echo ' namespacecheck - Name space analysis on compiled kernel' - @echo ' export_report - List the usages of all exported symbols' @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \ echo ' headers_check - Sanity check on exported headers'; \ fi @@ -1269,10 +1255,8 @@ $(clean-dirs): $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) clean: rm-dirs := $(MODVERDIR) -clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers clean: $(clean-dirs) $(call cmd,rmdirs) - $(call cmd,rmfiles) @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ @@ -1427,9 +1411,6 @@ versioncheck: namespacecheck: $(PERL) $(srctree)/scripts/namespace.pl -export_report: - $(PERL) $(srctree)/scripts/export_report.pl - endif #ifeq ($(config-targets),1) endif #ifeq ($(mixed-targets),1) @@ -1507,8 +1488,8 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) cmd_rmfiles = rm -f $(rm-files) -a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \ - $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \ +a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \ + $(NOSTDINC_FLAGS) $(CPPFLAGS) \ $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o) quiet_cmd_as_o_S = AS $@ diff --git a/trunk/arch/alpha/Makefile b/trunk/arch/alpha/Makefile index 63104ebd1806..1b704ee54bf3 100644 --- a/trunk/arch/alpha/Makefile +++ b/trunk/arch/alpha/Makefile @@ -12,28 +12,79 @@ NM := $(NM) -B LDFLAGS_vmlinux := -static -N #-relax CHECKFLAGS += -D__alpha__ -m64 -cflags-y := -pipe -mno-fp-regs -ffixed-8 -msmall-data +cflags-y := -pipe -mno-fp-regs -ffixed-8 -cpuflags-$(CONFIG_ALPHA_EV67) := -mcpu=ev67 -cpuflags-$(CONFIG_ALPHA_EV6) := -mcpu=ev6 -cpuflags-$(CONFIG_ALPHA_POLARIS) := -mcpu=pca56 -cpuflags-$(CONFIG_ALPHA_SX164) := -mcpu=pca56 -cpuflags-$(CONFIG_ALPHA_EV56) := -mcpu=ev56 -cpuflags-$(CONFIG_ALPHA_EV5) := -mcpu=ev5 -cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4 -# If GENERIC, make sure to turn off any instruction set extensions that -# the host compiler might have on by default. Given that EV4 and EV5 -# have the same instruction set, prefer EV5 because an EV5 schedule is -# more likely to keep an EV4 processor busy than vice-versa. -cpuflags-$(CONFIG_ALPHA_GENERIC) := -mcpu=ev5 +# Determine if we can use the BWX instructions with GAS. +old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) -cflags-y += $(cpuflags-y) +ifeq ($(old_gas),y) +$(error The assembler '$(AS)' does not support the BWX instruction) +endif + +# Determine if GCC understands the -mcpu= option. +have_mcpu := $(call cc-option-yn, -mcpu=ev5) +have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56) +have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6) +have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67) +have_msmall_data := $(call cc-option-yn, -msmall-data) + +cflags-$(have_msmall_data) += -msmall-data + +# Turn on the proper cpu optimizations. +ifeq ($(have_mcpu),y) + mcpu_done := n + # If GENERIC, make sure to turn off any instruction set extensions that + # the host compiler might have on by default. Given that EV4 and EV5 + # have the same instruction set, prefer EV5 because an EV5 schedule is + # more likely to keep an EV4 processor busy than vice-versa. + ifeq ($(CONFIG_ALPHA_GENERIC),y) + mcpu := ev5 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy) + mcpu := pca56 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_POLARIS)$(have_mcpu_pca56),nyy) + mcpu := pca56 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny) + mcpu := ev4 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV56),ny) + mcpu := ev56 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV5),ny) + mcpu := ev5 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy) + mcpu := ev67 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny) + ifeq ($(have_mcpu_ev6),y) + mcpu := ev6 + else + ifeq ($(have_mcpu_pca56),y) + mcpu := pca56 + else + mcpu=ev56 + endif + endif + mcpu_done := y + endif + cflags-$(mcpu_done) += -mcpu=$(mcpu) +endif # For TSUNAMI, we must have the assembler not emulate our instructions. # The same is true for IRONGATE, POLARIS, PYXIS. # BWX is most important, but we don't really want any emulation ever. -KBUILD_CFLAGS += $(cflags-y) -Wa,-mev6 +CFLAGS += $(cflags-y) -Wa,-mev6 head-y := arch/alpha/kernel/head.o diff --git a/trunk/arch/alpha/kernel/Makefile b/trunk/arch/alpha/kernel/Makefile index dccf05245d4d..ab6fa54b3860 100644 --- a/trunk/arch/alpha/kernel/Makefile +++ b/trunk/arch/alpha/kernel/Makefile @@ -3,7 +3,7 @@ # extra-y := head.o vmlinux.lds -EXTRA_AFLAGS := $(KBUILD_CFLAGS) +EXTRA_AFLAGS := $(CFLAGS) EXTRA_CFLAGS := -Werror -Wno-sign-compare obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ diff --git a/trunk/arch/alpha/kernel/entry.S b/trunk/arch/alpha/kernel/entry.S index 5fc61e281ac7..debc8f03886c 100644 --- a/trunk/arch/alpha/kernel/entry.S +++ b/trunk/arch/alpha/kernel/entry.S @@ -916,6 +916,15 @@ sys_pipe: ret .end sys_pipe + .align 4 + .globl sys_ptrace + .ent sys_ptrace +sys_ptrace: + .prologue 0 + mov $sp, $20 + jmp $31, do_sys_ptrace +.end sys_ptrace + .align 4 .globl sys_execve .ent sys_execve diff --git a/trunk/arch/alpha/kernel/ptrace.c b/trunk/arch/alpha/kernel/ptrace.c index 1e9ad52c460e..83a781842266 100644 --- a/trunk/arch/alpha/kernel/ptrace.c +++ b/trunk/arch/alpha/kernel/ptrace.c @@ -260,12 +260,38 @@ void ptrace_disable(struct task_struct *child) ptrace_cancel_bpt(child); } -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +asmlinkage long +do_sys_ptrace(long request, long pid, long addr, long data, + struct pt_regs *regs) { + struct task_struct *child; unsigned long tmp; size_t copied; long ret; + lock_kernel(); + DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n", + request, pid, addr, data)); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out_notsk; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out_notsk; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + goto out; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out; + switch (request) { /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -275,13 +301,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (copied != sizeof(tmp)) break; - force_successful_syscall_return(); + regs->r0 = 0; /* special return: no errors */ ret = tmp; break; /* Read register number ADDR. */ case PTRACE_PEEKUSR: - force_successful_syscall_return(); + regs->r0 = 0; /* special return: no errors */ ret = get_reg(child, addr); DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret)); break; @@ -327,7 +353,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* make sure single-step breakpoint is gone. */ ptrace_cancel_bpt(child); wake_up_process(child); - break; + goto out; case PTRACE_SINGLESTEP: /* execute single instruction. */ ret = -EIO; @@ -340,12 +366,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); /* give it a chance to run. */ ret = 0; - break; + goto out; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + goto out; default: ret = ptrace_request(child, request, addr, data); - break; + goto out; } + out: + put_task_struct(child); + out_notsk: + unlock_kernel(); return ret; } diff --git a/trunk/arch/alpha/kernel/vmlinux.lds.S b/trunk/arch/alpha/kernel/vmlinux.lds.S index 55c05b511f4c..7af07d3ad5f0 100644 --- a/trunk/arch/alpha/kernel/vmlinux.lds.S +++ b/trunk/arch/alpha/kernel/vmlinux.lds.S @@ -1,5 +1,4 @@ #include -#include OUTPUT_FORMAT("elf64-alpha") OUTPUT_ARCH(alpha) @@ -9,145 +8,138 @@ jiffies = jiffies_64; SECTIONS { #ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS - . = 0xfffffc0000310000; + . = 0xfffffc0000310000; #else - . = 0xfffffc0001010000; + . = 0xfffffc0001010000; #endif - _text = .; /* Text and read-only data */ - .text : { + _text = .; /* Text and read-only data */ + .text : { *(.text.head) - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) - } :kernel - _etext = .; /* End of text section */ - - /* Exception table */ - . = ALIGN(16); - __ex_table : { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - - NOTES :kernel :note - .dummy : { - *(.dummy) - } :kernel - - RODATA - - /* Will be freed after init */ - . = ALIGN(PAGE_SIZE); - /* Init code and data */ - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { - *(.init.data) - } - - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - - . = ALIGN(8); - .initcall.init : { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + *(.fixup) + *(.gnu.warning) + } :kernel + _etext = .; /* End of text section */ + + . = ALIGN(16); + __start___ex_table = .; /* Exception table */ + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + NOTES :kernel :note + .dummy : { *(.dummy) } :kernel + + RODATA + + /* Will be freed after init */ + . = ALIGN(8192); /* Init code and data */ + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { *(.init.data) } + + . = ALIGN(16); + __setup_start = .; + .init.setup : { *(.init.setup) } + __setup_end = .; + + . = ALIGN(8); + __initcall_start = .; + .initcall.init : { + INITCALLS + } + __initcall_end = .; #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } + . = ALIGN(8192); + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; #endif - . = ALIGN(8); - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - - . = ALIGN(8); - SECURITY_INIT - - PERCPU(PAGE_SIZE) - - . = ALIGN(2 * PAGE_SIZE); - __init_end = .; - /* Freed after init ends here */ - - /* Note 2 page alignment above. */ - .data.init_thread : { - *(.data.init_thread) - } - - . = ALIGN(PAGE_SIZE); - .data.page_aligned : { - *(.data.page_aligned) - } - - . = ALIGN(64); - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - - _data = .; - /* Data */ - .data : { - DATA_DATA - CONSTRUCTORS - } - - .got : { - *(.got) - } - .sdata : { - *(.sdata) - } - _edata = .; /* End of data section */ - - __bss_start = .; - .sbss : { - *(.sbss) - *(.scommon) - } - .bss : { - *(.bss) - *(COMMON) - } - __bss_stop = .; - _end = .; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.exit.text) - *(.exit.data) - *(.exitcall.exit) - } - - .mdebug 0 : { - *(.mdebug) - } - .note 0 : { - *(.note) - } - - STABS_DEBUG - DWARF_DEBUG + . = ALIGN(8); + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + + . = ALIGN(8); + SECURITY_INIT + + PERCPU(8192) + + . = ALIGN(2*8192); + __init_end = .; + /* Freed after init ends here */ + + /* Note 2 page alignment above. */ + .data.init_thread : { *(.data.init_thread) } + + . = ALIGN(8192); + .data.page_aligned : { *(.data.page_aligned) } + + . = ALIGN(64); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + _data = .; + .data : { /* Data */ + DATA_DATA + CONSTRUCTORS + } + + .got : { *(.got) } + .sdata : { *(.sdata) } + + _edata = .; /* End of data section */ + + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : { *(.bss) *(COMMON) } + __bss_stop = .; + + _end = .; + + /* Sections to be discarded */ + /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) } + + .mdebug 0 : { *(.mdebug) } + .note 0 : { *(.note) } + .comment 0 : { *(.comment) } + + /* Stabs debugging sections */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } } diff --git a/trunk/arch/alpha/lib/Makefile b/trunk/arch/alpha/lib/Makefile index 9b72c59c95be..266f78e13076 100644 --- a/trunk/arch/alpha/lib/Makefile +++ b/trunk/arch/alpha/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for alpha-specific library files.. # -EXTRA_AFLAGS := $(KBUILD_CFLAGS) +EXTRA_AFLAGS := $(CFLAGS) EXTRA_CFLAGS := -Werror # Many of these routines have implementations tuned for ev6. diff --git a/trunk/arch/alpha/mm/fault.c b/trunk/arch/alpha/mm/fault.c index 25154df3055a..a0e18da594d9 100644 --- a/trunk/arch/alpha/mm/fault.c +++ b/trunk/arch/alpha/mm/fault.c @@ -197,7 +197,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, current->comm, current->pid); if (!user_mode(regs)) goto no_context; - do_group_exit(SIGKILL); + do_exit(SIGKILL); do_sigbus: /* Send a sigbus, regardless of whether we were in kernel diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 35e56c99ad1d..6c2d539cd22b 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -14,9 +14,9 @@ LDFLAGS_vmlinux :=-p --no-undefined -X CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S GZFLAGS :=-9 -#KBUILD_CFLAGS +=-pipe +#CFLAGS +=-pipe # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: -KBUILD_CFLAGS +=$(call cc-option,-marm,) +CFLAGS +=$(call cc-option,-marm,) # Do not use arch/arm/defconfig - it's always outdated. # Select a platform tht is kept up-to-date @@ -28,15 +28,15 @@ MMUEXT := -nommu endif ifeq ($(CONFIG_FRAME_POINTER),y) -KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog +CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog endif ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) -KBUILD_CPPFLAGS += -mbig-endian +CPPFLAGS += -mbig-endian AS += -EB LD += -EB else -KBUILD_CPPFLAGS += -mlittle-endian +CPPFLAGS += -mlittle-endian AS += -EL LD += -EL endif @@ -85,8 +85,8 @@ CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-th endif # Need -Uarm for gcc < 3.x -KBUILD_CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm -KBUILD_AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float +CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm +AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float CHECKFLAGS += -D__arm__ diff --git a/trunk/arch/arm/boot/compressed/Makefile b/trunk/arch/arm/boot/compressed/Makefile index 5fde99f9d9f9..6b8cbd69f249 100644 --- a/trunk/arch/arm/boot/compressed/Makefile +++ b/trunk/arch/arm/boot/compressed/Makefile @@ -87,7 +87,7 @@ ifneq ($(PARAMS_PHYS),) LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) endif LDFLAGS_vmlinux += -p --no-undefined -X \ - $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T + $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T # Don't allow any static data in misc.o, which # would otherwise mess up our GOT table diff --git a/trunk/arch/arm/kernel/ptrace.c b/trunk/arch/arm/kernel/ptrace.c index 5feee722ea98..78c9f1a3d41f 100644 --- a/trunk/arch/arm/kernel/ptrace.c +++ b/trunk/arch/arm/kernel/ptrace.c @@ -731,6 +731,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; diff --git a/trunk/arch/arm/mach-s3c2410/mach-amlm5900.c b/trunk/arch/arm/mach-s3c2410/mach-amlm5900.c index a67a0685664d..43bb5e106302 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/trunk/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -168,31 +168,13 @@ static void __init amlm5900_map_io(void) } #ifdef CONFIG_FB_S3C2410 -static struct s3c2410fb_display __initdata amlm5900_lcd_info = { +static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = { .width = 160, .height = 160, - .type = S3C2410_LCDCON1_STN4, - - .pixclock = 680000, /* HCLK = 100MHz */ - .xres = 160, - .yres = 160, - .bpp = 4, - .left_margin = 1 << (4 + 3), - .right_margin = 8 << 3, - .hsync_len = 48, - .upper_margin = 0, - .lower_margin = 0, - - .lcdcon5 = 0x00000001, -}; - -static struct s3c2410fb_mach_info __initdata amlm5900_fb_info = { - - .displays = &amlm5900_lcd_info, - .num_displays = 1, - .default_display = 0, - +/* commented out until stn patch is submitted +* .type = S3C2410_LCDCON1_STN4, +*/ .gpccon = 0xaaaaaaaa, .gpccon_mask = 0xffffffff, .gpcup = 0x0000ffff, @@ -202,6 +184,32 @@ static struct s3c2410fb_mach_info __initdata amlm5900_fb_info = { .gpdcon_mask = 0xffffffff, .gpdup = 0x0000ffff, .gpdup_mask = 0xffffffff, + + .xres = { + .min = 160, + .max = 160, + .defval = 160, + }, + + .yres = { + .min = 160, + .max = 160, + .defval = 160, + }, + + .bpp = { + .min = 4, + .max = 4, + .defval = 4, + }, + + .regs = { + .lcdcon1 = 0x00008225, + .lcdcon2 = 0x0027c000, + .lcdcon3 = 0x00182708, + .lcdcon4 = 0x00000002, + .lcdcon5 = 0x00000001, + } }; #endif @@ -231,7 +239,7 @@ static void __init amlm5900_init(void) { amlm5900_init_pm(); #ifdef CONFIG_FB_S3C2410 - s3c24xx_fb_set_platdata(&amlm5900_fb_info); + s3c24xx_fb_set_platdata(&amlm5900_lcd_info); #endif platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices)); } diff --git a/trunk/arch/arm/mach-s3c2410/mach-bast.c b/trunk/arch/arm/mach-s3c2410/mach-bast.c index 587864fe25fb..bc926992b4e4 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-bast.c +++ b/trunk/arch/arm/mach-s3c2410/mach-bast.c @@ -467,70 +467,35 @@ static struct platform_device bast_device_axpp = { /* LCD/VGA controller */ -static struct s3c2410fb_display __initdata bast_lcd_info[] = { - { - .type = S3C2410_LCDCON1_TFT, - .width = 640, - .height = 480, - - .pixclock = 33333, - .xres = 640, - .yres = 480, - .bpp = 4, - .left_margin = 40, - .right_margin = 20, - .hsync_len = 88, - .upper_margin = 30, - .lower_margin = 32, - .vsync_len = 3, - - .lcdcon5 = 0x00014b02, +static struct s3c2410fb_mach_info __initdata bast_lcd_info = { + .width = 640, + .height = 480, + + .xres = { + .min = 320, + .max = 1024, + .defval = 640, }, - { - .type = S3C2410_LCDCON1_TFT, - .width = 640, - .height = 480, - - .pixclock = 33333, - .xres = 640, - .yres = 480, - .bpp = 8, - .left_margin = 40, - .right_margin = 20, - .hsync_len = 88, - .upper_margin = 30, - .lower_margin = 32, - .vsync_len = 3, - .lcdcon5 = 0x00014b02, + .yres = { + .min = 240, + .max = 600, + .defval = 480, }, - { - .type = S3C2410_LCDCON1_TFT, - .width = 640, - .height = 480, - - .pixclock = 33333, - .xres = 640, - .yres = 480, - .bpp = 16, - .left_margin = 40, - .right_margin = 20, - .hsync_len = 88, - .upper_margin = 30, - .lower_margin = 32, - .vsync_len = 3, - .lcdcon5 = 0x00014b02, + .bpp = { + .min = 4, + .max = 16, + .defval = 8, }, -}; -/* LCD/VGA controller */ - -static struct s3c2410fb_mach_info __initdata bast_fb_info = { - - .displays = bast_lcd_info, - .num_displays = ARRAY_SIZE(bast_lcd_info), - .default_display = 4, + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } }; /* Standard BAST devices */ @@ -587,7 +552,7 @@ static void __init bast_map_io(void) static void __init bast_init(void) { - s3c24xx_fb_set_platdata(&bast_fb_info); + s3c24xx_fb_set_platdata(&bast_lcd_info); platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices)); } diff --git a/trunk/arch/arm/mach-s3c2410/mach-h1940.c b/trunk/arch/arm/mach-s3c2410/mach-h1940.c index 7c1145e87c12..9a172b4ad720 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-h1940.c +++ b/trunk/arch/arm/mach-s3c2410/mach-h1940.c @@ -133,31 +133,29 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = { /** * Set lcd on or off **/ -static struct s3c2410fb_display h1940_lcd __initdata = { - .lcdcon5= S3C2410_LCDCON5_FRM565 | \ - S3C2410_LCDCON5_INVVLINE | \ - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - .width = 240, - .height = 320, - .pixclock = 260000, - .xres = 240, - .yres = 320, - .bpp = 16, - .left_margin = 20, - .right_margin = 8, - .hsync_len = 4, - .upper_margin = 8, - .lower_margin = 7, - .vsync_len = 1, -}; - -static struct s3c2410fb_mach_info h1940_fb_info __initdata = { - .displays = &h1940_lcd, - .num_displays = 1, - .default_display = 0, - +static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { + .fixed_syncs= 1, + .regs={ + .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \ + S3C2410_LCDCON1_TFT | \ + S3C2410_LCDCON1_CLKVAL(0x0C), + + .lcdcon2= S3C2410_LCDCON2_VBPD(7) | \ + S3C2410_LCDCON2_LINEVAL(319) | \ + S3C2410_LCDCON2_VFPD(6) | \ + S3C2410_LCDCON2_VSPW(0), + + .lcdcon3= S3C2410_LCDCON3_HBPD(19) | \ + S3C2410_LCDCON3_HOZVAL(239) | \ + S3C2410_LCDCON3_HFPD(7), + + .lcdcon4= S3C2410_LCDCON4_MVAL(0) | \ + S3C2410_LCDCON4_HSPW(3), + + .lcdcon5= S3C2410_LCDCON5_FRM565 | \ + S3C2410_LCDCON5_INVVLINE | \ + S3C2410_LCDCON5_HWSWP, + }, .lpcsel= 0x02, .gpccon= 0xaa940659, .gpccon_mask= 0xffffffff, @@ -167,6 +165,12 @@ static struct s3c2410fb_mach_info h1940_fb_info __initdata = { .gpdcon_mask= 0xffffffff, .gpdup= 0x0000faff, .gpdup_mask= 0xffffffff, + + .width= 240, + .height= 320, + .xres= {240,240,240}, + .yres= {320,320,320}, + .bpp= {16,16,16}, }; static struct platform_device s3c_device_leds = { @@ -213,7 +217,7 @@ static void __init h1940_init(void) { u32 tmp; - s3c24xx_fb_set_platdata(&h1940_fb_info); + s3c24xx_fb_set_platdata(&h1940_lcdcfg); s3c24xx_udc_set_platdata(&h1940_udc_cfg); /* Turn off suspend on both USB ports, and switch the diff --git a/trunk/arch/arm/mach-s3c2410/mach-qt2410.c b/trunk/arch/arm/mach-s3c2410/mach-qt2410.c index a1caf4b0adac..e670b1e1631b 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/trunk/arch/arm/mach-s3c2410/mach-qt2410.c @@ -95,83 +95,157 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { /* LCD driver info */ -static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = { - { - /* Configuration for 640x480 SHARP LQ080V3DG01 */ - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - .width = 640, - .height = 480, - - .pixclock = 40000, /* HCLK/4 */ - .xres = 640, - .yres = 480, - .bpp = 16, - .left_margin = 44, - .right_margin = 116, - .hsync_len = 96, - .upper_margin = 19, - .lower_margin = 11, - .vsync_len = 15, +/* Configuration for 640x480 SHARP LQ080V3DG01 */ +static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = { + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ + + .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */ + S3C2410_LCDCON2_LINEVAL(479) | + S3C2410_LCDCON2_VFPD(10) | /* 11 */ + S3C2410_LCDCON2_VSPW(14), /* 15 */ + + .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */ + S3C2410_LCDCON3_HOZVAL(639) | /* 640 */ + S3C2410_LCDCON3_HFPD(115), /* 116 */ + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(95), /* 96 */ + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, }, - { - /* Configuration for 480x640 toppoly TD028TTEC1 */ - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - .width = 480, - .height = 640, - .pixclock = 40000, /* HCLK/4 */ - .xres = 480, - .yres = 640, - .bpp = 16, - .left_margin = 8, - .right_margin = 24, - .hsync_len = 8, - .upper_margin = 2, - .lower_margin = 4, - .vsync_len = 2, + + .lpcsel = ((0xCE6) & ~7) | 1<<4, + + .width = 640, + .height = 480, + + .xres = { + .min = 640, + .max = 640, + .defval = 640, + }, + + .yres = { + .min = 480, + .max = 480, + .defval = 480, + }, + + .bpp = { + .min = 16, + .max = 16, + .defval = 16, + }, +}; + +/* Configuration for 480x640 toppoly TD028TTEC1 */ +static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = { + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ + + .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */ + S3C2410_LCDCON2_LINEVAL(639) |/* 640 */ + S3C2410_LCDCON2_VFPD(3) | /* 4 */ + S3C2410_LCDCON2_VSPW(1), /* 2 */ + + .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */ + S3C2410_LCDCON3_HOZVAL(479) | /* 479 */ + S3C2410_LCDCON3_HFPD(23), /* 24 */ + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(7), /* 8 */ + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + + .lpcsel = ((0xCE6) & ~7) | 1<<4, + + .width = 480, + .height = 640, + + .xres = { + .min = 480, + .max = 480, + .defval = 480, }, - { - /* Config for 240x320 LCD */ - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - .width = 240, - .height = 320, - .pixclock = 100000, /* HCLK/10 */ - .xres = 240, - .yres = 320, - .bpp = 16, - .left_margin = 13, - .right_margin = 8, - .hsync_len = 4, - .upper_margin = 2, - .lower_margin = 7, - .vsync_len = 4, + + .yres = { + .min = 640, + .max = 640, + .defval = 640, + }, + + .bpp = { + .min = 16, + .max = 16, + .defval = 16, }, }; +/* Config for 240x320 LCD */ +static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = { + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x04), + + .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | + S3C2410_LCDCON2_LINEVAL(319) | + S3C2410_LCDCON2_VFPD(6) | + S3C2410_LCDCON2_VSPW(3), + + .lcdcon3 = S3C2410_LCDCON3_HBPD(12) | + S3C2410_LCDCON3_HOZVAL(239) | + S3C2410_LCDCON3_HFPD(7), -static struct s3c2410fb_mach_info qt2410_fb_info __initdata = { - .displays = qt2410_lcd_cfg, - .num_displays = ARRAY_SIZE(qt2410_lcd_cfg), - .default_display = 0, + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(3), + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, .lpcsel = ((0xCE6) & ~7) | 1<<4, + + .width = 240, + .height = 320, + + .xres = { + .min = 240, + .max = 240, + .defval = 240, + }, + + .yres = { + .min = 320, + .max = 320, + .defval = 320, + }, + + .bpp = { + .min = 16, + .max = 16, + .defval = 16, + }, }; /* CS8900 */ @@ -334,17 +408,16 @@ static void __init qt2410_machine_init(void) switch (tft_type) { case 'p': /* production */ - qt2410_fb_info.default_display = 1; + s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg); break; case 'b': /* big */ - qt2410_fb_info.default_display = 0; + s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg); break; case 's': /* small */ default: - qt2410_fb_info.default_display = 2; + s3c24xx_fb_set_platdata(&qt2410_lcd_cfg); break; } - s3c24xx_fb_set_platdata(&qt2410_fb_info); s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPB0, 1); diff --git a/trunk/arch/arm/mach-s3c2440/mach-rx3715.c b/trunk/arch/arm/mach-s3c2440/mach-rx3715.c index bac40c4878a5..b59e6d39f2f2 100644 --- a/trunk/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/trunk/arch/arm/mach-s3c2440/mach-rx3715.c @@ -110,32 +110,28 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { /* framebuffer lcd controller information */ -static struct s3c2410fb_display rx3715_lcdcfg __initdata = { - .lcdcon5 = S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - .width = 240, - .height = 320, - - .pixclock = 260000, - .xres = 240, - .yres = 320, - .bpp = 16, - .left_margin = 36, - .right_margin = 36, - .hsync_len = 8, - .upper_margin = 6, - .lower_margin = 7, - .vsync_len = 3, -}; - -static struct s3c2410fb_mach_info rx3715_fb_info __initdata = { - - .displays = &rx3715_lcdcfg, - .num_displays = 1, - .default_display = 0, +static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { + .regs = { + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \ + S3C2410_LCDCON1_TFT | \ + S3C2410_LCDCON1_CLKVAL(0x0C), + + .lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \ + S3C2410_LCDCON2_LINEVAL(319) | \ + S3C2410_LCDCON2_VFPD(6) | \ + S3C2410_LCDCON2_VSPW(2), + + .lcdcon3 = S3C2410_LCDCON3_HBPD(35) | \ + S3C2410_LCDCON3_HOZVAL(239) | \ + S3C2410_LCDCON3_HFPD(35), + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | \ + S3C2410_LCDCON4_HSPW(7), + + .lcdcon5 = S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_HWSWP, + }, .lpcsel = 0xf82, @@ -148,6 +144,28 @@ static struct s3c2410fb_mach_info rx3715_fb_info __initdata = { .gpdcon_mask = 0xffc0fff0, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, + + .fixed_syncs = 1, + .width = 240, + .height = 320, + + .xres = { + .min = 240, + .max = 240, + .defval = 240, + }, + + .yres = { + .max = 320, + .min = 320, + .defval = 320, + }, + + .bpp = { + .min = 16, + .max = 16, + .defval = 16, + }, }; static struct mtd_partition rx3715_nand_part[] = { @@ -206,7 +224,7 @@ static void __init rx3715_init_machine(void) #endif s3c2410_pm_init(); - s3c24xx_fb_set_platdata(&rx3715_fb_info); + s3c24xx_fb_set_platdata(&rx3715_lcdcfg); platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices)); } diff --git a/trunk/arch/arm/mach-s3c2440/mach-smdk2440.c b/trunk/arch/arm/mach-s3c2440/mach-smdk2440.c index 4552828bf800..670115b8a12e 100644 --- a/trunk/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/trunk/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -103,35 +103,31 @@ static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = { /* LCD driver info */ -static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = { - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - - .type = S3C2410_LCDCON1_TFT, - - .width = 240, - .height = 320, - - .pixclock = 166667, /* HCLK 60 MHz, divisor 10 */ - .xres = 240, - .yres = 320, - .bpp = 16, - .left_margin = 20, - .right_margin = 8, - .hsync_len = 4, - .upper_margin = 8, - .lower_margin = 7, - .vsync_len = 4, -}; - -static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = { - .displays = &smdk2440_lcd_cfg, - .num_displays = 1, - .default_display = 0, +static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x04), + + .lcdcon2 = S3C2410_LCDCON2_VBPD(7) | + S3C2410_LCDCON2_LINEVAL(319) | + S3C2410_LCDCON2_VFPD(6) | + S3C2410_LCDCON2_VSPW(3), + + .lcdcon3 = S3C2410_LCDCON3_HBPD(19) | + S3C2410_LCDCON3_HOZVAL(239) | + S3C2410_LCDCON3_HFPD(7), + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(3), + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, #if 0 /* currently setup by downloader */ @@ -146,6 +142,28 @@ static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = { #endif .lpcsel = ((0xCE6) & ~7) | 1<<4, + .type = S3C2410_LCDCON1_TFT16BPP, + + .width = 240, + .height = 320, + + .xres = { + .min = 240, + .max = 240, + .defval = 240, + }, + + .yres = { + .min = 320, + .max = 320, + .defval = 320, + }, + + .bpp = { + .min = 16, + .max = 16, + .defval = 16, + }, }; static struct platform_device *smdk2440_devices[] __initdata = { @@ -165,7 +183,7 @@ static void __init smdk2440_map_io(void) static void __init smdk2440_machine_init(void) { - s3c24xx_fb_set_platdata(&smdk2440_fb_info); + s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); diff --git a/trunk/arch/arm/mm/fault.c b/trunk/arch/arm/mm/fault.c index 59ed1d05b71b..846cce48e2b7 100644 --- a/trunk/arch/arm/mm/fault.c +++ b/trunk/arch/arm/mm/fault.c @@ -266,7 +266,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * the page fault gracefully. */ printk("VM: killing process %s\n", tsk->comm); - do_group_exit(SIGKILL); + do_exit(SIGKILL); return 0; } if (fault & VM_FAULT_SIGBUS) { diff --git a/trunk/arch/arm/vfp/Makefile b/trunk/arch/arm/vfp/Makefile index 39f6d8e1af73..7e136e77971a 100644 --- a/trunk/arch/arm/vfp/Makefile +++ b/trunk/arch/arm/vfp/Makefile @@ -7,7 +7,7 @@ # EXTRA_CFLAGS := -DDEBUG # EXTRA_AFLAGS := -DDEBUG -KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) +AFLAGS :=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) LDFLAGS +=--no-warn-mismatch obj-y += vfp.o diff --git a/trunk/arch/avr32/Makefile b/trunk/arch/avr32/Makefile index 87918647be6d..dc6bc01f232c 100644 --- a/trunk/arch/avr32/Makefile +++ b/trunk/arch/avr32/Makefile @@ -11,15 +11,15 @@ all: uImage vmlinux.elf KBUILD_DEFCONFIG := atstk1002_defconfig -KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -KBUILD_AFLAGS += -mrelax -mno-pic +CFLAGS += -pipe -fno-builtin -mno-pic +AFLAGS += -mrelax -mno-pic CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000 -KBUILD_CFLAGS += $(cpuflags-y) -KBUILD_AFLAGS += $(cpuflags-y) +CFLAGS += $(cpuflags-y) +AFLAGS += $(cpuflags-y) CHECKFLAGS += -D__avr32__ -D__BIG_ENDIAN diff --git a/trunk/arch/avr32/kernel/kprobes.c b/trunk/arch/avr32/kernel/kprobes.c index 20b1c9d8f945..4942ee662e0b 100644 --- a/trunk/arch/avr32/kernel/kprobes.c +++ b/trunk/arch/avr32/kernel/kprobes.c @@ -22,8 +22,6 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe); static unsigned long kprobe_status; static struct pt_regs jprobe_saved_regs; -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - int __kprobes arch_prepare_kprobe(struct kprobe *p) { int ret = 0; diff --git a/trunk/arch/avr32/kernel/ptrace.c b/trunk/arch/avr32/kernel/ptrace.c index 9e16b8a447f2..39060cbeb2a3 100644 --- a/trunk/arch/avr32/kernel/ptrace.c +++ b/trunk/arch/avr32/kernel/ptrace.c @@ -227,6 +227,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; + /* Detach a process that was attached */ + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; diff --git a/trunk/arch/avr32/mm/fault.c b/trunk/arch/avr32/mm/fault.c index 11472f8701bd..ae2d2c593b2b 100644 --- a/trunk/arch/avr32/mm/fault.c +++ b/trunk/arch/avr32/mm/fault.c @@ -216,7 +216,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) } printk("VM: Killing process %s\n", tsk->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/blackfin/Kconfig b/trunk/arch/blackfin/Kconfig index aa9db3073312..b24f4535ffe0 100644 --- a/trunk/arch/blackfin/Kconfig +++ b/trunk/arch/blackfin/Kconfig @@ -758,7 +758,7 @@ config BFIN_DMA_5XX choice prompt "Uncached SDRAM region" default DMA_UNCACHED_1M - depends on BFIN_DMA_5XX + depends BFIN_DMA_5XX config DMA_UNCACHED_2M bool "Enable 2M DMA region" config DMA_UNCACHED_1M diff --git a/trunk/arch/blackfin/Makefile b/trunk/arch/blackfin/Makefile index 368933760d28..20841663270f 100644 --- a/trunk/arch/blackfin/Makefile +++ b/trunk/arch/blackfin/Makefile @@ -53,8 +53,8 @@ rev-$(CONFIG_BF_REV_0_5) := 0.5 rev-$(CONFIG_BF_REV_NONE) := none rev-$(CONFIG_BF_REV_ANY) := any -KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y) -KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y) +CFLAGS += -mcpu=$(cpu-y)-$(rev-y) +AFLAGS += -mcpu=$(cpu-y)-$(rev-y) head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o diff --git a/trunk/arch/blackfin/kernel/ptrace.c b/trunk/arch/blackfin/kernel/ptrace.c index 85caf9b711a1..64ce5fea8609 100644 --- a/trunk/arch/blackfin/kernel/ptrace.c +++ b/trunk/arch/blackfin/kernel/ptrace.c @@ -385,6 +385,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + case PTRACE_DETACH: + { /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + } + case PTRACE_GETREGS: { diff --git a/trunk/arch/cris/Makefile b/trunk/arch/cris/Makefile index e6bf00c262e0..ee114699ef8e 100644 --- a/trunk/arch/cris/Makefile +++ b/trunk/arch/cris/Makefile @@ -29,18 +29,18 @@ LD = $(CROSS_COMPILE)ld -mcrislinux OBJCOPYFLAGS := -O binary -R .note -R .comment -S CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) -KBUILD_AFLAGS += -mlinux +AFLAGS += -mlinux -KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe +CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe ifdef CONFIG_FRAME_POINTER -KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g -KBUILD_CFLAGS += -fno-omit-frame-pointer +CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g +CFLAGS += -fno-omit-frame-pointer endif head-y := arch/$(ARCH)/$(SARCH)/kernel/head.o -LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a) +LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a) core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/ diff --git a/trunk/arch/cris/arch-v10/kernel/ptrace.c b/trunk/arch/cris/arch-v10/kernel/ptrace.c index b570ae9b6cad..f4f9db698b44 100644 --- a/trunk/arch/cris/arch-v10/kernel/ptrace.c +++ b/trunk/arch/cris/arch-v10/kernel/ptrace.c @@ -177,6 +177,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + /* Get all GP registers from the child. */ case PTRACE_GETREGS: { int i; diff --git a/trunk/arch/cris/arch-v10/kernel/time.c b/trunk/arch/cris/arch-v10/kernel/time.c index 575a14bb1106..077e973c33f0 100644 --- a/trunk/arch/cris/arch-v10/kernel/time.c +++ b/trunk/arch/cris/arch-v10/kernel/time.c @@ -254,12 +254,8 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * it needs to be IRQF_DISABLED to make the jiffies update work properly */ -static struct irqaction irq2 = { - .handler = timer_interrupt, - .flags = IRQF_SHARED | IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "timer", -}; +static struct irqaction irq2 = { timer_interrupt, IRQF_SHARED | IRQF_DISABLED, + CPU_MASK_NONE, "timer", NULL, NULL}; void __init time_init(void) diff --git a/trunk/arch/cris/arch-v32/kernel/ptrace.c b/trunk/arch/cris/arch-v32/kernel/ptrace.c index 2df60529a8af..38ece0cd47cb 100644 --- a/trunk/arch/cris/arch-v32/kernel/ptrace.c +++ b/trunk/arch/cris/arch-v32/kernel/ptrace.c @@ -245,6 +245,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + /* Get all GP registers from the child. */ case PTRACE_GETREGS: { int i; diff --git a/trunk/arch/cris/arch-v32/kernel/smp.c b/trunk/arch/cris/arch-v32/kernel/smp.c index 697494bc2de1..77e655f26560 100644 --- a/trunk/arch/cris/arch-v32/kernel/smp.c +++ b/trunk/arch/cris/arch-v32/kernel/smp.c @@ -63,12 +63,8 @@ static unsigned long irq_regs[NR_CPUS] = static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int send_ipi(int vector, int wait, cpumask_t cpu_mask); -static struct irqaction irq_ipi = { - .handler = crisv32_ipi_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "ipi", -}; +static struct irqaction irq_ipi = { crisv32_ipi_interrupt, IRQF_DISABLED, + CPU_MASK_NONE, "ipi", NULL, NULL}; extern void cris_mmu_init(void); extern void cris_timer_init(void); diff --git a/trunk/arch/cris/mm/fault.c b/trunk/arch/cris/mm/fault.c index 8aab81430695..8672ab7d7978 100644 --- a/trunk/arch/cris/mm/fault.c +++ b/trunk/arch/cris/mm/fault.c @@ -360,7 +360,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, up_read(&mm->mmap_sem); printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/frv/Makefile b/trunk/arch/frv/Makefile index 310c47a663f8..9bf7345c5cc9 100644 --- a/trunk/arch/frv/Makefile +++ b/trunk/arch/frv/Makefile @@ -39,13 +39,13 @@ endif ARCHMODFLAGS += -G0 -mlong-calls ifdef CONFIG_GPREL_DATA_8 -KBUILD_CFLAGS += -G8 +CFLAGS += -G8 else ifdef CONFIG_GPREL_DATA_4 -KBUILD_CFLAGS += -G4 +CFLAGS += -G4 else ifdef CONFIG_GPREL_DATA_NONE -KBUILD_CFLAGS += -G0 +CFLAGS += -G0 endif endif endif @@ -53,26 +53,26 @@ endif #LDFLAGS_vmlinux := -Map linkmap.txt ifdef CONFIG_GC_SECTIONS -KBUILD_CFLAGS += -ffunction-sections -fdata-sections +CFLAGS += -ffunction-sections -fdata-sections LINKFLAGS += --gc-sections endif ifndef CONFIG_FRAME_POINTER -KBUILD_CFLAGS += -mno-linked-fp +CFLAGS += -mno-linked-fp endif ifdef CONFIG_CPU_FR451_COMPILE -KBUILD_CFLAGS += -mcpu=fr450 -KBUILD_AFLAGS += -mcpu=fr450 +CFLAGS += -mcpu=fr450 +AFLAGS += -mcpu=fr450 ASFLAGS += -mcpu=fr450 else ifdef CONFIG_CPU_FR551_COMPILE -KBUILD_CFLAGS += -mcpu=fr550 -KBUILD_AFLAGS += -mcpu=fr550 +CFLAGS += -mcpu=fr550 +AFLAGS += -mcpu=fr550 ASFLAGS += -mcpu=fr550 else -KBUILD_CFLAGS += -mcpu=fr400 -KBUILD_AFLAGS += -mcpu=fr400 +CFLAGS += -mcpu=fr400 +AFLAGS += -mcpu=fr400 ASFLAGS += -mcpu=fr400 endif endif @@ -80,16 +80,16 @@ endif # pretend the kernel is going to run on an FR400 with no media-fp unit # - reserve CC3 for use with atomic ops # - all the extra registers are dealt with only at context switch time -KBUILD_CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media -KBUILD_CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2 -KBUILD_AFLAGS += -mno-fdpic +CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media +CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2 +AFLAGS += -mno-fdpic ASFLAGS += -mno-fdpic # make sure the .S files get compiled with debug info # and disable optimisations that are unhelpful whilst debugging ifdef CONFIG_DEBUG_INFO -#KBUILD_CFLAGS += -O1 -KBUILD_AFLAGS += -Wa,--gdwarf2 +#CFLAGS += -O1 +AFLAGS += -Wa,--gdwarf2 ASFLAGS += -Wa,--gdwarf2 endif diff --git a/trunk/arch/frv/kernel/time.c b/trunk/arch/frv/kernel/time.c index e83e0bccfab9..ed588d73d7d8 100644 --- a/trunk/arch/frv/kernel/time.c +++ b/trunk/arch/frv/kernel/time.c @@ -43,10 +43,7 @@ unsigned long __delay_loops_MHz; static irqreturn_t timer_interrupt(int irq, void *dummy); static struct irqaction timer_irq = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "timer", + timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; static inline int set_rtc_mmss(unsigned long nowtime) diff --git a/trunk/arch/frv/mm/fault.c b/trunk/arch/frv/mm/fault.c index 05093d41d98e..6798fa0257b1 100644 --- a/trunk/arch/frv/mm/fault.c +++ b/trunk/arch/frv/mm/fault.c @@ -259,7 +259,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear up_read(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); if (user_mode(__frame)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/h8300/Makefile b/trunk/arch/h8300/Makefile index a556447877b4..53b5c1edf596 100644 --- a/trunk/arch/h8300/Makefile +++ b/trunk/arch/h8300/Makefile @@ -30,16 +30,16 @@ ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf cflags-$(CONFIG_CPU_H8S) := -ms ldflags-$(CONFIG_CPU_H8S) := -mh8300self -KBUILD_CFLAGS += $(cflags-y) -KBUILD_CFLAGS += -mint32 -fno-builtin -KBUILD_CFLAGS += -g -KBUILD_CFLAGS += -D__linux__ -KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" -KBUILD_AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y) +CFLAGS += $(cflags-y) +CFLAGS += -mint32 -fno-builtin +CFLAGS += -g +CFLAGS += -D__linux__ +CFLAGS += -DUTS_SYSNAME=\"uClinux\" +AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y) LDFLAGS += $(ldflags-y) CROSS_COMPILE = h8300-elf- -LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(CFLAGS) -print-libgcc-file-name) head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o diff --git a/trunk/arch/h8300/lib/Makefile b/trunk/arch/h8300/lib/Makefile index 1577f5075b10..98272b66f4e5 100644 --- a/trunk/arch/h8300/lib/Makefile +++ b/trunk/arch/h8300/lib/Makefile @@ -2,4 +2,7 @@ # Makefile for H8/300-specific library files.. # +.S.o: + $(CC) $(AFLAGS) -D__ASSEMBLY__ -c $< -o $@ + lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o diff --git a/trunk/arch/i386/Makefile b/trunk/arch/i386/Makefile index f036d2dee3de..5e50dbf00f3e 100644 --- a/trunk/arch/i386/Makefile +++ b/trunk/arch/i386/Makefile @@ -34,10 +34,10 @@ LDFLAGS_vmlinux := --emit-relocs endif CHECKFLAGS += -D__i386__ -KBUILD_CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return +CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return # prevent gcc from keeping the stack 16 byte aligned -KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) +CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu @@ -51,17 +51,17 @@ cflags-y += -maccumulate-outgoing-args # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots: -KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) +CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) # do binutils support CFI? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) -KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) -KBUILD_CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) # Default subarch .c files mcore-y := arch/x86/mach-default @@ -116,8 +116,8 @@ drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/ drivers-$(CONFIG_PM) += arch/x86/power/ drivers-$(CONFIG_FB) += arch/x86/video/ -KBUILD_CFLAGS += $(mflags-y) -KBUILD_AFLAGS += $(mflags-y) +CFLAGS += $(mflags-y) +AFLAGS += $(mflags-y) boot := arch/x86/boot diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 59b91ac861ac..2e6310b8eab7 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -54,11 +54,6 @@ config ARCH_HAS_ILOG2_U64 bool default n -config HUGETLB_PAGE_SIZE_VARIABLE - bool - depends on HUGETLB_PAGE - default y - config GENERIC_FIND_NEXT_BIT bool default y @@ -305,9 +300,6 @@ config HOTPLUG_CPU config ARCH_ENABLE_MEMORY_HOTPLUG def_bool y -config ARCH_ENABLE_MEMORY_HOTREMOVE - def_bool y - config SCHED_SMT bool "SMT scheduler support" depends on SMP @@ -356,7 +348,6 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y depends on ARCH_DISCONTIGMEM_ENABLE - select SPARSEMEM_VMEMMAP_ENABLE config ARCH_DISCONTIGMEM_DEFAULT def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) diff --git a/trunk/arch/ia64/Makefile b/trunk/arch/ia64/Makefile index 34951aa2370b..21033ed83307 100644 --- a/trunk/arch/ia64/Makefile +++ b/trunk/arch/ia64/Makefile @@ -29,7 +29,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ CFLAGS_KERNEL := -mconstant-gp GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)") -KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") +CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") ifeq ($(GAS_STATUS),buggy) $(error Sorry, you need a newer version of the assember, one that is built from \ @@ -44,7 +44,7 @@ ifeq ($(call cc-version),0304) cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley endif -KBUILD_CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o libs-y += arch/ia64/lib/ diff --git a/trunk/arch/ia64/hp/common/sba_iommu.c b/trunk/arch/ia64/hp/common/sba_iommu.c index 4338f4123f31..e980e7aa2306 100644 --- a/trunk/arch/ia64/hp/common/sba_iommu.c +++ b/trunk/arch/ia64/hp/common/sba_iommu.c @@ -396,7 +396,7 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents, startsg->dma_address, startsg->dma_length, sba_sg_address(startsg)); - startsg = sg_next(startsg); + startsg++; } } @@ -409,7 +409,7 @@ sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) while (the_nents-- > 0) { if (sba_sg_address(the_sg) == 0x0UL) sba_dump_sg(NULL, startsg, nents); - the_sg = sg_next(the_sg); + the_sg++; } } @@ -1201,7 +1201,7 @@ sba_fill_pdir( u32 pide = startsg->dma_address & ~PIDE_FLAG; dma_offset = (unsigned long) pide & ~iovp_mask; startsg->dma_address = 0; - dma_sg = sg_next(dma_sg); + dma_sg++; dma_sg->dma_address = pide | ioc->ibase; pdirp = &(ioc->pdir_base[pide >> iovp_shift]); n_mappings++; @@ -1228,7 +1228,7 @@ sba_fill_pdir( pdirp++; } while (cnt > 0); } - startsg = sg_next(startsg); + startsg++; } /* force pdir update */ wmb(); @@ -1297,7 +1297,7 @@ sba_coalesce_chunks( struct ioc *ioc, while (--nents > 0) { unsigned long vaddr; /* tmp */ - startsg = sg_next(startsg); + startsg++; /* PARANOID */ startsg->dma_address = startsg->dma_length = 0; @@ -1407,7 +1407,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di #ifdef ALLOW_IOV_BYPASS_SG ASSERT(to_pci_dev(dev)->dma_mask); if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) { - for_each_sg(sglist, sg, nents, filled) { + for (sg = sglist ; filled < nents ; filled++, sg++){ sg->dma_length = sg->length; sg->dma_address = virt_to_phys(sba_sg_address(sg)); } @@ -1501,7 +1501,7 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in while (nents && sglist->dma_length) { sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir); - sglist = sg_next(sglist); + sglist++; nents--; } diff --git a/trunk/arch/ia64/hp/sim/simscsi.c b/trunk/arch/ia64/hp/sim/simscsi.c index a3a558a06757..d62fa76e5a7d 100644 --- a/trunk/arch/ia64/hp/sim/simscsi.c +++ b/trunk/arch/ia64/hp/sim/simscsi.c @@ -360,7 +360,6 @@ static struct scsi_host_template driver_template = { .max_sectors = 1024, .cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int __init diff --git a/trunk/arch/ia64/kernel/gate.lds.S b/trunk/arch/ia64/kernel/gate.lds.S index 44817d97ab43..6d198339bf85 100644 --- a/trunk/arch/ia64/kernel/gate.lds.S +++ b/trunk/arch/ia64/kernel/gate.lds.S @@ -1,8 +1,7 @@ /* - * Linker script for gate DSO. The gate pages are an ELF shared object - * prelinked to its virtual address, with only one read-only segment and - * one execute-only segment (both fit in one page). This script controls - * its layout. + * Linker script for gate DSO. The gate pages are an ELF shared object prelinked to its + * virtual address, with only one read-only segment and one execute-only segment (both fit + * in one page). This script controls its layout. */ @@ -10,80 +9,72 @@ SECTIONS { - . = GATE_ADDR + SIZEOF_HEADERS; - - .hash : { *(.hash) } :readable - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .dynamic : { *(.dynamic) } :readable :dynamic - - /* - * This linker script is used both with -r and with -shared. For - * the layouts to match, we need to skip more than enough space for - * the dynamic symbol table et al. If this amount is insufficient, - * ld -shared will barf. Just increase it here. - */ - . = GATE_ADDR + 0x500; - - .data.patch : { - __start_gate_mckinley_e9_patchlist = .; - *(.data.patch.mckinley_e9) - __end_gate_mckinley_e9_patchlist = .; - - __start_gate_vtop_patchlist = .; - *(.data.patch.vtop) - __end_gate_vtop_patchlist = .; - - __start_gate_fsyscall_patchlist = .; - *(.data.patch.fsyscall_table) - __end_gate_fsyscall_patchlist = .; - - __start_gate_brl_fsys_bubble_down_patchlist = .; - *(.data.patch.brl_fsys_bubble_down) - __end_gate_brl_fsys_bubble_down_patchlist = .; - } :readable - - .IA_64.unwind_info : { *(.IA_64.unwind_info*) } - .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind + . = GATE_ADDR + SIZEOF_HEADERS; + + .hash : { *(.hash) } :readable + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .dynamic : { *(.dynamic) } :readable :dynamic + + /* + * This linker script is used both with -r and with -shared. For the layouts to match, + * we need to skip more than enough space for the dynamic symbol table et al. If this + * amount is insufficient, ld -shared will barf. Just increase it here. + */ + . = GATE_ADDR + 0x500; + + .data.patch : { + __start_gate_mckinley_e9_patchlist = .; + *(.data.patch.mckinley_e9) + __end_gate_mckinley_e9_patchlist = .; + + __start_gate_vtop_patchlist = .; + *(.data.patch.vtop) + __end_gate_vtop_patchlist = .; + + __start_gate_fsyscall_patchlist = .; + *(.data.patch.fsyscall_table) + __end_gate_fsyscall_patchlist = .; + + __start_gate_brl_fsys_bubble_down_patchlist = .; + *(.data.patch.brl_fsys_bubble_down) + __end_gate_brl_fsys_bubble_down_patchlist = .; + } :readable + .IA_64.unwind_info : { *(.IA_64.unwind_info*) } + .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind #ifdef HAVE_BUGGY_SEGREL - .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable + .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable #else - . = ALIGN(PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1)); - .text : { *(.text) *(.text.*) } :epc + . = ALIGN (PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1)); + .text : { *(.text) *(.text.*) } :epc #endif - /DISCARD/ : { - *(.got.plt) *(.got) - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(__ex_table) - *(__mca_table) - } + /DISCARD/ : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(__ex_table) + *(__mca_table) + } } -/* - * ld does not recognize this name token; use the constant. - */ -#define PT_IA_64_UNWIND 0x70000001 - /* * We must supply the ELF program headers explicitly to get just one * PT_LOAD segment, and set the flags explicitly to make segments read-only. */ PHDRS { - readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */ + readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */ #ifndef HAVE_BUGGY_SEGREL - epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */ + epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */ #endif - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - unwind PT_IA_64_UNWIND; + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + unwind 0x70000001; /* PT_IA_64_UNWIND, but ld doesn't match the name */ } /* @@ -91,14 +82,14 @@ PHDRS */ VERSION { - LINUX_2.5 { - global: - __kernel_syscall_via_break; - __kernel_syscall_via_epc; - __kernel_sigtramp; - - local: *; - }; + LINUX_2.5 { + global: + __kernel_syscall_via_break; + __kernel_syscall_via_epc; + __kernel_sigtramp; + + local: *; + }; } /* The ELF entry point can be used to set the AT_SYSINFO value. */ diff --git a/trunk/arch/ia64/kernel/kprobes.c b/trunk/arch/ia64/kernel/kprobes.c index 5fd65d8302c8..5dc98b5abcfb 100644 --- a/trunk/arch/ia64/kernel/kprobes.c +++ b/trunk/arch/ia64/kernel/kprobes.c @@ -40,8 +40,6 @@ extern void jprobe_inst_return(void); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - enum instruction_type {A, I, M, F, B, L, X, u}; static enum instruction_type bundle_encoding[32][3] = { { M, I, I }, /* 00 */ diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index c5cfcfa4c87c..9e392a30d197 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -528,6 +528,10 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); + + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); + check_for_logical_procs(); if (smp_num_cpucores > 1) printk(KERN_INFO @@ -869,16 +873,6 @@ cpu_init (void) void *cpu_data; cpu_data = per_cpu_init(); -#ifdef CONFIG_SMP - /* - * insert boot cpu into sibling and core mapes - * (must be done after per_cpu area is setup) - */ - if (smp_processor_id() == 0) { - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, cpu_core_map[0]); - } -#endif /* * We set ar.k3 so that assembly code in MCA handler can compute diff --git a/trunk/arch/ia64/kernel/smpboot.c b/trunk/arch/ia64/kernel/smpboot.c index c57dbce25c12..308772f7cddc 100644 --- a/trunk/arch/ia64/kernel/smpboot.c +++ b/trunk/arch/ia64/kernel/smpboot.c @@ -138,9 +138,7 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_possible_map); cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; -DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map); -EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); - +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; int smp_num_siblings = 1; int smp_num_cpucores = 1; @@ -652,12 +650,12 @@ clear_cpu_sibling_map(int cpu) { int i; - for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) - cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); + for_each_cpu_mask(i, cpu_sibling_map[cpu]) + cpu_clear(cpu, cpu_sibling_map[i]); for_each_cpu_mask(i, cpu_core_map[cpu]) cpu_clear(cpu, cpu_core_map[i]); - per_cpu(cpu_sibling_map, cpu) = cpu_core_map[cpu] = CPU_MASK_NONE; + cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE; } static void @@ -668,7 +666,7 @@ remove_siblinginfo(int cpu) if (cpu_data(cpu)->threads_per_core == 1 && cpu_data(cpu)->cores_per_socket == 1) { cpu_clear(cpu, cpu_core_map[cpu]); - cpu_clear(cpu, per_cpu(cpu_sibling_map, cpu)); + cpu_clear(cpu, cpu_sibling_map[cpu]); return; } @@ -809,8 +807,8 @@ set_cpu_sibling_map(int cpu) cpu_set(i, cpu_core_map[cpu]); cpu_set(cpu, cpu_core_map[i]); if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) { - cpu_set(i, per_cpu(cpu_sibling_map, cpu)); - cpu_set(cpu, per_cpu(cpu_sibling_map, i)); + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); } } } @@ -841,7 +839,7 @@ __cpu_up (unsigned int cpu) if (cpu_data(cpu)->threads_per_core == 1 && cpu_data(cpu)->cores_per_socket == 1) { - cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, cpu_sibling_map[cpu]); cpu_set(cpu, cpu_core_map[cpu]); return 0; } diff --git a/trunk/arch/ia64/kernel/uncached.c b/trunk/arch/ia64/kernel/uncached.c index a7be4f203420..c58e933694d5 100644 --- a/trunk/arch/ia64/kernel/uncached.c +++ b/trunk/arch/ia64/kernel/uncached.c @@ -196,7 +196,7 @@ unsigned long uncached_alloc_page(int starting_nid) nid = starting_nid; do { - if (!node_state(nid, N_HIGH_MEMORY)) + if (!node_online(nid)) continue; uc_pool = &uncached_pools[nid]; if (uc_pool->pool == NULL) @@ -268,7 +268,7 @@ static int __init uncached_init(void) { int nid; - for_each_node_state(nid, N_ONLINE) { + for_each_online_node(nid) { uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid); mutex_init(&uncached_pools[nid].add_chunk_mutex); } diff --git a/trunk/arch/ia64/mm/discontig.c b/trunk/arch/ia64/mm/discontig.c index 5628067a74d2..0d34585058c8 100644 --- a/trunk/arch/ia64/mm/discontig.c +++ b/trunk/arch/ia64/mm/discontig.c @@ -715,11 +715,3 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat) scatter_node_data(); } #endif - -#ifdef CONFIG_SPARSEMEM_VMEMMAP -int __meminit vmemmap_populate(struct page *start_page, - unsigned long size, int node) -{ - return vmemmap_populate_basepages(start_page, size, node); -} -#endif diff --git a/trunk/arch/ia64/mm/fault.c b/trunk/arch/ia64/mm/fault.c index 32f26253c4e8..9150ffaff9e8 100644 --- a/trunk/arch/ia64/mm/fault.c +++ b/trunk/arch/ia64/mm/fault.c @@ -281,6 +281,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re } printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; } diff --git a/trunk/arch/ia64/mm/hugetlbpage.c b/trunk/arch/ia64/mm/hugetlbpage.c index d3ce8f3bcaa6..a9ff685aea25 100644 --- a/trunk/arch/ia64/mm/hugetlbpage.c +++ b/trunk/arch/ia64/mm/hugetlbpage.c @@ -194,6 +194,6 @@ static int __init hugetlb_setup_sz(char *str) * override here with new page shift. */ ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2); - return 0; + return 1; } -early_param("hugepagesz", hugetlb_setup_sz); +__setup("hugepagesz=", hugetlb_setup_sz); diff --git a/trunk/arch/ia64/mm/init.c b/trunk/arch/ia64/mm/init.c index 3e10152abbf0..c14abefabafa 100644 --- a/trunk/arch/ia64/mm/init.c +++ b/trunk/arch/ia64/mm/init.c @@ -54,12 +54,15 @@ struct page *zero_page_memmap_ptr; /* map entry for zero page */ EXPORT_SYMBOL(zero_page_memmap_ptr); void -__ia64_sync_icache_dcache (pte_t pte) +lazy_mmu_prot_update (pte_t pte) { unsigned long addr; struct page *page; unsigned long order; + if (!pte_exec(pte)) + return; /* not an executable page... */ + page = pte_page(pte); addr = (unsigned long) page_address(page); @@ -718,21 +721,10 @@ int arch_add_memory(int nid, u64 start, u64 size) return ret; } -#ifdef CONFIG_MEMORY_HOTREMOVE + int remove_memory(u64 start, u64 size) { - unsigned long start_pfn, end_pfn; - unsigned long timeout = 120 * HZ; - int ret; - start_pfn = start >> PAGE_SHIFT; - end_pfn = start_pfn + (size >> PAGE_SHIFT); - ret = offline_pages(start_pfn, end_pfn, timeout); - if (ret) - goto out; - /* we can free mem_map at this point */ -out: - return ret; + return -EINVAL; } EXPORT_SYMBOL_GPL(remove_memory); -#endif /* CONFIG_MEMORY_HOTREMOVE */ #endif diff --git a/trunk/arch/ia64/sn/kernel/Makefile b/trunk/arch/ia64/sn/kernel/Makefile index 688a3c27e0f6..0a59371d3475 100644 --- a/trunk/arch/ia64/sn/kernel/Makefile +++ b/trunk/arch/ia64/sn/kernel/Makefile @@ -7,7 +7,7 @@ # Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved. # -EXTRA_CFLAGS += -Iarch/ia64/sn/include +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ huberror.o io_acpi_init.o io_common.o \ diff --git a/trunk/arch/ia64/sn/kernel/sn2/Makefile b/trunk/arch/ia64/sn/kernel/sn2/Makefile index 08e6565dc908..99e177693234 100644 --- a/trunk/arch/ia64/sn/kernel/sn2/Makefile +++ b/trunk/arch/ia64/sn/kernel/sn2/Makefile @@ -9,7 +9,7 @@ # sn2 specific kernel files # -EXTRA_CFLAGS += -Iarch/ia64/sn/include +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/trunk/arch/ia64/sn/pci/Makefile b/trunk/arch/ia64/sn/pci/Makefile index ad4ef34dfe26..c6946784a6a8 100644 --- a/trunk/arch/ia64/sn/pci/Makefile +++ b/trunk/arch/ia64/sn/pci/Makefile @@ -7,6 +7,6 @@ # # Makefile for the sn pci general routines. -EXTRA_CFLAGS += -Iarch/ia64/sn/include +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ diff --git a/trunk/arch/ia64/sn/pci/pci_dma.c b/trunk/arch/ia64/sn/pci/pci_dma.c index ecd8a52b9b9e..d79ddacfba2d 100644 --- a/trunk/arch/ia64/sn/pci/pci_dma.c +++ b/trunk/arch/ia64/sn/pci/pci_dma.c @@ -218,17 +218,16 @@ EXPORT_SYMBOL(sn_dma_unmap_single); * * Unmap a set of streaming mode DMA translations. */ -void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, +void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, int direction) { int i; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); - struct scatterlist *sg; BUG_ON(dev->bus != &pci_bus_type); - for_each_sg(sgl, sg, nhwentries, i) { + for (i = 0; i < nhwentries; i++, sg++) { provider->dma_unmap(pdev, sg->dma_address, direction); sg->dma_address = (dma_addr_t) NULL; sg->dma_length = 0; @@ -245,11 +244,11 @@ EXPORT_SYMBOL(sn_dma_unmap_sg); * * Maps each entry of @sg for DMA. */ -int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, +int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries, int direction) { unsigned long phys_addr; - struct scatterlist *saved_sg = sgl, *sg; + struct scatterlist *saved_sg = sg; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); int i; @@ -259,7 +258,7 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, /* * Setup a DMA address for each entry in the scatterlist. */ - for_each_sg(sgl, sg, nhwentries, i) { + for (i = 0; i < nhwentries; i++, sg++) { phys_addr = SG_ENT_PHYS_ADDRESS(sg); sg->dma_address = provider->dma_map(pdev, phys_addr, sg->length, diff --git a/trunk/arch/ia64/sn/pci/pcibr/Makefile b/trunk/arch/ia64/sn/pci/pcibr/Makefile index 01192d3247dd..3b403ea456f9 100644 --- a/trunk/arch/ia64/sn/pci/pcibr/Makefile +++ b/trunk/arch/ia64/sn/pci/pcibr/Makefile @@ -7,7 +7,7 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS += -Iarch/ia64/sn/include +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y += pcibr_dma.o pcibr_reg.o \ pcibr_ate.o pcibr_provider.o diff --git a/trunk/arch/m32r/Makefile b/trunk/arch/m32r/Makefile index 4072a07ebf8e..60e12f312654 100644 --- a/trunk/arch/m32r/Makefile +++ b/trunk/arch/m32r/Makefile @@ -9,7 +9,7 @@ LDFLAGS := OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -KBUILD_CFLAGS += -pipe -fno-schedule-insns +CFLAGS += -pipe -fno-schedule-insns CFLAGS_KERNEL += -mmodel=medium CFLAGS_MODULE += -mmodel=large @@ -24,14 +24,14 @@ endif cflags-$(CONFIG_ISA_M32R) += -DNO_FPU aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -O2 -Wa,-no-bitinst -KBUILD_CFLAGS += $(cflags-y) -KBUILD_AFLAGS += $(aflags-y) +CFLAGS += $(cflags-y) +AFLAGS += $(aflags-y) CHECKFLAGS += -D__m32r__ -D__BIG_ENDIAN__=1 head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) libs-y += arch/m32r/lib/ $(LIBGCC) core-y += arch/m32r/kernel/ \ diff --git a/trunk/arch/m32r/kernel/ptrace.c b/trunk/arch/m32r/kernel/ptrace.c index ed4d0756c5db..62a51429306e 100644 --- a/trunk/arch/m32r/kernel/ptrace.c +++ b/trunk/arch/m32r/kernel/ptrace.c @@ -570,7 +570,7 @@ withdraw_debug_trap(struct pt_regs *regs) } } -void +static void init_debug_traps(struct task_struct *child) { struct debug_trap *p = &child->thread.debug_trap; @@ -593,8 +593,8 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -long -arch_ptrace(struct task_struct *child, long request, long addr, long data) +static int +do_ptrace(long request, struct task_struct *child, long addr, long data) { int ret; @@ -704,6 +704,14 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + /* + * detach a process that was attached. + */ + case PTRACE_DETACH: + ret = 0; + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; @@ -720,6 +728,42 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + if (ret == 0) + init_debug_traps(child); + goto out_tsk; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret == 0) + ret = do_ptrace(request, child, addr, data); + +out_tsk: + put_task_struct(child); +out: + unlock_kernel(); + + return ret; +} + /* notification of system call entry/exit * - triggered by current->work.syscall_trace */ diff --git a/trunk/arch/m32r/kernel/time.c b/trunk/arch/m32r/kernel/time.c index 994cc1556355..3858c9f39ba5 100644 --- a/trunk/arch/m32r/kernel/time.c +++ b/trunk/arch/m32r/kernel/time.c @@ -228,12 +228,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct irqaction irq0 = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "MFT2", -}; +struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, + "MFT2", NULL, NULL }; void __init time_init(void) { diff --git a/trunk/arch/m32r/mm/fault.c b/trunk/arch/m32r/mm/fault.c index 70a766aad3e0..676a1c443d28 100644 --- a/trunk/arch/m32r/mm/fault.c +++ b/trunk/arch/m32r/mm/fault.c @@ -278,7 +278,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, } printk("VM: killing process %s\n", tsk->comm); if (error_code & ACE_USERMODE) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/m68k/Makefile b/trunk/arch/m68k/Makefile index 4a1bd44ff162..aa383a5ea7ac 100644 --- a/trunk/arch/m68k/Makefile +++ b/trunk/arch/m68k/Makefile @@ -32,18 +32,18 @@ endif CHECKFLAGS += -D__mc68000__ # without -fno-strength-reduce the 53c7xx.c driver fails ;-( -KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 +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 +CFLAGS := $(CFLAGS) -m68040 endif ifndef CONFIG_M68040 -KBUILD_CFLAGS += -m68060 +CFLAGS := $(CFLAGS) -m68060 endif endif @@ -52,7 +52,7 @@ 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 +CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g endif ifndef CONFIG_SUN3 diff --git a/trunk/arch/m68k/kernel/ptrace.c b/trunk/arch/m68k/kernel/ptrace.c index 2075543c2d92..e792d3cba4c7 100644 --- a/trunk/arch/m68k/kernel/ptrace.c +++ b/trunk/arch/m68k/kernel/ptrace.c @@ -226,6 +226,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); break; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: /* Get all gp regs from the child. */ for (i = 0; i < 19; i++) { tmp = get_reg(child, i); diff --git a/trunk/arch/m68k/mm/fault.c b/trunk/arch/m68k/mm/fault.c index eaa618681159..578b48f47b9e 100644 --- a/trunk/arch/m68k/mm/fault.c +++ b/trunk/arch/m68k/mm/fault.c @@ -188,7 +188,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); no_context: current->thread.signo = SIGBUS; diff --git a/trunk/arch/m68knommu/Makefile b/trunk/arch/m68knommu/Makefile index 92227aaaa26e..1305cc980023 100644 --- a/trunk/arch/m68knommu/Makefile +++ b/trunk/arch/m68knommu/Makefile @@ -102,11 +102,11 @@ cflags-$(CONFIG_M68EZ328) := -m68000 cflags-$(CONFIG_M68VZ328) := -m68000 cflags-$(CONFIG_M68360) := -m68332 -KBUILD_AFLAGS += $(cflags-y) +AFLAGS += $(cflags-y) -KBUILD_CFLAGS += $(cflags-y) -KBUILD_CFLAGS += -D__linux__ -KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" +CFLAGS += $(cflags-y) +CFLAGS += -D__linux__ +CFLAGS += -DUTS_SYSNAME=\"uClinux\" head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o diff --git a/trunk/arch/m68knommu/platform/5206/Makefile b/trunk/arch/m68knommu/platform/5206/Makefile index c7bb0cef31a0..701b7abe019d 100644 --- a/trunk/arch/m68knommu/platform/5206/Makefile +++ b/trunk/arch/m68knommu/platform/5206/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/5206e/Makefile b/trunk/arch/m68knommu/platform/5206e/Makefile index c7bb0cef31a0..701b7abe019d 100644 --- a/trunk/arch/m68knommu/platform/5206e/Makefile +++ b/trunk/arch/m68knommu/platform/5206e/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/520x/Makefile b/trunk/arch/m68knommu/platform/520x/Makefile index 31b4eb51739d..e861b05106bc 100644 --- a/trunk/arch/m68knommu/platform/520x/Makefile +++ b/trunk/arch/m68knommu/platform/520x/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/523x/Makefile b/trunk/arch/m68knommu/platform/523x/Makefile index ac9fbece8a4f..c1578b016160 100644 --- a/trunk/arch/m68knommu/platform/523x/Makefile +++ b/trunk/arch/m68knommu/platform/523x/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/5249/Makefile b/trunk/arch/m68knommu/platform/5249/Makefile index c7bb0cef31a0..701b7abe019d 100644 --- a/trunk/arch/m68knommu/platform/5249/Makefile +++ b/trunk/arch/m68knommu/platform/5249/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/5272/Makefile b/trunk/arch/m68knommu/platform/5272/Makefile index 7475c38c3b4e..0871a29dd589 100644 --- a/trunk/arch/m68knommu/platform/5272/Makefile +++ b/trunk/arch/m68knommu/platform/5272/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/527x/Makefile b/trunk/arch/m68knommu/platform/527x/Makefile index 7475c38c3b4e..0871a29dd589 100644 --- a/trunk/arch/m68knommu/platform/527x/Makefile +++ b/trunk/arch/m68knommu/platform/527x/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/528x/Makefile b/trunk/arch/m68knommu/platform/528x/Makefile index 7475c38c3b4e..0871a29dd589 100644 --- a/trunk/arch/m68knommu/platform/528x/Makefile +++ b/trunk/arch/m68knommu/platform/528x/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/m68knommu/platform/5307/Makefile b/trunk/arch/m68knommu/platform/5307/Makefile index 5b600530c8d2..719a313494bc 100644 --- a/trunk/arch/m68knommu/platform/5307/Makefile +++ b/trunk/arch/m68knommu/platform/5307/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-$(CONFIG_COLDFIRE) += entry.o vectors.o diff --git a/trunk/arch/m68knommu/platform/532x/Makefile b/trunk/arch/m68knommu/platform/532x/Makefile index 475b92866a9b..12301803b9eb 100644 --- a/trunk/arch/m68knommu/platform/532x/Makefile +++ b/trunk/arch/m68knommu/platform/532x/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif #obj-y := config.o usb-mcf532x.o spi-mcf532x.o diff --git a/trunk/arch/m68knommu/platform/5407/Makefile b/trunk/arch/m68knommu/platform/5407/Makefile index 68633b27df51..91b2f495dd39 100644 --- a/trunk/arch/m68knommu/platform/5407/Makefile +++ b/trunk/arch/m68knommu/platform/5407/Makefile @@ -13,7 +13,7 @@ # ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif obj-y := config.o diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 235d4514e0a9..f943736541cb 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -133,7 +133,6 @@ config LASAT select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI - select IRQ_CPU select PCI_GT64XXX_PCI0 select MIPS_NILE4 select R5000_CPU_SCACHE @@ -411,7 +410,6 @@ config SGI_IP32 select BOOT_ELF32 select DMA_NONCOHERENT select HW_HAS_PCI - select IRQ_CPU select R5000_CPU_SCACHE select RM7000_CPU_SCACHE select SYS_HAS_CPU_R5000 diff --git a/trunk/arch/mips/Makefile b/trunk/arch/mips/Makefile index 6b663bec4752..ebd5d02a7d78 100644 --- a/trunk/arch/mips/Makefile +++ b/trunk/arch/mips/Makefile @@ -608,14 +608,14 @@ ifdef CONFIG_64BIT endif endif -KBUILD_AFLAGS += $(cflags-y) -KBUILD_CFLAGS += $(cflags-y) \ +AFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) \ -D"VMLINUX_LOAD_ADDRESS=$(load-y)" LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/") ifdef CONFIG_64BIT @@ -632,7 +632,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo # CPPFLAGS_vmlinux.lds := \ - $(KBUILD_CFLAGS) \ + $(CFLAGS) \ -D"LOADADDR=$(load-y)" \ -D"JIFFIES=$(JIFFIES)" \ -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)" diff --git a/trunk/arch/mips/au1000/common/au1xxx_irqmap.c b/trunk/arch/mips/au1000/common/au1xxx_irqmap.c index 98a4e34b0248..7acfe9bf5fc3 100644 --- a/trunk/arch/mips/au1000/common/au1xxx_irqmap.c +++ b/trunk/arch/mips/au1000/common/au1xxx_irqmap.c @@ -54,7 +54,7 @@ * Careful if you change match 2 request! * The interrupt handler is called directly from the low level dispatch code. */ -struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = { +au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = { #if defined(CONFIG_SOC_AU1000) { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, diff --git a/trunk/arch/mips/au1000/common/dbdma.c b/trunk/arch/mips/au1000/common/dbdma.c index 9d6ad43fded6..461cf0139737 100644 --- a/trunk/arch/mips/au1000/common/dbdma.c +++ b/trunk/arch/mips/au1000/common/dbdma.c @@ -859,7 +859,7 @@ dbdma_interrupt(int irq, void *dev_id) intstat = dbdma_gptr->ddma_intstat; au_sync(); - chan_index = ffs(intstat); + chan_index = au_ffs(intstat) - 1; ctp = chan_tab_ptr[chan_index]; cp = ctp->chan_ptr; diff --git a/trunk/arch/mips/au1000/common/irq.c b/trunk/arch/mips/au1000/common/irq.c index c00f308fd505..a6640b998c6e 100644 --- a/trunk/arch/mips/au1000/common/irq.c +++ b/trunk/arch/mips/au1000/common/irq.c @@ -26,18 +26,39 @@ * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #ifdef CONFIG_MIPS_PB1000 #include #endif +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + #define EXT_INTC0_REQ0 2 /* IP 2 */ #define EXT_INTC0_REQ1 3 /* IP 3 */ #define EXT_INTC1_REQ0 4 /* IP 4 */ @@ -48,98 +69,16 @@ void (*board_init_irq)(void); static DEFINE_SPINLOCK(irq_lock); -#ifdef CONFIG_PM - -/* - * Save/restore the interrupt controller state. - * Called from the save/restore core registers as part of the - * au_sleep function in power.c.....maybe I should just pm_register() - * them instead? - */ -static unsigned int sleep_intctl_config0[2]; -static unsigned int sleep_intctl_config1[2]; -static unsigned int sleep_intctl_config2[2]; -static unsigned int sleep_intctl_src[2]; -static unsigned int sleep_intctl_assign[2]; -static unsigned int sleep_intctl_wake[2]; -static unsigned int sleep_intctl_mask[2]; - -void save_au1xxx_intctl(void) -{ - sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); - sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); - sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); - sleep_intctl_src[0] = au_readl(IC0_SRCRD); - sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); - sleep_intctl_wake[0] = au_readl(IC0_WAKERD); - sleep_intctl_mask[0] = au_readl(IC0_MASKRD); - - sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); - sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); - sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); - sleep_intctl_src[1] = au_readl(IC1_SRCRD); - sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); - sleep_intctl_wake[1] = au_readl(IC1_WAKERD); - sleep_intctl_mask[1] = au_readl(IC1_MASKRD); -} - -/* - * For most restore operations, we clear the entire register and - * then set the bits we found during the save. - */ -void restore_au1xxx_intctl(void) -{ - au_writel(0xffffffff, IC0_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); - au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); - au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); - au_writel(0xffffffff, IC0_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); - au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC0_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); - au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC0_TESTBIT); au_sync(); - - au_writel(0xffffffff, IC1_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); - au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); - au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); - au_writel(0xffffffff, IC1_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); - au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC1_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); - au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC1_TESTBIT); au_sync(); - - au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); - - au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); -} -#endif /* CONFIG_PM */ - inline void local_enable_irq(unsigned int irq_nr) { if (irq_nr > AU1000_LAST_INTC0_INT) { - au_writel(1 << (irq_nr - 32), IC1_MASKSET); - au_writel(1 << (irq_nr - 32), IC1_WAKESET); - } else { - au_writel(1 << irq_nr, IC0_MASKSET); - au_writel(1 << irq_nr, IC0_WAKESET); + au_writel(1<<(irq_nr-32), IC1_MASKSET); + au_writel(1<<(irq_nr-32), IC1_WAKESET); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1 << (irq_nr - 32), IC1_MASKCLR); - au_writel(1 << (irq_nr - 32), IC1_WAKECLR); - } else { - au_writel(1 << irq_nr, IC0_MASKCLR); - au_writel(1 << irq_nr, IC0_WAKECLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_WAKECLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1 << (irq_nr - 32), IC1_RISINGCLR); - au_writel(1 << (irq_nr - 32), IC1_MASKCLR); - } else { - au_writel(1 << irq_nr, IC0_RISINGCLR); - au_writel(1 << irq_nr, IC0_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_RISINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1 << (irq_nr - 32), IC1_FALLINGCLR); - au_writel(1 << (irq_nr - 32), IC1_MASKCLR); - } else { - au_writel(1 << irq_nr, IC0_FALLINGCLR); - au_writel(1 << irq_nr, IC0_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1 << (irq_nr - 32), IC1_FALLINGCLR); - au_writel(1 << (irq_nr - 32), IC1_RISINGCLR); - au_writel(1 << (irq_nr - 32), IC1_MASKCLR); - } else { - au_writel(1 << irq_nr, IC0_FALLINGCLR); - au_writel(1 << irq_nr, IC0_RISINGCLR); - au_writel(1 << irq_nr, IC0_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); + au_writel(1<<(irq_nr-32), IC1_RISINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &rise_edge_irq_type); - break; - case INTC_INT_FALL_EDGE: /* 0:1:0 */ - au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG1SET); - au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &fall_edge_irq_type); - break; - case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ - au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG1SET); - au_writel(1 << (irq_nr - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &either_edge_irq_type); - break; - case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ - au_writel(1 << (irq_nr - 32), IC1_CFG2SET); - au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG0SET); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_LOW_LEVEL: /* 1:1:0 */ - au_writel(1 << (irq_nr - 32), IC1_CFG2SET); - au_writel(1 << (irq_nr - 32), IC1_CFG1SET); - au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_DISABLED: /* 0:0:0 */ - au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); - break; - default: /* disable the interrupt */ - printk(KERN_WARNING "unexpected int type %d (irq %d)\n", - type, irq_nr); - au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); - au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); - return; + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + set_irq_chip(irq_nr, &rise_edge_irq_type); + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &fall_edge_irq_type); + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + set_irq_chip(irq_nr, &either_edge_irq_type); + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2SET); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG2SET); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + break; + default: /* disable the interrupt */ + printk("unexpected int type %d (irq %d)\n", type, irq_nr); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + return; } if (int_req) /* assign to interrupt request 1 */ - au_writel(1 << (irq_nr - 32), IC1_ASSIGNCLR); + au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR); else /* assign to interrupt request 0 */ - au_writel(1 << (irq_nr - 32), IC1_ASSIGNSET); - au_writel(1 << (irq_nr - 32), IC1_SRCSET); - au_writel(1 << (irq_nr - 32), IC1_MASKCLR); - au_writel(1 << (irq_nr - 32), IC1_WAKECLR); - } else { + au_writel(1<<(irq_nr-32), IC1_ASSIGNSET); + au_writel(1<<(irq_nr-32), IC1_SRCSET); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_WAKECLR); + } + else { switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1 << irq_nr, IC0_CFG2CLR); - au_writel(1 << irq_nr, IC0_CFG1CLR); - au_writel(1 << irq_nr, IC0_CFG0SET); - set_irq_chip(irq_nr, &rise_edge_irq_type); - break; - case INTC_INT_FALL_EDGE: /* 0:1:0 */ - au_writel(1 << irq_nr, IC0_CFG2CLR); - au_writel(1 << irq_nr, IC0_CFG1SET); - au_writel(1 << irq_nr, IC0_CFG0CLR); - set_irq_chip(irq_nr, &fall_edge_irq_type); - break; - case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ - au_writel(1 << irq_nr, IC0_CFG2CLR); - au_writel(1 << irq_nr, IC0_CFG1SET); - au_writel(1 << irq_nr, IC0_CFG0SET); - set_irq_chip(irq_nr, &either_edge_irq_type); - break; - case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ - au_writel(1 << irq_nr, IC0_CFG2SET); - au_writel(1 << irq_nr, IC0_CFG1CLR); - au_writel(1 << irq_nr, IC0_CFG0SET); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_LOW_LEVEL: /* 1:1:0 */ - au_writel(1 << irq_nr, IC0_CFG2SET); - au_writel(1 << irq_nr, IC0_CFG1SET); - au_writel(1 << irq_nr, IC0_CFG0CLR); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_DISABLED: /* 0:0:0 */ - au_writel(1 << irq_nr, IC0_CFG0CLR); - au_writel(1 << irq_nr, IC0_CFG1CLR); - au_writel(1 << irq_nr, IC0_CFG2CLR); - break; - default: /* disable the interrupt */ - printk(KERN_WARNING "unexpected int type %d (irq %d)\n", - type, irq_nr); - au_writel(1 << irq_nr, IC0_CFG0CLR); - au_writel(1 << irq_nr, IC0_CFG1CLR); - au_writel(1 << irq_nr, IC0_CFG2CLR); - return; + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1<im_irq, imp->im_type, imp->im_request); + imp++; + } + + /* Now set up the irq mapping for the board. + */ + imp = au1xxx_irq_map; + for (i=0; iim_irq, imp->im_type, imp->im_request); + imp++; + } + + set_c0_status(ALLINTS); + + /* Board specific IRQ initialization. + */ + if (board_init_irq) + (*board_init_irq)(); +} + + /* * Interrupts are nested. Even if an interrupt handler is registered * as "fast", we might get another interrupt before we return from @@ -462,27 +468,26 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req) static void intc0_req0_irqdispatch(void) { int irq = 0; - static unsigned long intc0_req0; + static unsigned long intc0_req0 = 0; intc0_req0 |= au_readl(IC0_REQ0INT); if (!intc0_req0) return; - #ifdef AU1000_USB_DEV_REQ_INT /* * Because of the tight timing of SETUP token to reply * transactions, the USB devices-side packet complete * interrupt needs the highest priority. */ - if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { - intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); + if ((intc0_req0 & (1<im_irq, imp->im_type, imp->im_request); - imp++; - } - - /* Now set up the irq mapping for the board. - */ - imp = au1xxx_irq_map; - for (i = 0; i < au1xxx_nr_irqs; i++) { - setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); - imp++; - } - - set_c0_status(ALLINTS); - - /* Board specific IRQ initialization. - */ - if (board_init_irq) - (*board_init_irq)(); -} diff --git a/trunk/arch/mips/au1000/db1x00/irqmap.c b/trunk/arch/mips/au1000/db1x00/irqmap.c index 09cea03411b0..3e5729145c2b 100644 --- a/trunk/arch/mips/au1000/db1x00/irqmap.c +++ b/trunk/arch/mips/au1000/db1x00/irqmap.c @@ -79,7 +79,7 @@ char irq_tab_alchemy[][5] __initdata = { #endif -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { #ifndef CONFIG_MIPS_MIRAGE #ifdef CONFIG_MIPS_DB1550 diff --git a/trunk/arch/mips/au1000/mtx-1/irqmap.c b/trunk/arch/mips/au1000/mtx-1/irqmap.c index 49c612aeddcf..a4fa0f227e42 100644 --- a/trunk/arch/mips/au1000/mtx-1/irqmap.c +++ b/trunk/arch/mips/au1000/mtx-1/irqmap.c @@ -58,7 +58,7 @@ char irq_tab_alchemy[][5] __initdata = { [7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ }; -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/trunk/arch/mips/au1000/pb1000/irqmap.c b/trunk/arch/mips/au1000/pb1000/irqmap.c index 88e354508204..156500ba467f 100644 --- a/trunk/arch/mips/au1000/pb1000/irqmap.c +++ b/trunk/arch/mips/au1000/pb1000/irqmap.c @@ -47,7 +47,7 @@ #include #include -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, }; diff --git a/trunk/arch/mips/au1000/pb1100/irqmap.c b/trunk/arch/mips/au1000/pb1100/irqmap.c index 880456bf8c11..d986916221b7 100644 --- a/trunk/arch/mips/au1000/pb1100/irqmap.c +++ b/trunk/arch/mips/au1000/pb1100/irqmap.c @@ -47,7 +47,7 @@ #include #include -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted# { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG# { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ# diff --git a/trunk/arch/mips/au1000/pb1200/irqmap.c b/trunk/arch/mips/au1000/pb1200/irqmap.c index 3bee274445f5..7c708db04a88 100644 --- a/trunk/arch/mips/au1000/pb1200/irqmap.c +++ b/trunk/arch/mips/au1000/pb1200/irqmap.c @@ -54,7 +54,7 @@ #define PB1200_INT_END DB1200_INT_END #endif -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade }; @@ -74,7 +74,7 @@ irqreturn_t pb1200_cascade_handler( int irq, void *dev_id) bcsr->int_status = bisr; for( ; bisr; bisr &= (bisr-1) ) { - extirq_nr = PB1200_INT_BEGIN + au_ffs(bisr); + extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr); /* Ack and dispatch IRQ */ do_IRQ(extirq_nr); } diff --git a/trunk/arch/mips/au1000/pb1500/irqmap.c b/trunk/arch/mips/au1000/pb1500/irqmap.c index 810f695e24bb..409d1612bb63 100644 --- a/trunk/arch/mips/au1000/pb1500/irqmap.c +++ b/trunk/arch/mips/au1000/pb1500/irqmap.c @@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ }; -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/trunk/arch/mips/au1000/pb1550/irqmap.c b/trunk/arch/mips/au1000/pb1550/irqmap.c index 56becab28e5d..24a9d186cf5a 100644 --- a/trunk/arch/mips/au1000/pb1550/irqmap.c +++ b/trunk/arch/mips/au1000/pb1550/irqmap.c @@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ }; -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, }; diff --git a/trunk/arch/mips/au1000/xxs1500/irqmap.c b/trunk/arch/mips/au1000/xxs1500/irqmap.c index 389349295d70..3844c6429e27 100644 --- a/trunk/arch/mips/au1000/xxs1500/irqmap.c +++ b/trunk/arch/mips/au1000/xxs1500/irqmap.c @@ -47,7 +47,7 @@ #include #include -struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/trunk/arch/mips/jmr3927/rbhma3100/setup.c b/trunk/arch/mips/jmr3927/rbhma3100/setup.c index 0c7aee1682cd..7f14f70a1b88 100644 --- a/trunk/arch/mips/jmr3927/rbhma3100/setup.c +++ b/trunk/arch/mips/jmr3927/rbhma3100/setup.c @@ -425,7 +425,7 @@ static int __init jmr3927_rtc_init(void) .flags = IORESOURCE_MEM, }; struct platform_device *dev; - dev = platform_device_register_simple("rtc-ds1742", -1, &res, 1); + dev = platform_device_register_simple("ds1742", -1, &res, 1); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } device_initcall(jmr3927_rtc_init); diff --git a/trunk/arch/mips/kernel/Makefile b/trunk/arch/mips/kernel/Makefile index 95a356ef3910..a2689f93c160 100644 --- a/trunk/arch/mips/kernel/Makefile +++ b/trunk/arch/mips/kernel/Makefile @@ -71,7 +71,7 @@ obj-$(CONFIG_PCSPEAKER) += pcspeaker.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) +CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o diff --git a/trunk/arch/mips/kernel/ptrace.c b/trunk/arch/mips/kernel/ptrace.c index 999f7853de26..58aa6fec1146 100644 --- a/trunk/arch/mips/kernel/ptrace.c +++ b/trunk/arch/mips/kernel/ptrace.c @@ -435,6 +435,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); break; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + case PTRACE_GET_THREAD_AREA: ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); diff --git a/trunk/arch/mips/kernel/time.c b/trunk/arch/mips/kernel/time.c index 05b365167a09..5892491b40eb 100644 --- a/trunk/arch/mips/kernel/time.c +++ b/trunk/arch/mips/kernel/time.c @@ -421,7 +421,7 @@ void __cpuinit mips_clockevent_init(void) cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); cd->shift = 32; cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ns = clockevent_delta2ns(0x30, cd); cd->rating = 300; cd->irq = irq; diff --git a/trunk/arch/mips/kernel/traps.c b/trunk/arch/mips/kernel/traps.c index 9c0c478d71ac..632bce1bf420 100644 --- a/trunk/arch/mips/kernel/traps.c +++ b/trunk/arch/mips/kernel/traps.c @@ -104,7 +104,7 @@ static int __init set_raw_show_trace(char *str) __setup("raw_show_trace", set_raw_show_trace); #endif -static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) +static void show_backtrace(struct task_struct *task, struct pt_regs *regs) { unsigned long sp = regs->regs[29]; unsigned long ra = regs->regs[31]; @@ -126,8 +126,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -static void show_stacktrace(struct task_struct *task, - const struct pt_regs *regs) +static void show_stacktrace(struct task_struct *task, struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); long stackdata; @@ -204,7 +203,7 @@ static void show_code(unsigned int __user *pc) } } -static void __show_regs(const struct pt_regs *regs) +void show_regs(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); unsigned int cause = regs->cp0_cause; @@ -300,17 +299,9 @@ static void __show_regs(const struct pt_regs *regs) cpu_name_string()); } -/* - * FIXME: really the generic show_regs should take a const pointer argument. - */ -void show_regs(struct pt_regs *regs) -{ - __show_regs((struct pt_regs *)regs); -} - -void show_registers(const struct pt_regs *regs) +void show_registers(struct pt_regs *regs) { - __show_regs(regs); + show_regs(regs); print_modules(); printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", current->comm, current->pid, current_thread_info(), current); @@ -321,7 +312,7 @@ void show_registers(const struct pt_regs *regs) static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, const struct pt_regs * regs) +void __noreturn die(const char * str, struct pt_regs * regs) { static int die_counter; #ifdef CONFIG_MIPS_MT_SMTC diff --git a/trunk/arch/mips/kernel/vmlinux.lds.S b/trunk/arch/mips/kernel/vmlinux.lds.S index 2781cff1485e..84f9a4cc6f2f 100644 --- a/trunk/arch/mips/kernel/vmlinux.lds.S +++ b/trunk/arch/mips/kernel/vmlinux.lds.S @@ -5,10 +5,6 @@ #define mips mips OUTPUT_ARCH(mips) ENTRY(kernel_entry) -PHDRS { - text PT_LOAD FLAGS(7); /* RWX */ - note PT_NOTE FLAGS(4); /* R__ */ -} jiffies = JIFFIES; SECTIONS @@ -25,6 +21,7 @@ SECTIONS * >= 0xa800 0000 0030 0000 otherwise */ + /* . = 0xa800000000300000; */ /* . = 0xa800000000300000; */ . = 0xffffffff80300000; #endif @@ -35,10 +32,9 @@ SECTIONS TEXT_TEXT SCHED_TEXT LOCK_TEXT - KPROBES_TEXT *(.fixup) *(.gnu.warning) - } :text = 0 + } =0 _etext = .; /* End of text section */ /* Exception table */ @@ -55,10 +51,6 @@ SECTIONS *(__dbe_table) __stop___dbe_table = .; } - - NOTES :text :note - .dummy : { *(.dummy) } :text - RODATA /* writeable */ @@ -209,4 +201,7 @@ SECTIONS *(.gptab.bss) *(.gptab.sbss) } + .note : { + *(.note) + } } diff --git a/trunk/arch/mips/kernel/vpe.c b/trunk/arch/mips/kernel/vpe.c index df8cbe4c7c0d..61b729fa0548 100644 --- a/trunk/arch/mips/kernel/vpe.c +++ b/trunk/arch/mips/kernel/vpe.c @@ -1317,8 +1317,7 @@ static void kspd_sp_exit( int sp_id) } #endif -static ssize_t store_kill(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_kill(struct class_device *dev, const char *buf, size_t len) { struct vpe *vpe = get_vpe(tclimit); struct vpe_notifications *not; @@ -1335,16 +1334,14 @@ static ssize_t store_kill(struct device *dev, struct device_attribute *attr, return len; } -static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr, - char *buf) +static ssize_t show_ntcs(struct class_device *cd, char *buf) { struct vpe *vpe = get_vpe(tclimit); return sprintf(buf, "%d\n", vpe->ntcs); } -static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_ntcs(struct class_device *dev, const char *buf, size_t len) { struct vpe *vpe = get_vpe(tclimit); unsigned long new; @@ -1365,13 +1362,13 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, return -EINVAL;; } -static struct device_attribute vpe_class_attributes[] = { +static struct class_device_attribute vpe_class_attributes[] = { __ATTR(kill, S_IWUSR, NULL, store_kill), __ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs), {} }; -static void vpe_device_release(struct device *cd) +static void vpe_class_device_release(struct class_device *cd) { kfree(cd); } @@ -1379,11 +1376,11 @@ static void vpe_device_release(struct device *cd) struct class vpe_class = { .name = "vpe", .owner = THIS_MODULE, - .dev_release = vpe_device_release, - .dev_attrs = vpe_class_attributes, + .release = vpe_class_device_release, + .class_dev_attrs = vpe_class_attributes, }; -struct device vpe_device; +struct class_device vpe_device; static int __init vpe_module_init(void) { @@ -1426,12 +1423,12 @@ static int __init vpe_module_init(void) goto out_chrdev; } - device_initialize(&vpe_device); + class_device_initialize(&vpe_device); vpe_device.class = &vpe_class, vpe_device.parent = NULL, - strlcpy(vpe_device.bus_id, "vpe1", BUS_ID_SIZE); + strlcpy(vpe_device.class_id, "vpe1", BUS_ID_SIZE); vpe_device.devt = MKDEV(major, minor); - err = device_add(&vpe_device); + err = class_device_add(&vpe_device); if (err) { printk(KERN_ERR "Adding vpe_device failed\n"); goto out_class; @@ -1576,7 +1573,7 @@ static void __exit vpe_module_exit(void) } } - device_del(&vpe_device); + class_device_del(&vpe_device); unregister_chrdev(major, module_name); } diff --git a/trunk/arch/mips/lasat/interrupt.c b/trunk/arch/mips/lasat/interrupt.c index ba9692be3564..5f35289bfff5 100644 --- a/trunk/arch/mips/lasat/interrupt.c +++ b/trunk/arch/mips/lasat/interrupt.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -89,7 +88,7 @@ asmlinkage void plat_irq_dispatch(void) int irq; if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */ - do_IRQ(7); + ll_timer_interrupt(7); return; } @@ -97,7 +96,7 @@ asmlinkage void plat_irq_dispatch(void) /* if int_status == 0, then the interrupt has already been cleared */ if (int_status) { - irq = LASATINT_BASE + ls1bit32(int_status); + irq = ls1bit32(int_status); do_IRQ(irq); } @@ -126,7 +125,6 @@ void __init arch_init_irq(void) panic("arch_init_irq: mips_machtype incorrect"); } - mips_cpu_irq_init(); - for (i = LASATINT_BASE; i <= LASATINT_END; i++) + for (i = 0; i <= LASATINT_END; i++) set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq); } diff --git a/trunk/arch/mips/mipssim/sim_cmdline.c b/trunk/arch/mips/mipssim/sim_cmdline.c index 74240e1ce5a5..c63021a5dc6c 100644 --- a/trunk/arch/mips/mipssim/sim_cmdline.c +++ b/trunk/arch/mips/mipssim/sim_cmdline.c @@ -28,5 +28,8 @@ char * __init prom_getcmdline(void) void __init prom_init_cmdline(void) { - /* XXX: Get boot line from environment? */ + char *cp; + cp = arcs_cmdline; + /* Get boot line from environment? */ + *cp = '\0'; } diff --git a/trunk/arch/mips/mm/c-r4k.c b/trunk/arch/mips/mm/c-r4k.c index d7088331fb0f..971f6c047b8a 100644 --- a/trunk/arch/mips/mm/c-r4k.c +++ b/trunk/arch/mips/mm/c-r4k.c @@ -983,15 +983,11 @@ static void __init probe_pcache(void) printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", icache_size >> 10, - cpu_has_vtag_icache ? "VIVT" : "VIPT", + cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", way_string[c->icache.ways], c->icache.linesz); - printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n", - dcache_size >> 10, way_string[c->dcache.ways], - (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT", - (c->dcache.flags & MIPS_CACHE_ALIASES) ? - "cache aliases" : "no aliases", - c->dcache.linesz); + printk("Primary data cache %ldkB, %s, linesize %d bytes.\n", + dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz); } /* diff --git a/trunk/arch/mips/mm/fault.c b/trunk/arch/mips/mm/fault.c index 5699c7713e2f..521771b373de 100644 --- a/trunk/arch/mips/mm/fault.c +++ b/trunk/arch/mips/mm/fault.c @@ -180,7 +180,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/mips/mm/init.c b/trunk/arch/mips/mm/init.c index 110ee7656b41..5240432e6d1d 100644 --- a/trunk/arch/mips/mm/init.c +++ b/trunk/arch/mips/mm/init.c @@ -211,7 +211,7 @@ void copy_user_highpage(struct page *to, struct page *from, void *vfrom, *vto; vto = kmap_atomic(to, KM_USER1); - if (cpu_has_dc_aliases && page_mapped(from)) { + if (cpu_has_dc_aliases && !Page_dcache_dirty(from)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); kunmap_coherent(); @@ -234,15 +234,12 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases && page_mapped(page)) { + if (cpu_has_dc_aliases) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); kunmap_coherent(); - } else { + } else memcpy(dst, src, len); - if (cpu_has_dc_aliases) - SetPageDcacheDirty(page); - } if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) flush_cache_page(vma, vaddr, page_to_pfn(page)); } @@ -253,15 +250,13 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases && page_mapped(page)) { - void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + if (cpu_has_dc_aliases) { + void *vfrom = + kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); kunmap_coherent(); - } else { + } else memcpy(dst, src, len); - if (cpu_has_dc_aliases) - SetPageDcacheDirty(page); - } } EXPORT_SYMBOL(copy_from_user_page); diff --git a/trunk/arch/mips/pci/pci-lasat.c b/trunk/arch/mips/pci/pci-lasat.c index 174f314933b5..5abd5c7119be 100644 --- a/trunk/arch/mips/pci/pci-lasat.c +++ b/trunk/arch/mips/pci/pci-lasat.c @@ -10,7 +10,6 @@ #include #include #include -#include extern struct pci_ops nile4_pci_ops; extern struct pci_ops gt64xxx_pci0_ops; @@ -55,15 +54,15 @@ static int __init lasat_pci_setup(void) arch_initcall(lasat_pci_setup); -#define LASATINT_ETH1 (LASATINT_BASE + 0) -#define LASATINT_ETH0 (LASATINT_BASE + 1) -#define LASATINT_HDC (LASATINT_BASE + 2) -#define LASATINT_COMP (LASATINT_BASE + 3) -#define LASATINT_HDLC (LASATINT_BASE + 4) -#define LASATINT_PCIA (LASATINT_BASE + 5) -#define LASATINT_PCIB (LASATINT_BASE + 6) -#define LASATINT_PCIC (LASATINT_BASE + 7) -#define LASATINT_PCID (LASATINT_BASE + 8) +#define LASATINT_ETH1 0 +#define LASATINT_ETH0 1 +#define LASATINT_HDC 2 +#define LASATINT_COMP 3 +#define LASATINT_HDLC 4 +#define LASATINT_PCIA 5 +#define LASATINT_PCIB 6 +#define LASATINT_PCIC 7 +#define LASATINT_PCID 8 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { diff --git a/trunk/arch/mips/sgi-ip22/Makefile b/trunk/arch/mips/sgi-ip22/Makefile index e3acb51b70b5..1fb3e353e212 100644 --- a/trunk/arch/mips/sgi-ip22/Makefile +++ b/trunk/arch/mips/sgi-ip22/Makefile @@ -7,5 +7,3 @@ obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o obj-$(CONFIG_EISA) += ip22-eisa.o - -EXTRA_CFLAGS += -Werror diff --git a/trunk/arch/mips/sgi-ip22/ip22-reset.c b/trunk/arch/mips/sgi-ip22/ip22-reset.c index a435b31cf031..63afd7e44428 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-reset.c +++ b/trunk/arch/mips/sgi-ip22/ip22-reset.c @@ -232,18 +232,11 @@ static struct notifier_block panic_block = { static int __init reboot_setup(void) { - int res; - _machine_restart = sgi_machine_restart; _machine_halt = sgi_machine_halt; pm_power_off = sgi_machine_power_off; - res = request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); - if (res) { - printk(KERN_ERR "Allocation of front panel IRQ failed\n"); - return res; - } - + request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); init_timer(&blink_timer); blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); diff --git a/trunk/arch/mips/sgi-ip32/ip32-irq.c b/trunk/arch/mips/sgi-ip32/ip32-irq.c index 7e8094f617bf..7f4b793c3df3 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-irq.c +++ b/trunk/arch/mips/sgi-ip32/ip32-irq.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -47,8 +46,7 @@ static void inline flush_mace_bus(void) #define DBG(x...) #endif -/* - * O2 irq map +/* O2 irq map * * IP0 -> software (ignored) * IP1 -> software (ignored) @@ -57,60 +55,60 @@ static void inline flush_mace_bus(void) * IP4 -> (irq2) X unknown * IP5 -> (irq3) X unknown * IP6 -> (irq4) X unknown - * IP7 -> (irq5) 7 CPU count/compare timer (system timer) + * IP7 -> (irq5) 0 CPU count/compare timer (system timer) * * crime: (C) * * CRIME_INT_STAT 31:0: * - * 0 -> 8 Video in 1 - * 1 -> 9 Video in 2 - * 2 -> 10 Video out - * 3 -> 11 Mace ethernet + * 0 -> 1 Video in 1 + * 1 -> 2 Video in 2 + * 2 -> 3 Video out + * 3 -> 4 Mace ethernet * 4 -> S SuperIO sub-interrupt * 5 -> M Miscellaneous sub-interrupt * 6 -> A Audio sub-interrupt - * 7 -> 15 PCI bridge errors - * 8 -> 16 PCI SCSI aic7xxx 0 - * 9 -> 17 PCI SCSI aic7xxx 1 - * 10 -> 18 PCI slot 0 - * 11 -> 19 unused (PCI slot 1) - * 12 -> 20 unused (PCI slot 2) - * 13 -> 21 unused (PCI shared 0) - * 14 -> 22 unused (PCI shared 1) - * 15 -> 23 unused (PCI shared 2) - * 16 -> 24 GBE0 (E) - * 17 -> 25 GBE1 (E) - * 18 -> 26 GBE2 (E) - * 19 -> 27 GBE3 (E) - * 20 -> 28 CPU errors - * 21 -> 29 Memory errors - * 22 -> 30 RE empty edge (E) - * 23 -> 31 RE full edge (E) - * 24 -> 32 RE idle edge (E) - * 25 -> 33 RE empty level - * 26 -> 34 RE full level - * 27 -> 35 RE idle level - * 28 -> 36 unused (software 0) (E) - * 29 -> 37 unused (software 1) (E) - * 30 -> 38 unused (software 2) - crime 1.5 CPU SysCorError (E) - * 31 -> 39 VICE + * 7 -> 8 PCI bridge errors + * 8 -> 9 PCI SCSI aic7xxx 0 + * 9 -> 10 PCI SCSI aic7xxx 1 + * 10 -> 11 PCI slot 0 + * 11 -> 12 unused (PCI slot 1) + * 12 -> 13 unused (PCI slot 2) + * 13 -> 14 unused (PCI shared 0) + * 14 -> 15 unused (PCI shared 1) + * 15 -> 16 unused (PCI shared 2) + * 16 -> 17 GBE0 (E) + * 17 -> 18 GBE1 (E) + * 18 -> 19 GBE2 (E) + * 19 -> 20 GBE3 (E) + * 20 -> 21 CPU errors + * 21 -> 22 Memory errors + * 22 -> 23 RE empty edge (E) + * 23 -> 24 RE full edge (E) + * 24 -> 25 RE idle edge (E) + * 25 -> 26 RE empty level + * 26 -> 27 RE full level + * 27 -> 28 RE idle level + * 28 -> 29 unused (software 0) (E) + * 29 -> 30 unused (software 1) (E) + * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 31 -> 32 VICE * * S, M, A: Use the MACE ISA interrupt register * MACE_ISA_INT_STAT 31:0 * - * 0-7 -> 40-47 Audio - * 8 -> 48 RTC - * 9 -> 49 Keyboard + * 0-7 -> 33-40 Audio + * 8 -> 41 RTC + * 9 -> 42 Keyboard * 10 -> X Keyboard polled - * 11 -> 51 Mouse + * 11 -> 44 Mouse * 12 -> X Mouse polled - * 13-15 -> 53-55 Count/compare timers - * 16-19 -> 56-59 Parallel (16 E) - * 20-25 -> 60-62 Serial 1 (22 E) - * 26-31 -> 66-71 Serial 2 (28 E) + * 13-15 -> 46-48 Count/compare timers + * 16-19 -> 49-52 Parallel (16 E) + * 20-25 -> 53-58 Serial 1 (22 E) + * 26-31 -> 59-64 Serial 2 (28 E) * - * Note that this means IRQs 12-14, 50, and 52 do not exist. This is a + * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a * different IRQ map than IRIX uses, but that's OK as Linux irq handling * is quite different anyway. */ @@ -132,6 +130,36 @@ struct irqaction cpuerr_irq = { .name = "CRIME CPU error", }; +/* + * For interrupts wired from a single device to the CPU. Only the clock + * uses this it seems, which is IRQ 0 and IP7. + */ + +static void enable_cpu_irq(unsigned int irq) +{ + set_c0_status(STATUSF_IP7); +} + +static void disable_cpu_irq(unsigned int irq) +{ + clear_c0_status(STATUSF_IP7); +} + +static void end_cpu_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_cpu_irq(irq); +} + +static struct irq_chip ip32_cpu_interrupt = { + .name = "IP32 CPU", + .ack = disable_cpu_irq, + .mask = disable_cpu_irq, + .mask_ack = disable_cpu_irq, + .unmask = enable_cpu_irq, + .end = end_cpu_irq, +}; + /* * This is for pure CRIME interrupts - ie not MACE. The advantage? * We get to split the register in half and do faster lookups. @@ -394,23 +422,15 @@ static void ip32_irq0(void) uint64_t crime_int; int irq = 0; - /* - * Sanity check interrupt numbering enum. - * MACE got 32 interrupts and there are 32 MACE ISA interrupts daisy - * chained. - */ - BUILD_BUG_ON(CRIME_VICE_IRQ - MACE_VID_IN1_IRQ != 31); - BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31); - crime_int = crime->istat & crime_mask; - irq = MACE_VID_IN1_IRQ + __ffs(crime_int); + irq = __ffs(crime_int); crime_int = 1 << irq; if (crime_int & CRIME_MACEISA_INT_MASK) { unsigned long mace_int = mace->perif.ctrl.istat; - irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ; + irq = __ffs(mace_int & maceisa_mask) + 32; } - + irq++; DBG("*irq %u*\n", irq); do_IRQ(irq); } @@ -437,7 +457,7 @@ static void ip32_irq4(void) static void ip32_irq5(void) { - do_IRQ(MIPS_CPU_IRQ_BASE + 7); + do_IRQ(IP32_R4K_TIMER_IRQ); } asmlinkage void plat_irq_dispatch(void) @@ -470,25 +490,21 @@ void __init arch_init_irq(void) mace->perif.ctrl.istat = 0; mace->perif.ctrl.imask = 0; - mips_cpu_irq_init(); - for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { - struct irq_chip *chip; - - switch (irq) { - case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: - chip = &ip32_mace_interrupt; - break; - case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ: - chip = &ip32_macepci_interrupt; - break; - case CRIME_GBE0_IRQ ... CRIME_VICE_IRQ: - chip = &ip32_crime_interrupt; - break; - default: - chip = &ip32_maceisa_interrupt; - } - - set_irq_chip(irq, chip); + for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { + struct irq_chip *controller; + + if (irq == IP32_R4K_TIMER_IRQ) + controller = &ip32_cpu_interrupt; + else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) + controller = &ip32_mace_interrupt; + else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) + controller = &ip32_macepci_interrupt; + else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) + controller = &ip32_crime_interrupt; + else + controller = &ip32_maceisa_interrupt; + + set_irq_chip(irq, controller); } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/trunk/arch/mips/sgi-ip32/ip32-setup.c b/trunk/arch/mips/sgi-ip32/ip32-setup.c index fc75bfcb0c0e..4125a5ba119e 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-setup.c +++ b/trunk/arch/mips/sgi-ip32/ip32-setup.c @@ -83,7 +83,7 @@ void __init plat_time_init(void) void __init plat_timer_setup(struct irqaction *irq) { irq->handler = no_action; - setup_irq(MIPS_CPU_IRQ_BASE + 7, irq); + setup_irq(IP32_R4K_TIMER_IRQ, irq); } void __init plat_mem_setup(void) diff --git a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index b97102a1c635..acaf613358c7 100644 --- a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -963,7 +963,7 @@ static int __init toshiba_rbtx4927_rtc_init(void) .flags = IORESOURCE_MEM, }; struct platform_device *dev = - platform_device_register_simple("rtc-ds1742", -1, &res, 1); + platform_device_register_simple("ds1742", -1, &res, 1); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } device_initcall(toshiba_rbtx4927_rtc_init); diff --git a/trunk/arch/parisc/Makefile b/trunk/arch/parisc/Makefile index f3d0d7c70977..760567a9ba16 100644 --- a/trunk/arch/parisc/Makefile +++ b/trunk/arch/parisc/Makefile @@ -63,7 +63,7 @@ cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000 head-y := arch/parisc/kernel/head.o -KBUILD_CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o kernel-$(CONFIG_HPUX) += hpux/ diff --git a/trunk/arch/parisc/kernel/ptrace.c b/trunk/arch/parisc/kernel/ptrace.c index 49c637970789..26ec774c5027 100644 --- a/trunk/arch/parisc/kernel/ptrace.c +++ b/trunk/arch/parisc/kernel/ptrace.c @@ -329,6 +329,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* give it a chance to run. */ goto out_wake; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + goto out_tsk; + case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); goto out_tsk; diff --git a/trunk/arch/parisc/math-emu/Makefile b/trunk/arch/parisc/math-emu/Makefile index 1f3f225897f5..affd4c80e3b7 100644 --- a/trunk/arch/parisc/math-emu/Makefile +++ b/trunk/arch/parisc/math-emu/Makefile @@ -3,7 +3,7 @@ # # See arch/parisc/math-emu/README -EXTRA_CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \ +CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \ -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \ -Wno-implicit-int diff --git a/trunk/arch/parisc/mm/fault.c b/trunk/arch/parisc/mm/fault.c index 1c091b415cd9..7899ab87785a 100644 --- a/trunk/arch/parisc/mm/fault.c +++ b/trunk/arch/parisc/mm/fault.c @@ -263,6 +263,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, up_read(&mm->mmap_sem); printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; } diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 5e001ad588a7..037664d496d7 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -295,7 +295,6 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y depends on PPC64 - select SPARSEMEM_VMEMMAP_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y diff --git a/trunk/arch/powerpc/Kconfig.debug b/trunk/arch/powerpc/Kconfig.debug index c939fe86a9e0..464f9b4b3169 100644 --- a/trunk/arch/powerpc/Kconfig.debug +++ b/trunk/arch/powerpc/Kconfig.debug @@ -144,7 +144,7 @@ config BDI_SWITCH config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" - depends on PPC_OF && PPC_MULTIPLATFORM + depends PPC_OF && PPC_MULTIPLATFORM help Say Y here to see progress messages from the boot firmware in text mode. Requires either BootX or Open Firmware. @@ -234,12 +234,12 @@ endchoice config PPC_EARLY_DEBUG_44x_PHYSLOW hex "Low 32 bits of early debug UART physical address" - depends on PPC_EARLY_DEBUG_44x + depends PPC_EARLY_DEBUG_44x default "0x40000200" config PPC_EARLY_DEBUG_44x_PHYSHIGH hex "EPRN of early debug UART physical address" - depends on PPC_EARLY_DEBUG_44x + depends PPC_EARLY_DEBUG_44x default "0x1" config PPC_EARLY_DEBUG_CPM_ADDR diff --git a/trunk/arch/powerpc/Makefile b/trunk/arch/powerpc/Makefile index 4e165342210a..643839a3f5d8 100644 --- a/trunk/arch/powerpc/Makefile +++ b/trunk/arch/powerpc/Makefile @@ -75,10 +75,10 @@ CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple -KBUILD_CPPFLAGS += $(CPPFLAGS-y) -KBUILD_AFLAGS += $(AFLAGS-y) -KBUILD_CFLAGS += -msoft-float -pipe $(CFLAGS-y) -CPP = $(CC) -E $(KBUILD_CFLAGS) +CPPFLAGS += $(CPPFLAGS-y) +AFLAGS += $(AFLAGS-y) +CFLAGS += -msoft-float -pipe $(CFLAGS-y) +CPP = $(CC) -E $(CFLAGS) CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__ @@ -88,35 +88,35 @@ GCC_BROKEN_VEC := $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi ifeq ($(CONFIG_POWER4_ONLY),y) ifeq ($(CONFIG_ALTIVEC),y) ifeq ($(GCC_BROKEN_VEC),y) - KBUILD_CFLAGS += $(call cc-option,-mcpu=970) + CFLAGS += $(call cc-option,-mcpu=970) else - KBUILD_CFLAGS += $(call cc-option,-mcpu=power4) + CFLAGS += $(call cc-option,-mcpu=power4) endif else - KBUILD_CFLAGS += $(call cc-option,-mcpu=power4) + CFLAGS += $(call cc-option,-mcpu=power4) endif else - KBUILD_CFLAGS += $(call cc-option,-mtune=power4) + CFLAGS += $(call cc-option,-mtune=power4) endif endif ifeq ($(CONFIG_TUNE_CELL),y) - KBUILD_CFLAGS += $(call cc-option,-mtune=cell) + CFLAGS += $(call cc-option,-mtune=cell) endif # No AltiVec instruction when building kernel -KBUILD_CFLAGS += $(call cc-option,-mno-altivec) +CFLAGS += $(call cc-option,-mno-altivec) # Enable unit-at-a-time mode when possible. It shrinks the # kernel considerably. -KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) +CFLAGS += $(call cc-option,-funit-at-a-time) # Never use string load/store instructions as they are # often slow when they are implemented at all -KBUILD_CFLAGS += -mno-string +CFLAGS += -mno-string ifeq ($(CONFIG_6xx),y) -KBUILD_CFLAGS += -mcpu=powerpc +CFLAGS += -mcpu=powerpc endif cpu-as-$(CONFIG_4xx) += -Wa,-m405 @@ -125,8 +125,8 @@ cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec cpu-as-$(CONFIG_E500) += -Wa,-me500 cpu-as-$(CONFIG_E200) += -Wa,-me200 -KBUILD_AFLAGS += $(cpu-as-y) -KBUILD_CFLAGS += $(cpu-as-y) +AFLAGS += $(cpu-as-y) +CFLAGS += $(cpu-as-y) head-y := arch/powerpc/kernel/head_$(CONFIG_WORD_SIZE).o head-$(CONFIG_8xx) := arch/powerpc/kernel/head_8xx.o diff --git a/trunk/arch/powerpc/configs/bamboo_defconfig b/trunk/arch/powerpc/configs/bamboo_defconfig index d22fed6d2cd9..b592dec4640f 100644 --- a/trunk/arch/powerpc/configs/bamboo_defconfig +++ b/trunk/arch/powerpc/configs/bamboo_defconfig @@ -91,9 +91,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -696,7 +695,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/celleb_defconfig b/trunk/arch/powerpc/configs/celleb_defconfig index 2c5969801bd6..b4ac498c3cce 100644 --- a/trunk/arch/powerpc/configs/celleb_defconfig +++ b/trunk/arch/powerpc/configs/celleb_defconfig @@ -92,9 +92,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1219,7 +1218,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/chrp32_defconfig b/trunk/arch/powerpc/configs/chrp32_defconfig index 6f27e57331d5..c3977e334b3b 100644 --- a/trunk/arch/powerpc/configs/chrp32_defconfig +++ b/trunk/arch/powerpc/configs/chrp32_defconfig @@ -92,9 +92,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1374,7 +1373,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/ebony_defconfig b/trunk/arch/powerpc/configs/ebony_defconfig index 35a95dda681e..3a50467b1f75 100644 --- a/trunk/arch/powerpc/configs/ebony_defconfig +++ b/trunk/arch/powerpc/configs/ebony_defconfig @@ -90,9 +90,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -774,7 +773,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/g5_defconfig b/trunk/arch/powerpc/configs/g5_defconfig index 0a6fa1fc9766..a655d87b3f8b 100644 --- a/trunk/arch/powerpc/configs/g5_defconfig +++ b/trunk/arch/powerpc/configs/g5_defconfig @@ -92,9 +92,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1581,7 +1580,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/holly_defconfig b/trunk/arch/powerpc/configs/holly_defconfig index 11009185d230..97d0202a9fe0 100644 --- a/trunk/arch/powerpc/configs/holly_defconfig +++ b/trunk/arch/powerpc/configs/holly_defconfig @@ -88,9 +88,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -910,7 +909,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/iseries_defconfig b/trunk/arch/powerpc/configs/iseries_defconfig index d78e3a6fc68c..3fe1929460e7 100644 --- a/trunk/arch/powerpc/configs/iseries_defconfig +++ b/trunk/arch/powerpc/configs/iseries_defconfig @@ -93,9 +93,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1057,7 +1056,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/kilauea_defconfig b/trunk/arch/powerpc/configs/kilauea_defconfig index fd1c530aa3ec..31790d329269 100644 --- a/trunk/arch/powerpc/configs/kilauea_defconfig +++ b/trunk/arch/powerpc/configs/kilauea_defconfig @@ -91,9 +91,8 @@ CONFIG_SIGNALFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -701,7 +700,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/linkstation_defconfig b/trunk/arch/powerpc/configs/linkstation_defconfig index 401033aefd40..a4e3ee045a6a 100644 --- a/trunk/arch/powerpc/configs/linkstation_defconfig +++ b/trunk/arch/powerpc/configs/linkstation_defconfig @@ -89,9 +89,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1460,7 +1459,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/lite5200_defconfig b/trunk/arch/powerpc/configs/lite5200_defconfig index dd78ed955eb0..d42e226d3a28 100644 --- a/trunk/arch/powerpc/configs/lite5200_defconfig +++ b/trunk/arch/powerpc/configs/lite5200_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -817,7 +816,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/maple_defconfig b/trunk/arch/powerpc/configs/maple_defconfig index 84b9ab4a5a92..96b538bc676b 100644 --- a/trunk/arch/powerpc/configs/maple_defconfig +++ b/trunk/arch/powerpc/configs/maple_defconfig @@ -90,9 +90,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1096,7 +1095,8 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_SLAB_LEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc7448_hpc2_defconfig b/trunk/arch/powerpc/configs/mpc7448_hpc2_defconfig index 87ae894551b7..05814a3b0e33 100644 --- a/trunk/arch/powerpc/configs/mpc7448_hpc2_defconfig +++ b/trunk/arch/powerpc/configs/mpc7448_hpc2_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc8272_ads_defconfig b/trunk/arch/powerpc/configs/mpc8272_ads_defconfig index 865a942ecc69..6b7951ec941a 100644 --- a/trunk/arch/powerpc/configs/mpc8272_ads_defconfig +++ b/trunk/arch/powerpc/configs/mpc8272_ads_defconfig @@ -85,9 +85,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -868,7 +867,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8313_rdb_defconfig b/trunk/arch/powerpc/configs/mpc8313_rdb_defconfig index 259d40d1eb5a..f387dac69d09 100644 --- a/trunk/arch/powerpc/configs/mpc8313_rdb_defconfig +++ b/trunk/arch/powerpc/configs/mpc8313_rdb_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1273,7 +1272,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc832x_mds_defconfig b/trunk/arch/powerpc/configs/mpc832x_mds_defconfig index dd68d1818d6b..fc6695302cc8 100644 --- a/trunk/arch/powerpc/configs/mpc832x_mds_defconfig +++ b/trunk/arch/powerpc/configs/mpc832x_mds_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc832x_rdb_defconfig b/trunk/arch/powerpc/configs/mpc832x_rdb_defconfig index 4f391028c79c..6d1c3e842051 100644 --- a/trunk/arch/powerpc/configs/mpc832x_rdb_defconfig +++ b/trunk/arch/powerpc/configs/mpc832x_rdb_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc834x_itx_defconfig b/trunk/arch/powerpc/configs/mpc834x_itx_defconfig index eb28dd85cb2b..ddafa6b9af05 100644 --- a/trunk/arch/powerpc/configs/mpc834x_itx_defconfig +++ b/trunk/arch/powerpc/configs/mpc834x_itx_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc834x_itxgp_defconfig b/trunk/arch/powerpc/configs/mpc834x_itxgp_defconfig index 22b95462c913..8241c6985861 100644 --- a/trunk/arch/powerpc/configs/mpc834x_itxgp_defconfig +++ b/trunk/arch/powerpc/configs/mpc834x_itxgp_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc834x_mds_defconfig b/trunk/arch/powerpc/configs/mpc834x_mds_defconfig index e59a88e95486..06233b1a9418 100644 --- a/trunk/arch/powerpc/configs/mpc834x_mds_defconfig +++ b/trunk/arch/powerpc/configs/mpc834x_mds_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc836x_mds_defconfig b/trunk/arch/powerpc/configs/mpc836x_mds_defconfig index 75657528518e..3045749d62fe 100644 --- a/trunk/arch/powerpc/configs/mpc836x_mds_defconfig +++ b/trunk/arch/powerpc/configs/mpc836x_mds_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/mpc8540_ads_defconfig b/trunk/arch/powerpc/configs/mpc8540_ads_defconfig index b953b2c51453..b282c3521dd5 100644 --- a/trunk/arch/powerpc/configs/mpc8540_ads_defconfig +++ b/trunk/arch/powerpc/configs/mpc8540_ads_defconfig @@ -90,9 +90,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -705,7 +704,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8544_ds_defconfig b/trunk/arch/powerpc/configs/mpc8544_ds_defconfig index 9a3e08bcd188..150221f6f723 100644 --- a/trunk/arch/powerpc/configs/mpc8544_ds_defconfig +++ b/trunk/arch/powerpc/configs/mpc8544_ds_defconfig @@ -93,9 +93,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1428,7 +1427,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8560_ads_defconfig b/trunk/arch/powerpc/configs/mpc8560_ads_defconfig index 0211e6b68e1a..3d68c65212cf 100644 --- a/trunk/arch/powerpc/configs/mpc8560_ads_defconfig +++ b/trunk/arch/powerpc/configs/mpc8560_ads_defconfig @@ -94,9 +94,8 @@ CONFIG_SIGNALFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -792,7 +791,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8568mds_defconfig b/trunk/arch/powerpc/configs/mpc8568mds_defconfig index 883d8af9debd..0307fe7b0487 100644 --- a/trunk/arch/powerpc/configs/mpc8568mds_defconfig +++ b/trunk/arch/powerpc/configs/mpc8568mds_defconfig @@ -88,9 +88,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -950,7 +949,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8572_ds_defconfig b/trunk/arch/powerpc/configs/mpc8572_ds_defconfig index 4e85b2e88525..7f1a3e987138 100644 --- a/trunk/arch/powerpc/configs/mpc8572_ds_defconfig +++ b/trunk/arch/powerpc/configs/mpc8572_ds_defconfig @@ -93,9 +93,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1428,7 +1427,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc85xx_cds_defconfig b/trunk/arch/powerpc/configs/mpc85xx_cds_defconfig index a4f33d110542..e6850c619f88 100644 --- a/trunk/arch/powerpc/configs/mpc85xx_cds_defconfig +++ b/trunk/arch/powerpc/configs/mpc85xx_cds_defconfig @@ -90,9 +90,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -833,7 +832,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8610_hpcd_defconfig b/trunk/arch/powerpc/configs/mpc8610_hpcd_defconfig index 0483211f52be..de19b781937f 100644 --- a/trunk/arch/powerpc/configs/mpc8610_hpcd_defconfig +++ b/trunk/arch/powerpc/configs/mpc8610_hpcd_defconfig @@ -88,9 +88,8 @@ CONFIG_SIGNALFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -994,7 +993,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc8641_hpcn_defconfig b/trunk/arch/powerpc/configs/mpc8641_hpcn_defconfig index ed214fcd8abe..b2f389dcaded 100644 --- a/trunk/arch/powerpc/configs/mpc8641_hpcn_defconfig +++ b/trunk/arch/powerpc/configs/mpc8641_hpcn_defconfig @@ -94,9 +94,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1433,7 +1432,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/mpc866_ads_defconfig b/trunk/arch/powerpc/configs/mpc866_ads_defconfig index 070b0a5b9c0d..143a0cd83327 100644 --- a/trunk/arch/powerpc/configs/mpc866_ads_defconfig +++ b/trunk/arch/powerpc/configs/mpc866_ads_defconfig @@ -83,9 +83,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/pasemi_defconfig b/trunk/arch/powerpc/configs/pasemi_defconfig index 1ccf3ed7693e..295207030c60 100644 --- a/trunk/arch/powerpc/configs/pasemi_defconfig +++ b/trunk/arch/powerpc/configs/pasemi_defconfig @@ -90,9 +90,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1589,7 +1588,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/pmac32_defconfig b/trunk/arch/powerpc/configs/pmac32_defconfig index 95b823b60c97..cfc9c6573a3c 100644 --- a/trunk/arch/powerpc/configs/pmac32_defconfig +++ b/trunk/arch/powerpc/configs/pmac32_defconfig @@ -91,9 +91,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1830,7 +1829,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/ppc64_defconfig b/trunk/arch/powerpc/configs/ppc64_defconfig index bb8d4e46f0c5..5f6224a1feb8 100644 --- a/trunk/arch/powerpc/configs/ppc64_defconfig +++ b/trunk/arch/powerpc/configs/ppc64_defconfig @@ -96,9 +96,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -217,10 +216,6 @@ CONFIG_AXON_RAM=m # # Kernel options # -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y # CONFIG_HZ_300 is not set @@ -1755,7 +1750,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/pq2fads_defconfig b/trunk/arch/powerpc/configs/pq2fads_defconfig index 9191f557b044..a51fc39dea4e 100644 --- a/trunk/arch/powerpc/configs/pq2fads_defconfig +++ b/trunk/arch/powerpc/configs/pq2fads_defconfig @@ -86,9 +86,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -931,7 +930,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/prpmc2800_defconfig b/trunk/arch/powerpc/configs/prpmc2800_defconfig index 3e87faf9b5c2..cce3d3da086b 100644 --- a/trunk/arch/powerpc/configs/prpmc2800_defconfig +++ b/trunk/arch/powerpc/configs/prpmc2800_defconfig @@ -89,9 +89,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set diff --git a/trunk/arch/powerpc/configs/ps3_defconfig b/trunk/arch/powerpc/configs/ps3_defconfig index 3566c448bdc0..ca7a197998ee 100644 --- a/trunk/arch/powerpc/configs/ps3_defconfig +++ b/trunk/arch/powerpc/configs/ps3_defconfig @@ -91,9 +91,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -1060,7 +1059,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set CONFIG_DEBUG_SPINLOCK=y diff --git a/trunk/arch/powerpc/configs/pseries_defconfig b/trunk/arch/powerpc/configs/pseries_defconfig index c09eb8cfbe71..0f274e5f6926 100644 --- a/trunk/arch/powerpc/configs/pseries_defconfig +++ b/trunk/arch/powerpc/configs/pseries_defconfig @@ -96,9 +96,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -177,10 +176,6 @@ CONFIG_IBMEBUS=y # # Kernel options # -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y # CONFIG_HZ_300 is not set @@ -1509,7 +1504,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/sequoia_defconfig b/trunk/arch/powerpc/configs/sequoia_defconfig index 45a4ca0e0d7d..bc7f5089a894 100644 --- a/trunk/arch/powerpc/configs/sequoia_defconfig +++ b/trunk/arch/powerpc/configs/sequoia_defconfig @@ -91,9 +91,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -782,7 +781,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/configs/walnut_defconfig b/trunk/arch/powerpc/configs/walnut_defconfig index 7724292cc06d..766bf840c18d 100644 --- a/trunk/arch/powerpc/configs/walnut_defconfig +++ b/trunk/arch/powerpc/configs/walnut_defconfig @@ -87,9 +87,8 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -707,7 +706,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set -# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/trunk/arch/powerpc/kernel/dma_64.c b/trunk/arch/powerpc/kernel/dma_64.c index 9001104b56b0..7b0e754383cf 100644 --- a/trunk/arch/powerpc/kernel/dma_64.c +++ b/trunk/arch/powerpc/kernel/dma_64.c @@ -154,13 +154,12 @@ static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, { } -static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, +static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - struct scatterlist *sg; int i; - for_each_sg(sgl, sg, nents, i) { + for (i = 0; i < nents; i++, sg++) { sg->dma_address = (page_to_phys(sg->page) + sg->offset) | dma_direct_offset; sg->dma_length = sg->length; diff --git a/trunk/arch/powerpc/kernel/entry_64.S b/trunk/arch/powerpc/kernel/entry_64.S index 148a3547c9aa..0ec134034899 100644 --- a/trunk/arch/powerpc/kernel/entry_64.S +++ b/trunk/arch/powerpc/kernel/entry_64.S @@ -408,12 +408,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT) std r7,SLBSHADOW_STACKVSID(r9) /* Save VSID */ std r0,SLBSHADOW_STACKESID(r9) /* Save ESID */ - /* No need to check for CPU_FTR_NO_SLBIE_B here, since when - * we have 1TB segments, the only CPUs known to have the errata - * only support less than 1TB of system memory and we'll never - * actually hit this code path. - */ - slbie r6 slbie r6 /* Workaround POWER5 < DD2.1 issue */ slbmte r7,r0 diff --git a/trunk/arch/powerpc/kernel/ibmebus.c b/trunk/arch/powerpc/kernel/ibmebus.c index 289d7e935918..53bf64623bd8 100644 --- a/trunk/arch/powerpc/kernel/ibmebus.c +++ b/trunk/arch/powerpc/kernel/ibmebus.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -51,13 +50,6 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */ struct bus_type ibmebus_bus_type; -/* These devices will automatically be added to the bus during init */ -static struct of_device_id builtin_matches[] = { - { .compatible = "IBM,lhca" }, - { .compatible = "IBM,lhea" }, - {}, -}; - static void *ibmebus_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, @@ -95,16 +87,15 @@ static void ibmebus_unmap_single(struct device *dev, } static int ibmebus_map_sg(struct device *dev, - struct scatterlist *sgl, + struct scatterlist *sg, int nents, enum dma_data_direction direction) { - struct scatterlist *sg; int i; - for_each_sg(sgl, sg, nents, i) { - sg->dma_address = (dma_addr_t)page_address(sg->page) - + sg->offset; - sg->dma_length = sg->length; + for (i = 0; i < nents; i++) { + sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + + sg[i].offset; + sg[i].dma_length = sg[i].length; } return nents; @@ -132,87 +123,190 @@ static struct dma_mapping_ops ibmebus_dma_ops = { .dma_supported = ibmebus_dma_supported, }; -static int ibmebus_match_path(struct device *dev, void *data) +static int ibmebus_bus_probe(struct device *dev) { - struct device_node *dn = to_of_device(dev)->node; - return (dn->full_name && - (strcasecmp((char *)data, dn->full_name) == 0)); + struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev); + struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); + const struct of_device_id *id; + int error = -ENODEV; + + if (!ibmebusdrv->probe) + return error; + + id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev); + if (id) { + error = ibmebusdrv->probe(ibmebusdev, id); + } + + return error; } -static int ibmebus_match_node(struct device *dev, void *data) +static int ibmebus_bus_remove(struct device *dev) { - return to_of_device(dev)->node == data; + struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev); + struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); + + if (ibmebusdrv->remove) { + return ibmebusdrv->remove(ibmebusdev); + } + + return 0; } -static int ibmebus_create_device(struct device_node *dn) +static void __devinit ibmebus_dev_release(struct device *dev) { - struct of_device *dev; - int ret; + of_node_put(to_ibmebus_dev(dev)->ofdev.node); + kfree(to_ibmebus_dev(dev)); +} - dev = of_device_alloc(dn, NULL, &ibmebus_bus_device); - if (!dev) - return -ENOMEM; +static int __devinit ibmebus_register_device_common( + struct ibmebus_dev *dev, const char *name) +{ + int err = 0; - dev->dev.bus = &ibmebus_bus_type; - dev->dev.archdata.dma_ops = &ibmebus_dma_ops; + dev->ofdev.dev.parent = &ibmebus_bus_device; + dev->ofdev.dev.bus = &ibmebus_bus_type; + dev->ofdev.dev.release = ibmebus_dev_release; - ret = of_device_register(dev); - if (ret) { - of_device_free(dev); - return ret; + dev->ofdev.dev.archdata.of_node = dev->ofdev.node; + dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops; + dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); + + /* An ibmebusdev is based on a of_device. We have to change the + * bus type to use our own DMA mapping operations. + */ + if ((err = of_device_register(&dev->ofdev)) != 0) { + printk(KERN_ERR "%s: failed to register device (%d).\n", + __FUNCTION__, err); + return -ENODEV; } return 0; } -static int ibmebus_create_devices(const struct of_device_id *matches) +static struct ibmebus_dev* __devinit ibmebus_register_device_node( + struct device_node *dn) +{ + struct ibmebus_dev *dev; + int i, len, bus_len; + + dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->ofdev.node = of_node_get(dn); + + len = strlen(dn->full_name + 1); + bus_len = min(len, BUS_ID_SIZE - 1); + memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1 + + (len - bus_len), bus_len); + for (i = 0; i < bus_len; i++) + if (dev->ofdev.dev.bus_id[i] == '/') + dev->ofdev.dev.bus_id[i] = '_'; + + /* Register with generic device framework. */ + if (ibmebus_register_device_common(dev, dn->name) != 0) { + kfree(dev); + return ERR_PTR(-ENODEV); + } + + return dev; +} + +static void ibmebus_probe_of_nodes(char* name) +{ + struct device_node *dn = NULL; + + while ((dn = of_find_node_by_name(dn, name))) { + if (IS_ERR(ibmebus_register_device_node(dn))) { + of_node_put(dn); + return; + } + } + + of_node_put(dn); + + return; +} + +static void ibmebus_add_devices_by_id(struct of_device_id *idt) +{ + while (strlen(idt->name) > 0) { + ibmebus_probe_of_nodes(idt->name); + idt++; + } + + return; +} + +static int ibmebus_match_name(struct device *dev, void *data) { - struct device_node *root, *child; - int ret = 0; + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name; + + name = of_get_property(ebus_dev->ofdev.node, "name", NULL); - root = of_find_node_by_path("/"); + if (name && (strcmp(data, name) == 0)) + return 1; - for (child = NULL; (child = of_get_next_child(root, child)); ) { - if (!of_match_node(matches, child)) - continue; + return 0; +} - if (bus_find_device(&ibmebus_bus_type, NULL, child, - ibmebus_match_node)) - continue; +static int ibmebus_unregister_device(struct device *dev) +{ + of_device_unregister(to_of_device(dev)); - ret = ibmebus_create_device(child); - if (ret) { - printk(KERN_ERR "%s: failed to create device (%i)", - __FUNCTION__, ret); - of_node_put(child); - break; + return 0; +} + +static void ibmebus_remove_devices_by_id(struct of_device_id *idt) +{ + struct device *dev; + + while (strlen(idt->name) > 0) { + while ((dev = bus_find_device(&ibmebus_bus_type, NULL, + (void*)idt->name, + ibmebus_match_name))) { + ibmebus_unregister_device(dev); } + idt++; } - of_node_put(root); - return ret; + return; } -int ibmebus_register_driver(struct of_platform_driver *drv) +int ibmebus_register_driver(struct ibmebus_driver *drv) { - /* If the driver uses devices that ibmebus doesn't know, add them */ - ibmebus_create_devices(drv->match_table); + int err = 0; drv->driver.name = drv->name; drv->driver.bus = &ibmebus_bus_type; + drv->driver.probe = ibmebus_bus_probe; + drv->driver.remove = ibmebus_bus_remove; - return driver_register(&drv->driver); + if ((err = driver_register(&drv->driver) != 0)) + return err; + + /* remove all supported devices first, in case someone + * probed them manually before registering the driver */ + ibmebus_remove_devices_by_id(drv->id_table); + ibmebus_add_devices_by_id(drv->id_table); + + return 0; } EXPORT_SYMBOL(ibmebus_register_driver); -void ibmebus_unregister_driver(struct of_platform_driver *drv) +void ibmebus_unregister_driver(struct ibmebus_driver *drv) { driver_unregister(&drv->driver); + ibmebus_remove_devices_by_id(drv->id_table); } EXPORT_SYMBOL(ibmebus_unregister_driver); -int ibmebus_request_irq(u32 ist, irq_handler_t handler, - unsigned long irq_flags, const char *devname, +int ibmebus_request_irq(struct ibmebus_dev *dev, + u32 ist, + irq_handler_t handler, + unsigned long irq_flags, const char * devname, void *dev_id) { unsigned int irq = irq_create_mapping(NULL, ist); @@ -220,11 +314,12 @@ int ibmebus_request_irq(u32 ist, irq_handler_t handler, if (irq == NO_IRQ) return -EINVAL; - return request_irq(irq, handler, irq_flags, devname, dev_id); + return request_irq(irq, handler, + irq_flags, devname, dev_id); } EXPORT_SYMBOL(ibmebus_request_irq); -void ibmebus_free_irq(u32 ist, void *dev_id) +void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { unsigned int irq = irq_find_mapping(NULL, ist); @@ -232,10 +327,29 @@ void ibmebus_free_irq(u32 ist, void *dev_id) } EXPORT_SYMBOL(ibmebus_free_irq); +static int ibmebus_bus_match(struct device *dev, struct device_driver *drv) +{ + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv); + const struct of_device_id *ids = ebus_drv->id_table; + const struct of_device_id *found_id; + + if (!ids) + return 0; + + found_id = of_match_device(ids, &ebus_dev->ofdev); + if (found_id) + return 1; + + return 0; +} + static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", to_of_device(dev)->node->name); + struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL); + return sprintf(buf, "%s\n", name); } static struct device_attribute ibmebus_dev_attrs[] = { @@ -243,6 +357,18 @@ static struct device_attribute ibmebus_dev_attrs[] = { __ATTR_NULL }; +static int ibmebus_match_path(struct device *dev, void *data) +{ + int rc; + struct device_node *dn = + of_node_get(to_ibmebus_dev(dev)->ofdev.node); + + rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0)); + + of_node_put(dn); + return rc; +} + static char *ibmebus_chomp(const char *in, size_t count) { char *out = kmalloc(count + 1, GFP_KERNEL); @@ -262,8 +388,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, const char *buf, size_t count) { struct device_node *dn = NULL; + struct ibmebus_dev *dev; char *path; - ssize_t rc = 0; + ssize_t rc; path = ibmebus_chomp(buf, count); if (!path) @@ -278,8 +405,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, } if ((dn = of_find_node_by_path(path))) { - rc = ibmebus_create_device(dn); + dev = ibmebus_register_device_node(dn); of_node_put(dn); + rc = IS_ERR(dev) ? PTR_ERR(dev) : count; } else { printk(KERN_WARNING "%s: no such device node: %s\n", __FUNCTION__, path); @@ -288,9 +416,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, out: kfree(path); - if (rc) - return rc; - return count; + return rc; } static ssize_t ibmebus_store_remove(struct bus_type *bus, @@ -305,7 +431,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus, if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, ibmebus_match_path))) { - of_device_unregister(to_of_device(dev)); + ibmebus_unregister_device(dev); kfree(path); return count; @@ -325,7 +451,8 @@ static struct bus_attribute ibmebus_bus_attrs[] = { }; struct bus_type ibmebus_bus_type = { - .uevent = of_device_uevent, + .name = "ibmebus", + .match = ibmebus_bus_match, .dev_attrs = ibmebus_dev_attrs, .bus_attrs = ibmebus_bus_attrs }; @@ -337,9 +464,9 @@ static int __init ibmebus_bus_init(void) printk(KERN_INFO "IBM eBus Device Driver\n"); - err = of_bus_type_init(&ibmebus_bus_type, "ibmebus"); + err = bus_register(&ibmebus_bus_type); if (err) { - printk(KERN_ERR "%s: failed to register IBM eBus.\n", + printk(KERN_ERR ":%s: failed to register IBM eBus.\n", __FUNCTION__); return err; } @@ -353,13 +480,6 @@ static int __init ibmebus_bus_init(void) return err; } - err = ibmebus_create_devices(builtin_matches); - if (err) { - device_unregister(&ibmebus_bus_device); - bus_unregister(&ibmebus_bus_type); - return err; - } - return 0; } -postcore_initcall(ibmebus_bus_init); +__initcall(ibmebus_bus_init); diff --git a/trunk/arch/powerpc/kernel/iommu.c b/trunk/arch/powerpc/kernel/iommu.c index 306a6f75b6c5..e4ec6eee81a8 100644 --- a/trunk/arch/powerpc/kernel/iommu.c +++ b/trunk/arch/powerpc/kernel/iommu.c @@ -277,7 +277,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, dma_addr_t dma_next = 0, dma_addr; unsigned long flags; struct scatterlist *s, *outs, *segstart; - int outcount, incount, i; + int outcount, incount; unsigned long handle; BUG_ON(direction == DMA_NONE); @@ -297,7 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, spin_lock_irqsave(&(tbl->it_lock), flags); - for_each_sg(sglist, s, nelems, i) { + for (s = outs; nelems; nelems--, s++) { unsigned long vaddr, npages, entry, slen; slen = s->length; @@ -341,8 +341,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, if (novmerge || (dma_addr != dma_next)) { /* Can't merge: create a new segment */ segstart = s; - outcount++; - outs = sg_next(outs); + outcount++; outs++; DBG(" can't merge, new segment.\n"); } else { outs->dma_length += s->length; @@ -375,7 +374,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, * next entry of the sglist if we didn't fill the list completely */ if (outcount < incount) { - outs = sg_next(outs); + outs++; outs->dma_address = DMA_ERROR_CODE; outs->dma_length = 0; } @@ -386,7 +385,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, return outcount; failure: - for_each_sg(sglist, s, nelems, i) { + for (s = &sglist[0]; s <= outs; s++) { if (s->dma_length != 0) { unsigned long vaddr, npages; @@ -396,8 +395,6 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, s->dma_address = DMA_ERROR_CODE; s->dma_length = 0; } - if (s == outs) - break; } spin_unlock_irqrestore(&(tbl->it_lock), flags); return 0; @@ -407,7 +404,6 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - struct scatterlist *sg; unsigned long flags; BUG_ON(direction == DMA_NONE); @@ -417,16 +413,15 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, spin_lock_irqsave(&(tbl->it_lock), flags); - sg = sglist; while (nelems--) { unsigned int npages; - dma_addr_t dma_handle = sg->dma_address; + dma_addr_t dma_handle = sglist->dma_address; - if (sg->dma_length == 0) + if (sglist->dma_length == 0) break; - npages = iommu_num_pages(dma_handle, sg->dma_length); + npages = iommu_num_pages(dma_handle,sglist->dma_length); __iommu_free(tbl, dma_handle, npages); - sg = sg_next(sg); + sglist++; } /* Flush/invalidate TLBs if necessary. As for iommu_free(), we diff --git a/trunk/arch/powerpc/kernel/kprobes.c b/trunk/arch/powerpc/kernel/kprobes.c index 5338e4855712..440f5a87271f 100644 --- a/trunk/arch/powerpc/kernel/kprobes.c +++ b/trunk/arch/powerpc/kernel/kprobes.c @@ -38,8 +38,6 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - int __kprobes arch_prepare_kprobe(struct kprobe *p) { int ret = 0; diff --git a/trunk/arch/powerpc/kernel/of_device.c b/trunk/arch/powerpc/kernel/of_device.c index 3388ad619996..8f3db32fac8b 100644 --- a/trunk/arch/powerpc/kernel/of_device.c +++ b/trunk/arch/powerpc/kernel/of_device.c @@ -7,88 +7,8 @@ #include #include -#include #include -static void of_device_make_bus_id(struct of_device *dev) -{ - static atomic_t bus_no_reg_magic; - struct device_node *node = dev->node; - char *name = dev->dev.bus_id; - const u32 *reg; - u64 addr; - int magic; - - /* - * If it's a DCR based device, use 'd' for native DCRs - * and 'D' for MMIO DCRs. - */ -#ifdef CONFIG_PPC_DCR - reg = of_get_property(node, "dcr-reg", NULL); - if (reg) { -#ifdef CONFIG_PPC_DCR_NATIVE - snprintf(name, BUS_ID_SIZE, "d%x.%s", - *reg, node->name); -#else /* CONFIG_PPC_DCR_NATIVE */ - addr = of_translate_dcr_address(node, *reg, NULL); - if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "D%llx.%s", (unsigned long long)addr, - node->name); - return; - } -#endif /* !CONFIG_PPC_DCR_NATIVE */ - } -#endif /* CONFIG_PPC_DCR */ - - /* - * For MMIO, get the physical address - */ - reg = of_get_property(node, "reg", NULL); - if (reg) { - addr = of_translate_address(node, reg); - if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "%llx.%s", (unsigned long long)addr, - node->name); - return; - } - } - - /* - * No BusID, use the node name and add a globally incremented - * counter (and pray...) - */ - magic = atomic_add_return(1, &bus_no_reg_magic); - snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); -} - -struct of_device *of_device_alloc(struct device_node *np, - const char *bus_id, - struct device *parent) -{ - struct of_device *dev; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - - dev->node = of_node_get(np); - dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = parent; - dev->dev.release = of_release_dev; - dev->dev.archdata.of_node = np; - dev->dev.archdata.numa_node = of_node_to_nid(np); - - if (bus_id) - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); - else - of_device_make_bus_id(dev); - - return dev; -} -EXPORT_SYMBOL(of_device_alloc); - ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len) { diff --git a/trunk/arch/powerpc/kernel/of_platform.c b/trunk/arch/powerpc/kernel/of_platform.c index aeaa20268ce2..eca8ccc3fa12 100644 --- a/trunk/arch/powerpc/kernel/of_platform.c +++ b/trunk/arch/powerpc/kernel/of_platform.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,8 @@ static struct of_device_id of_default_bus_ids[] = { {}, }; +static atomic_t bus_no_reg_magic; + struct bus_type of_platform_bus_type = { .uevent = of_device_uevent, }; @@ -84,26 +87,89 @@ void of_unregister_platform_driver(struct of_platform_driver *drv) } EXPORT_SYMBOL(of_unregister_platform_driver); +static void of_platform_make_bus_id(struct of_device *dev) +{ + struct device_node *node = dev->node; + char *name = dev->dev.bus_id; + const u32 *reg; + u64 addr; + int magic; + + /* + * If it's a DCR based device, use 'd' for native DCRs + * and 'D' for MMIO DCRs. + */ +#ifdef CONFIG_PPC_DCR + reg = of_get_property(node, "dcr-reg", NULL); + if (reg) { +#ifdef CONFIG_PPC_DCR_NATIVE + snprintf(name, BUS_ID_SIZE, "d%x.%s", + *reg, node->name); +#else /* CONFIG_PPC_DCR_NATIVE */ + addr = of_translate_dcr_address(node, *reg, NULL); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "D%llx.%s", (unsigned long long)addr, + node->name); + return; + } +#endif /* !CONFIG_PPC_DCR_NATIVE */ + } +#endif /* CONFIG_PPC_DCR */ + + /* + * For MMIO, get the physical address + */ + reg = of_get_property(node, "reg", NULL); + if (reg) { + addr = of_translate_address(node, reg); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "%llx.%s", (unsigned long long)addr, + node->name); + return; + } + } + + /* + * No BusID, use the node name and add a globally incremented + * counter (and pray...) + */ + magic = atomic_add_return(1, &bus_no_reg_magic); + snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); +} + struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent) { struct of_device *dev; - dev = of_device_alloc(np, bus_id, parent); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; + dev->node = of_node_get(np); dev->dma_mask = 0xffffffffUL; + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; + dev->dev.release = of_release_dev; + dev->dev.archdata.of_node = np; + dev->dev.archdata.numa_node = of_node_to_nid(np); /* We do not fill the DMA ops for platform devices by default. * This is currently the responsibility of the platform code * to do such, possibly using a device notifier */ + if (bus_id) + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + else + of_platform_make_bus_id(dev); + if (of_device_register(dev) != 0) { - of_device_free(dev); + kfree(dev); return NULL; } diff --git a/trunk/arch/powerpc/kernel/ptrace.c b/trunk/arch/powerpc/kernel/ptrace.c index 3e17d154d0d4..cf7732cdd6c7 100644 --- a/trunk/arch/powerpc/kernel/ptrace.c +++ b/trunk/arch/powerpc/kernel/ptrace.c @@ -505,6 +505,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = ptrace_set_debugreg(child, addr, data); break; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + #ifdef CONFIG_PPC64 case PTRACE_GETREGS64: #endif diff --git a/trunk/arch/powerpc/kernel/setup-common.c b/trunk/arch/powerpc/kernel/setup-common.c index 2de00f870edc..36c90ba2d312 100644 --- a/trunk/arch/powerpc/kernel/setup-common.c +++ b/trunk/arch/powerpc/kernel/setup-common.c @@ -413,28 +413,16 @@ void __init smp_setup_cpu_maps(void) of_node_put(dn); } - vdso_data->processorCount = num_present_cpus(); -#endif /* CONFIG_PPC64 */ -} - -/* - * Being that cpu_sibling_map is now a per_cpu array, then it cannot - * be initialized until the per_cpu areas have been created. This - * function is now called from setup_per_cpu_areas(). - */ -void __init smp_setup_cpu_sibling_map(void) -{ -#if defined(CONFIG_PPC64) - int cpu; - /* * Do the sibling map; assume only two threads per processor. */ for_each_possible_cpu(cpu) { - cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, cpu_sibling_map[cpu]); if (cpu_has_feature(CPU_FTR_SMT)) - cpu_set(cpu ^ 0x1, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); } + + vdso_data->processorCount = num_present_cpus(); #endif /* CONFIG_PPC64 */ } #endif /* CONFIG_SMP */ diff --git a/trunk/arch/powerpc/kernel/setup_64.c b/trunk/arch/powerpc/kernel/setup_64.c index ede77dbbd4df..008ab6823b02 100644 --- a/trunk/arch/powerpc/kernel/setup_64.c +++ b/trunk/arch/powerpc/kernel/setup_64.c @@ -426,14 +426,11 @@ void __init setup_system(void) printk("-----------------------------------------------------\n"); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); - if (ppc64_caches.dline_size != 0x80) - printk("ppc64_caches.dcache_line_size = 0x%x\n", - ppc64_caches.dline_size); - if (ppc64_caches.iline_size != 0x80) - printk("ppc64_caches.icache_line_size = 0x%x\n", - ppc64_caches.iline_size); - if (htab_address) - printk("htab_address = 0x%p\n", htab_address); + printk("ppc64_caches.dcache_line_size = 0x%x\n", + ppc64_caches.dline_size); + printk("ppc64_caches.icache_line_size = 0x%x\n", + ppc64_caches.iline_size); + printk("htab_address = 0x%p\n", htab_address); printk("htab_hash_mask = 0x%lx\n", htab_hash_mask); #if PHYSICAL_START > 0 printk("physical_start = 0x%x\n", PHYSICAL_START); @@ -600,9 +597,6 @@ void __init setup_per_cpu_areas(void) paca[i].data_offset = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); } - - /* Now that per_cpu is setup, initialize cpu_sibling_map */ - smp_setup_cpu_sibling_map(); } #endif diff --git a/trunk/arch/powerpc/kernel/smp.c b/trunk/arch/powerpc/kernel/smp.c index 338950aeb6f6..d30f08fa0297 100644 --- a/trunk/arch/powerpc/kernel/smp.c +++ b/trunk/arch/powerpc/kernel/smp.c @@ -61,11 +61,11 @@ struct thread_info *secondary_ti; cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; -DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; +cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); -EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); +EXPORT_SYMBOL(cpu_sibling_map); /* SMP operations for this machine */ struct smp_ops_t *smp_ops; diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index 863a5d6d9b18..9368da371f36 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -829,7 +829,7 @@ static void register_decrementer_clockevent(int cpu) *dec = decrementer_clockevent; dec->cpumask = cpumask_of_cpu(cpu); - printk(KERN_INFO "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", + printk(KERN_ERR "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", dec->name, dec->mult, dec->shift, cpu); clockevents_register_device(dec); diff --git a/trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S b/trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S index 9352ab5200e5..26e138c4ce17 100644 --- a/trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S @@ -1,147 +1,130 @@ + /* * This is the infamous ld script for the 32 bits vdso * library */ #include +/* Default link addresses for the vDSOs */ OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") OUTPUT_ARCH(powerpc:common) ENTRY(_start) SECTIONS { - . = VDSO32_LBASE + SIZEOF_HEADERS; - - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .note : { *(.note.*) } :text :note - - . = ALIGN(16); - .text : { - *(.text .stub .text.* .gnu.linkonce.t.*) - } - PROVIDE(__etext = .); - PROVIDE(_etext = .); - PROVIDE(etext = .); - - . = ALIGN(8); - __ftr_fixup : { *(__ftr_fixup) } + . = VDSO32_LBASE + SIZEOF_HEADERS; + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + . = ALIGN (16); + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } #ifdef CONFIG_PPC64 - . = ALIGN(8); - __fw_ftr_fixup : { *(__fw_ftr_fixup) } + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } #endif - /* - * Other stuff is appended to the text segment: - */ - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .gcc_except_table : { *(.gcc_except_table) } - .fixup : { *(.fixup) } - - .dynamic : { *(.dynamic) } :text :dynamic - .got : { *(.got) } - .plt : { *(.plt) } - - _end = .; - __end = .; - PROVIDE(end = .); - - /* - * Stabs debugging sections are here too. - */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - /* - * DWARF debug sections. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. - */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - - /DISCARD/ : { - *(.note.GNU-stack) - *(.data .data.* .gnu.linkonce.d.* .sdata*) - *(.bss .sbss .dynbss .dynsbss) - } + /* Other stuff is appended to the text segment: */ + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .gcc_except_table : { *(.gcc_except_table) } + .fixup : { *(.fixup) } + + .dynamic : { *(.dynamic) } :text :dynamic + .got : { *(.got) } + .plt : { *(.plt) } + + _end = .; + __end = .; + PROVIDE (end = .); + + + /* Stabs debugging sections are here too + */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { *(.note.GNU-stack) } + /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.* .sdata*) } + /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) } } -/* - * Very old versions of ld do not recognize this name token; use the constant. - */ -#define PT_GNU_EH_FRAME 0x6474e550 -/* - * We must supply the ELF program headers explicitly to get just one - * PT_LOAD segment, and set the flags explicitly to make segments read-only. - */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - note PT_NOTE FLAGS(4); /* PF_R */ - eh_frame_hdr PT_GNU_EH_FRAME; + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + note PT_NOTE FLAGS(4); /* PF_R */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ } + /* * This controls what symbols we export from the DSO. */ VERSION { - VDSO_VERSION_STRING { - global: - /* - * Has to be there for the kernel to find - */ - __kernel_datapage_offset; - - __kernel_get_syscall_map; - __kernel_gettimeofday; - __kernel_clock_gettime; - __kernel_clock_getres; - __kernel_get_tbfreq; - __kernel_sync_dicache; - __kernel_sync_dicache_p5; - __kernel_sigtramp32; - __kernel_sigtramp_rt32; - - local: *; - }; + VDSO_VERSION_STRING { + global: + __kernel_datapage_offset; /* Has to be there for the kernel to find */ + __kernel_get_syscall_map; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + __kernel_get_tbfreq; + __kernel_sync_dicache; + __kernel_sync_dicache_p5; + __kernel_sigtramp32; + __kernel_sigtramp_rt32; + local: *; + }; } diff --git a/trunk/arch/powerpc/kernel/vdso64/sigtramp.S b/trunk/arch/powerpc/kernel/vdso64/sigtramp.S index 59eb59bb4082..17a83fa6dc52 100644 --- a/trunk/arch/powerpc/kernel/vdso64/sigtramp.S +++ b/trunk/arch/powerpc/kernel/vdso64/sigtramp.S @@ -134,16 +134,13 @@ V_FUNCTION_END(__kernel_sigtramp_rt64) 9: /* This is where the pt_regs pointer can be found on the stack. */ -#define PTREGS 128+168+56 +#define PTREGS 128+168+56 /* Size of regs. */ -#define RSIZE 8 - -/* Size of CR reg in DWARF unwind info. */ -#define CRSIZE 4 +#define RSIZE 8 /* This is the offset of the VMX reg pointer. */ -#define VREGS 48*RSIZE+33*8 +#define VREGS 48*RSIZE+33*8 /* Describe where general purpose regs are saved. */ #define EH_FRAME_GEN \ @@ -181,7 +178,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64) rsave (31, 31*RSIZE); \ rsave (67, 32*RSIZE); /* ap, used as temp for nip */ \ rsave (65, 36*RSIZE); /* lr */ \ - rsave (70, 38*RSIZE + (RSIZE - CRSIZE)) /* cr */ + rsave (70, 38*RSIZE) /* cr */ /* Describe where the FP regs are saved. */ #define EH_FRAME_FP \ diff --git a/trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S b/trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S index 932b3fdb34b9..2d70f35d50b5 100644 --- a/trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S @@ -10,114 +10,100 @@ ENTRY(_start) SECTIONS { - . = VDSO64_LBASE + SIZEOF_HEADERS; - - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .note : { *(.note.*) } :text :note - - . = ALIGN(16); - .text : { - *(.text .stub .text.* .gnu.linkonce.t.*) - *(.sfpr .glink) - } :text - PROVIDE(__etext = .); - PROVIDE(_etext = .); - PROVIDE(etext = .); - - . = ALIGN(8); - __ftr_fixup : { *(__ftr_fixup) } - - . = ALIGN(8); - __fw_ftr_fixup : { *(__fw_ftr_fixup) } - - /* - * Other stuff is appended to the text segment: - */ - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .gcc_except_table : { *(.gcc_except_table) } - - .opd ALIGN(8) : { KEEP (*(.opd)) } - .got ALIGN(8) : { *(.got .toc) } - .rela.dyn ALIGN(8) : { *(.rela.dyn) } - - .dynamic : { *(.dynamic) } :text :dynamic - - _end = .; - PROVIDE(end = .); - - /* - * Stabs debugging sections are here too. - */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - /* - * DWARF debug sections. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. - */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - - /DISCARD/ : { - *(.note.GNU-stack) - *(.branch_lt) - *(.data .data.* .gnu.linkonce.d.* .sdata*) - *(.bss .sbss .dynbss .dynsbss) - } + . = VDSO64_LBASE + SIZEOF_HEADERS; + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + . = ALIGN (16); + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.sfpr .glink) + } :text + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } + + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } + + /* Other stuff is appended to the text segment: */ + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .gcc_except_table : { *(.gcc_except_table) } + + .opd ALIGN(8) : { KEEP (*(.opd)) } + .got ALIGN(8) : { *(.got .toc) } + .rela.dyn ALIGN(8) : { *(.rela.dyn) } + + .dynamic : { *(.dynamic) } :text :dynamic + + _end = .; + PROVIDE (end = .); + + /* Stabs debugging sections are here too + */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sectio/ns. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { *(.note.GNU-stack) } + /DISCARD/ : { *(.branch_lt) } + /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.*) } + /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) } } -/* - * Very old versions of ld do not recognize this name token; use the constant. - */ -#define PT_GNU_EH_FRAME 0x6474e550 - -/* - * We must supply the ELF program headers explicitly to get just one - * PT_LOAD segment, and set the flags explicitly to make segments read-only. - */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - note PT_NOTE FLAGS(4); /* PF_R */ - eh_frame_hdr PT_GNU_EH_FRAME; + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + note PT_NOTE FLAGS(4); /* PF_R */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ } /* @@ -125,22 +111,17 @@ PHDRS */ VERSION { - VDSO_VERSION_STRING { - global: - /* - * Has to be there for the kernel to find - */ - __kernel_datapage_offset; - - __kernel_get_syscall_map; - __kernel_gettimeofday; - __kernel_clock_gettime; - __kernel_clock_getres; - __kernel_get_tbfreq; - __kernel_sync_dicache; - __kernel_sync_dicache_p5; - __kernel_sigtramp_rt64; - - local: *; - }; + VDSO_VERSION_STRING { + global: + __kernel_datapage_offset; /* Has to be there for the kernel to find */ + __kernel_get_syscall_map; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + __kernel_get_tbfreq; + __kernel_sync_dicache; + __kernel_sync_dicache_p5; + __kernel_sigtramp_rt64; + local: *; + }; } diff --git a/trunk/arch/powerpc/lib/rheap.c b/trunk/arch/powerpc/lib/rheap.c index ada5b42dd231..22c3b4f53de7 100644 --- a/trunk/arch/powerpc/lib/rheap.c +++ b/trunk/arch/powerpc/lib/rheap.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -275,6 +276,7 @@ rh_info_t *rh_create(unsigned int alignment) return info; } +EXPORT_SYMBOL_GPL(rh_create); /* * Destroy a dynamically created remote heap. Deallocate only if the areas @@ -288,6 +290,7 @@ void rh_destroy(rh_info_t * info) if ((info->flags & RHIF_STATIC_INFO) == 0) kfree(info); } +EXPORT_SYMBOL_GPL(rh_destroy); /* * Initialize in place a remote heap info block. This is needed to support @@ -320,6 +323,7 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks, for (i = 0, blk = block; i < max_blocks; i++, blk++) list_add(&blk->list, &info->empty_list); } +EXPORT_SYMBOL_GPL(rh_init); /* Attach a free memory region, coalesces regions if adjuscent */ int rh_attach_region(rh_info_t * info, unsigned long start, int size) @@ -360,6 +364,7 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size) return 0; } +EXPORT_SYMBOL_GPL(rh_attach_region); /* Detatch given address range, splits free block if needed. */ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) @@ -428,6 +433,7 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) return s; } +EXPORT_SYMBOL_GPL(rh_detach_region); /* Allocate a block of memory at the specified alignment. The value returned * is an offset into the buffer initialized by rh_init(), or a negative number @@ -502,6 +508,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch return start; } +EXPORT_SYMBOL_GPL(rh_alloc_align); /* Allocate a block of memory at the default alignment. The value returned is * an offset into the buffer initialized by rh_init(), or a negative number if @@ -511,6 +518,7 @@ unsigned long rh_alloc(rh_info_t * info, int size, const char *owner) { return rh_alloc_align(info, size, info->alignment, owner); } +EXPORT_SYMBOL_GPL(rh_alloc); /* Allocate a block of memory at the given offset, rounded up to the default * alignment. The value returned is an offset into the buffer initialized by @@ -594,6 +602,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co return start; } +EXPORT_SYMBOL_GPL(rh_alloc_fixed); /* Deallocate the memory previously allocated by one of the rh_alloc functions. * The return value is the size of the deallocated block, or a negative number @@ -626,6 +635,7 @@ int rh_free(rh_info_t * info, unsigned long start) return size; } +EXPORT_SYMBOL_GPL(rh_free); int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) { @@ -663,6 +673,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) return nr; } +EXPORT_SYMBOL_GPL(rh_get_stats); int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) { @@ -687,6 +698,7 @@ int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) return size; } +EXPORT_SYMBOL_GPL(rh_set_owner); void rh_dump(rh_info_t * info) { @@ -722,6 +734,7 @@ void rh_dump(rh_info_t * info) st[i].size, st[i].owner != NULL ? st[i].owner : ""); printk(KERN_INFO "\n"); } +EXPORT_SYMBOL_GPL(rh_dump); void rh_dump_blk(rh_info_t * info, rh_block_t * blk) { @@ -729,3 +742,5 @@ void rh_dump_blk(rh_info_t * info, rh_block_t * blk) "blk @0x%p: 0x%lx-0x%lx (%u)\n", blk, blk->start, blk->start + blk->size, blk->size); } +EXPORT_SYMBOL_GPL(rh_dump_blk); + diff --git a/trunk/arch/powerpc/math-emu/math.c b/trunk/arch/powerpc/math-emu/math.c index 381306bb1590..69058b2873de 100644 --- a/trunk/arch/powerpc/math-emu/math.c +++ b/trunk/arch/powerpc/math-emu/math.c @@ -407,16 +407,11 @@ do_mathemu(struct pt_regs *regs) case XE: idx = (insn >> 16) & 0x1f; - op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; - if (!idx) { - if (((insn >> 1) & 0x3ff) == STFIWX) - op1 = (void *)(regs->gpr[(insn >> 11) & 0x1f]); - else - goto illegal; - } else { - op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); - } + if (!idx) + goto illegal; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); break; case XEU: diff --git a/trunk/arch/powerpc/mm/hash_utils_64.c b/trunk/arch/powerpc/mm/hash_utils_64.c index c78dc912411f..611ad084b7e7 100644 --- a/trunk/arch/powerpc/mm/hash_utils_64.c +++ b/trunk/arch/powerpc/mm/hash_utils_64.c @@ -209,10 +209,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, if (prop[0] == 40) { DBG("1T segment support detected\n"); cur_cpu_spec->cpu_features |= CPU_FTR_1T_SEGMENT; - return 1; } + return 1; } - cur_cpu_spec->cpu_features &= ~CPU_FTR_NO_SLBIE_B; return 0; } diff --git a/trunk/arch/powerpc/mm/init_64.c b/trunk/arch/powerpc/mm/init_64.c index 6720b1c93f18..fa90f6561b9f 100644 --- a/trunk/arch/powerpc/mm/init_64.c +++ b/trunk/arch/powerpc/mm/init_64.c @@ -183,71 +183,3 @@ void pgtable_cache_init(void) zero_ctor); } } - -#ifdef CONFIG_SPARSEMEM_VMEMMAP -/* - * Given an address within the vmemmap, determine the pfn of the page that - * represents the start of the section it is within. Note that we have to - * do this by hand as the proffered address may not be correctly aligned. - * Subtraction of non-aligned pointers produces undefined results. - */ -unsigned long __meminit vmemmap_section_start(unsigned long page) -{ - unsigned long offset = page - ((unsigned long)(vmemmap)); - - /* Return the pfn of the start of the section. */ - return (offset / sizeof(struct page)) & PAGE_SECTION_MASK; -} - -/* - * Check if this vmemmap page is already initialised. If any section - * which overlaps this vmemmap page is initialised then this page is - * initialised already. - */ -int __meminit vmemmap_populated(unsigned long start, int page_size) -{ - unsigned long end = start + page_size; - - for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) - if (pfn_valid(vmemmap_section_start(start))) - return 1; - - return 0; -} - -int __meminit vmemmap_populate(struct page *start_page, - unsigned long nr_pages, int node) -{ - unsigned long mode_rw; - unsigned long start = (unsigned long)start_page; - unsigned long end = (unsigned long)(start_page + nr_pages); - unsigned long page_size = 1 << mmu_psize_defs[mmu_linear_psize].shift; - - mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; - - /* Align to the page size of the linear mapping. */ - start = _ALIGN_DOWN(start, page_size); - - for (; start < end; start += page_size) { - int mapped; - void *p; - - if (vmemmap_populated(start, page_size)) - continue; - - p = vmemmap_alloc_block(page_size, node); - if (!p) - return -ENOMEM; - - printk(KERN_WARNING "vmemmap %08lx allocated at %p, " - "physical %08lx.\n", start, p, __pa(p)); - - mapped = htab_bolt_mapping(start, start + page_size, - __pa(p), mode_rw, mmu_linear_psize, - mmu_kernel_ssize); - BUG_ON(mapped < 0); - } - - return 0; -} -#endif diff --git a/trunk/arch/powerpc/mm/mem.c b/trunk/arch/powerpc/mm/mem.c index 81eb96ec13b2..32dcfc9b0082 100644 --- a/trunk/arch/powerpc/mm/mem.c +++ b/trunk/arch/powerpc/mm/mem.c @@ -129,6 +129,51 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) return __add_pages(zone, start_pfn, nr_pages); } +/* + * First pass at this code will check to determine if the remove + * request is within the RMO. Do not allow removal within the RMO. + */ +int __devinit remove_memory(u64 start, u64 size) +{ + struct zone *zone; + unsigned long start_pfn, end_pfn, nr_pages; + + start_pfn = start >> PAGE_SHIFT; + nr_pages = size >> PAGE_SHIFT; + end_pfn = start_pfn + nr_pages; + + printk("%s(): Attempting to remove memoy in range " + "%lx to %lx\n", __func__, start, start+size); + /* + * check for range within RMO + */ + zone = page_zone(pfn_to_page(start_pfn)); + + printk("%s(): memory will be removed from " + "the %s zone\n", __func__, zone->name); + + /* + * not handling removing memory ranges that + * overlap multiple zones yet + */ + if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages)) + goto overlap; + + /* make sure it is NOT in RMO */ + if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) { + printk("%s(): range to be removed must NOT be in RMO!\n", + __func__); + goto in_rmo; + } + + return __remove_pages(zone, start_pfn, nr_pages); + +overlap: + printk("%s(): memory range to be removed overlaps " + "multiple zones!!!\n", __func__); +in_rmo: + return -1; +} #endif /* CONFIG_MEMORY_HOTPLUG */ void show_mem(void) diff --git a/trunk/arch/powerpc/mm/slb.c b/trunk/arch/powerpc/mm/slb.c index bbd2c512ee05..6c164cec9d2c 100644 --- a/trunk/arch/powerpc/mm/slb.c +++ b/trunk/arch/powerpc/mm/slb.c @@ -157,8 +157,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) unsigned long stack = KSTK_ESP(tsk); unsigned long unmapped_base; - if (!cpu_has_feature(CPU_FTR_NO_SLBIE_B) && - offset <= SLB_CACHE_ENTRIES) { + if (offset <= SLB_CACHE_ENTRIES) { int i; asm volatile("isync" : : : "memory"); for (i = 0; i < offset; i++) { diff --git a/trunk/arch/powerpc/platforms/Kconfig b/trunk/arch/powerpc/platforms/Kconfig index 186397f283bb..cc6013ffc29a 100644 --- a/trunk/arch/powerpc/platforms/Kconfig +++ b/trunk/arch/powerpc/platforms/Kconfig @@ -117,7 +117,7 @@ config RTAS_FLASH config PPC_PMI tristate "Support for PMI" - depends on PPC_IBM_CELL_BLADE + depends PPC_IBM_CELL_BLADE help PMI (Platform Management Interrupt) is a way to communicate with the BMC (Baseboard Mangement Controller). diff --git a/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c b/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c index 13d5a87f13b1..5123e9d4164b 100644 --- a/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -117,7 +117,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = cbe_freqs[cur_pmode].frequency; #ifdef CONFIG_SMP - policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); + policy->cpus = cpu_sibling_map[policy->cpu]; #endif cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); diff --git a/trunk/arch/powerpc/platforms/iseries/htab.c b/trunk/arch/powerpc/platforms/iseries/htab.c index f99c6c4b6985..15a7097e5dd7 100644 --- a/trunk/arch/powerpc/platforms/iseries/htab.c +++ b/trunk/arch/powerpc/platforms/iseries/htab.c @@ -39,9 +39,9 @@ static inline void iSeries_hunlock(unsigned long slot) spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]); } -static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, +long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, - unsigned long vflags, int psize, int ssize) + unsigned long vflags, int psize) { long slot; struct hash_pte lhpte; diff --git a/trunk/arch/powerpc/platforms/iseries/vio.c b/trunk/arch/powerpc/platforms/iseries/vio.c index d6435b03971f..910b00b4703e 100644 --- a/trunk/arch/powerpc/platforms/iseries/vio.c +++ b/trunk/arch/powerpc/platforms/iseries/vio.c @@ -2,7 +2,7 @@ * Legacy iSeries specific vio initialisation * that needs to be built in (not a module). * - * © Copyright 2007 IBM Corporation + * © Copyright 2007 IBM Corporation * Author: Stephen Rothwell * Some parts collected from various other files * diff --git a/trunk/arch/powerpc/platforms/ps3/system-bus.c b/trunk/arch/powerpc/platforms/ps3/system-bus.c index 07e64b48e7fc..190ff4b59a55 100644 --- a/trunk/arch/powerpc/platforms/ps3/system-bus.c +++ b/trunk/arch/powerpc/platforms/ps3/system-bus.c @@ -616,18 +616,17 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, } } -static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, - int nents, enum dma_data_direction direction) +static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) { #if defined(CONFIG_PS3_DYNAMIC_DMA) BUG_ON("do"); return -EPERM; #else struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - struct scatterlist *sg; int i; - for_each_sg(sgl, sg, nents, i) { + for (i = 0; i < nents; i++, sg++) { int result = ps3_dma_map(dev->d_region, page_to_phys(sg->page) + sg->offset, sg->length, &sg->dma_address, 0); diff --git a/trunk/arch/powerpc/sysdev/fsl_pci.c b/trunk/arch/powerpc/sysdev/fsl_pci.c index 33df4c347ca7..af090c93be10 100644 --- a/trunk/arch/powerpc/sysdev/fsl_pci.c +++ b/trunk/arch/powerpc/sysdev/fsl_pci.c @@ -255,7 +255,7 @@ DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_transpare DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_transparent); -DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_transparent); +DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_transparent) DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_transparent); DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_transparent); diff --git a/trunk/arch/ppc/Makefile b/trunk/arch/ppc/Makefile index 95894ef7beaa..eee6264e8a04 100644 --- a/trunk/arch/ppc/Makefile +++ b/trunk/arch/ppc/Makefile @@ -22,22 +22,22 @@ endif LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic # The -Iarch/$(ARCH)/include is temporary while we are merging -KBUILD_CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include -KBUILD_AFLAGS += -Iarch/$(ARCH) -KBUILD_CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ +CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include +AFLAGS += -Iarch/$(ARCH) +CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -mmultiple # No AltiVec instruction when building kernel -KBUILD_CFLAGS += $(call cc-option, -mno-altivec) +CFLAGS += $(call cc-option, -mno-altivec) -CPP = $(CC) -E $(KBUILD_CFLAGS) +CPP = $(CC) -E $(CFLAGS) # Temporary hack until we have migrated to asm-powerpc LINUXINCLUDE += -Iarch/$(ARCH)/include CHECKFLAGS += -D__powerpc__ ifndef CONFIG_FSL_BOOKE -KBUILD_CFLAGS += -mstring +CFLAGS += -mstring endif cpu-as-$(CONFIG_4xx) += -Wa,-m405 @@ -45,8 +45,8 @@ cpu-as-$(CONFIG_6xx) += -Wa,-maltivec cpu-as-$(CONFIG_E500) += -Wa,-me500 cpu-as-$(CONFIG_E200) += -Wa,-me200 -KBUILD_AFLAGS += $(cpu-as-y) -KBUILD_CFLAGS += $(cpu-as-y) +AFLAGS += $(cpu-as-y) +CFLAGS += $(cpu-as-y) # Default to the common case. KBUILD_DEFCONFIG := common_defconfig diff --git a/trunk/arch/ppc/boot/Makefile b/trunk/arch/ppc/boot/Makefile index 487dc66dcc74..b739e25d4728 100644 --- a/trunk/arch/ppc/boot/Makefile +++ b/trunk/arch/ppc/boot/Makefile @@ -13,6 +13,7 @@ # modified by Cort (cort@cs.nmt.edu) # +CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include HOSTCFLAGS += -Iarch/$(ARCH)/boot/include BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd diff --git a/trunk/arch/ppc/mm/fault.c b/trunk/arch/ppc/mm/fault.c index 94913ddcf76e..b98244e277fb 100644 --- a/trunk/arch/ppc/mm/fault.c +++ b/trunk/arch/ppc/mm/fault.c @@ -297,7 +297,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); return SIGKILL; do_sigbus: diff --git a/trunk/arch/s390/Makefile b/trunk/arch/s390/Makefile index f708be367b03..143ed8e154af 100644 --- a/trunk/arch/s390/Makefile +++ b/trunk/arch/s390/Makefile @@ -15,16 +15,16 @@ ifndef CONFIG_64BIT LDFLAGS := -m elf_s390 -KBUILD_CFLAGS += -m31 -KBUILD_AFLAGS += -m31 +CFLAGS += -m31 +AFLAGS += -m31 UTS_MACHINE := s390 STACK_SIZE := 8192 CHECKFLAGS += -D__s390__ -msize-long else LDFLAGS := -m elf64_s390 MODFLAGS += -fpic -D__PIC__ -KBUILD_CFLAGS += -m64 -KBUILD_AFLAGS += -m64 +CFLAGS += -m64 +AFLAGS += -m64 UTS_MACHINE := s390x STACK_SIZE := 16384 CHECKFLAGS += -D__s390__ -D__s390x__ @@ -77,9 +77,9 @@ cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE) endif -KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) -KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare -KBUILD_AFLAGS += $(aflags-y) +CFLAGS += -mbackchain -msoft-float $(cflags-y) +CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare +AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start diff --git a/trunk/arch/s390/kernel/kprobes.c b/trunk/arch/s390/kernel/kprobes.c index c5549a206284..e40373d9fbce 100644 --- a/trunk/arch/s390/kernel/kprobes.c +++ b/trunk/arch/s390/kernel/kprobes.c @@ -33,8 +33,6 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* Make sure the probe isn't going on a difficult instruction */ diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index 1d81bf9488ae..f4503ca27630 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -683,6 +683,11 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); return 0; + case PTRACE_DETACH: + /* detach a process that was attached. */ + return ptrace_detach(child, data); + + /* Do requests that differ for 31/64 bit */ default: #ifdef CONFIG_COMPAT diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index 14c241ccdd4d..4c1ac341ec80 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -218,7 +218,7 @@ static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code, } printk("VM: killing process %s\n", tsk->comm); if (regs->psw.mask & PSW_MASK_PSTATE) - do_group_exit(SIGKILL); + do_exit(SIGKILL); do_no_context(regs, error_code, address); return 0; } diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index 408342b175c8..a0a2083aad3e 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -91,12 +91,12 @@ LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' LDFLAGS += -EB endif -KBUILD_CFLAGS += -pipe $(cflags-y) -KBUILD_AFLAGS += $(cflags-y) +CFLAGS += -pipe $(cflags-y) +AFLAGS += $(cflags-y) head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) core-y += arch/sh/kernel/ arch/sh/mm/ core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/ diff --git a/trunk/arch/sh/boot/compressed/Makefile b/trunk/arch/sh/boot/compressed/Makefile index 906a13f82fe0..013504ae1122 100644 --- a/trunk/arch/sh/boot/compressed/Makefile +++ b/trunk/arch/sh/boot/compressed/Makefile @@ -21,7 +21,7 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ $(CONFIG_MEMORY_START) + \ $(CONFIG_BOOT_LINK_OFFSET)]') -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds diff --git a/trunk/arch/sh/kernel/ptrace.c b/trunk/arch/sh/kernel/ptrace.c index ac725f0aeb72..f64a2d2416d4 100644 --- a/trunk/arch/sh/kernel/ptrace.c +++ b/trunk/arch/sh/kernel/ptrace.c @@ -211,6 +211,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + #ifdef CONFIG_SH_DSP case PTRACE_GETDSPREGS: { unsigned long dp; diff --git a/trunk/arch/sh/kernel/vsyscall/vsyscall.lds.S b/trunk/arch/sh/kernel/vsyscall/vsyscall.lds.S index c9bf2af35d35..b13c3d439fee 100644 --- a/trunk/arch/sh/kernel/vsyscall/vsyscall.lds.S +++ b/trunk/arch/sh/kernel/vsyscall/vsyscall.lds.S @@ -17,52 +17,45 @@ ENTRY(__kernel_vsyscall); SECTIONS { - . = SIZEOF_HEADERS; + . = SIZEOF_HEADERS; - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } - /* - * This linker script is used both with -r and with -shared. - * For the layouts to match, we need to skip more than enough - * space for the dynamic symbol table et al. If this amount - * is insufficient, ld -shared will barf. Just increase it here. - */ - . = 0x400; + /* This linker script is used both with -r and with -shared. + For the layouts to match, we need to skip more than enough + space for the dynamic symbol table et al. If this amount + is insufficient, ld -shared will barf. Just increase it here. */ + . = 0x400; - .text : { *(.text) } :text =0x90909090 - .note : { *(.note.*) } :text :note - .eh_frame_hdr : { *(.eh_frame_hdr ) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .dynamic : { *(.dynamic) } :text :dynamic - .useless : { - *(.got.plt) *(.got) - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - } :text + .text : { *(.text) } :text =0x90909090 + .note : { *(.note.*) } :text :note + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .dynamic : { *(.dynamic) } :text :dynamic + .useless : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + } :text } -/* - * Very old versions of ld do not recognize this name token; use the constant. - */ -#define PT_GNU_EH_FRAME 0x6474e550 - /* * We must supply the ELF program headers explicitly to get just one * PT_LOAD segment, and set the flags explicitly to make segments read-only. */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - note PT_NOTE FLAGS(4); /* PF_R */ - eh_frame_hdr PT_GNU_EH_FRAME; + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ } /* @@ -70,12 +63,12 @@ PHDRS */ VERSION { - LINUX_2.6 { - global: - __kernel_vsyscall; - __kernel_sigreturn; - __kernel_rt_sigreturn; + LINUX_2.6 { + global: + __kernel_vsyscall; + __kernel_sigreturn; + __kernel_rt_sigreturn; - local: *; - }; + local: *; + }; } diff --git a/trunk/arch/sh/mm/fault.c b/trunk/arch/sh/mm/fault.c index 4729668ce5bf..04a39aa7f1f9 100644 --- a/trunk/arch/sh/mm/fault.c +++ b/trunk/arch/sh/mm/fault.c @@ -214,7 +214,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index d5e160da64b2..82b68c789a5f 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -294,6 +294,12 @@ int arch_add_memory(int nid, u64 start, u64 size) } EXPORT_SYMBOL_GPL(arch_add_memory); +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); + #ifdef CONFIG_NUMA int memory_add_physaddr_to_nid(u64 addr) { diff --git a/trunk/arch/sh64/Makefile b/trunk/arch/sh64/Makefile index 8dac7e1a2be6..8290c6380d7d 100644 --- a/trunk/arch/sh64/Makefile +++ b/trunk/arch/sh64/Makefile @@ -26,7 +26,7 @@ LDFLAGS += -EB -mshelf32_linux endif # No requirements for endianess support from AFLAGS, 'as' always run through gcc -KBUILD_CFLAGS += $(cpu-y) +CFLAGS += $(cpu-y) LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \ --defsym phys_stext_shmedia=phys_stext+1 \ @@ -58,7 +58,7 @@ ifneq ($(machine-y),) core-y += arch/sh64/mach-$(machine-y)/ endif -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) libs-y += arch/$(ARCH)/lib/ $(LIBGCC) drivers-$(CONFIG_OPROFILE) += arch/sh64/oprofile/ diff --git a/trunk/arch/sh64/kernel/ptrace.c b/trunk/arch/sh64/kernel/ptrace.c index 8a2d339cf760..df06c6477468 100644 --- a/trunk/arch/sh64/kernel/ptrace.c +++ b/trunk/arch/sh64/kernel/ptrace.c @@ -244,6 +244,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + default: ret = ptrace_request(child, request, addr, data); break; diff --git a/trunk/arch/sh64/mm/fault.c b/trunk/arch/sh64/mm/fault.c index dd81c669c79b..0d069d82141f 100644 --- a/trunk/arch/sh64/mm/fault.c +++ b/trunk/arch/sh64/mm/fault.c @@ -334,7 +334,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/sparc/Makefile b/trunk/arch/sparc/Makefile index fef28e267a52..f33c3817f014 100644 --- a/trunk/arch/sparc/Makefile +++ b/trunk/arch/sparc/Makefile @@ -8,16 +8,16 @@ # # -# Uncomment the first KBUILD_CFLAGS if you are doing kgdb source level +# Uncomment the first CFLAGS if you are doing kgdb source level # debugging of the kernel to get the proper debugging information. AS := $(AS) -32 LDFLAGS := -m elf32_sparc CHECKFLAGS += -D__sparc__ -#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 -KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 -KBUILD_AFLAGS += -m32 +#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 +CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 +AFLAGS := $(AFLAGS) -m32 #LDFLAGS_vmlinux = -N -Ttext 0xf0004000 # Since 2.5.40, the first stage is left not btfix-ed. diff --git a/trunk/arch/sparc/kernel/ioport.c b/trunk/arch/sparc/kernel/ioport.c index 9c3ed88853f3..62182d2d7b0d 100644 --- a/trunk/arch/sparc/kernel/ioport.c +++ b/trunk/arch/sparc/kernel/ioport.c @@ -35,7 +35,6 @@ #include #include /* struct pci_dev */ #include -#include #include #include @@ -718,19 +717,19 @@ void pci_unmap_page(struct pci_dev *hwdev, * Device ownership issues as mentioned above for pci_map_single are * the same here. */ -int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, +int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { - struct scatterlist *sg; int n; BUG_ON(direction == PCI_DMA_NONE); /* IIep is write-through, not flushing. */ - for_each_sg(sgl, sg, nents, n) { + for (n = 0; n < nents; n++) { BUG_ON(page_address(sg->page) == NULL); sg->dvma_address = virt_to_phys(page_address(sg->page)) + sg->offset; sg->dvma_length = sg->length; + sg++; } return nents; } @@ -739,19 +738,19 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, * Again, cpu read rules concerning calls here are the same as for * pci_unmap_single() above. */ -void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, +void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { - struct scatterlist *sg; int n; BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { + for (n = 0; n < nents; n++) { BUG_ON(page_address(sg->page) == NULL); mmu_inval_dma_area( (unsigned long) page_address(sg->page), (sg->length + PAGE_SIZE-1) & PAGE_MASK); + sg++; } } } @@ -790,34 +789,34 @@ void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t * The same as pci_dma_sync_single_* but for a scatter-gather list, * same rules and usage. */ -void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction) +void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { - struct scatterlist *sg; int n; BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { + for (n = 0; n < nents; n++) { BUG_ON(page_address(sg->page) == NULL); mmu_inval_dma_area( (unsigned long) page_address(sg->page), (sg->length + PAGE_SIZE-1) & PAGE_MASK); + sg++; } } } -void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction) +void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { - struct scatterlist *sg; int n; BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { + for (n = 0; n < nents; n++) { BUG_ON(page_address(sg->page) == NULL); mmu_inval_dma_area( (unsigned long) page_address(sg->page), (sg->length + PAGE_SIZE-1) & PAGE_MASK); + sg++; } } } diff --git a/trunk/arch/sparc/mm/fault.c b/trunk/arch/sparc/mm/fault.c index e4d9c8e19df5..50747fe44356 100644 --- a/trunk/arch/sparc/mm/fault.c +++ b/trunk/arch/sparc/mm/fault.c @@ -369,7 +369,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, up_read(&mm->mmap_sem); printk("VM: killing process %s\n", tsk->comm); if (from_user) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/sparc/mm/io-unit.c b/trunk/arch/sparc/mm/io-unit.c index 375b4db63704..7c89893b1fe8 100644 --- a/trunk/arch/sparc/mm/io-unit.c +++ b/trunk/arch/sparc/mm/io-unit.c @@ -11,8 +11,8 @@ #include #include /* pte_offset_map => kmap_atomic */ #include -#include +#include #include #include #include @@ -144,9 +144,8 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { --sz; - sg->dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg->page) + sg->offset, sg->length); - sg->dvma_length = sg->length; - sg = sg_next(sg); + sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); + sg[sz].dvma_length = sg[sz].length; } spin_unlock_irqrestore(&iounit->lock, flags); } @@ -174,12 +173,11 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_ spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { --sz; - len = ((sg->dvma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT; - vaddr = (sg->dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; + len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT; + vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); for (len += vaddr; vaddr < len; vaddr++) clear_bit(vaddr, iounit->bmap); - sg = sg_next(sg); } spin_unlock_irqrestore(&iounit->lock, flags); } diff --git a/trunk/arch/sparc/mm/iommu.c b/trunk/arch/sparc/mm/iommu.c index 283656d9f6ea..52e907af9d29 100644 --- a/trunk/arch/sparc/mm/iommu.c +++ b/trunk/arch/sparc/mm/iommu.c @@ -12,8 +12,8 @@ #include #include #include /* pte_offset_map => kmap_atomic */ -#include +#include #include #include #include @@ -240,7 +240,7 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; - sg = sg_next(sg); + sg++; } } @@ -254,7 +254,7 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; - sg = sg_next(sg); + sg++; } } @@ -285,7 +285,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; - sg = sg_next(sg); + sg++; } } @@ -325,7 +325,7 @@ static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus); sg->dvma_address = 0x21212121; - sg = sg_next(sg); + sg++; } } diff --git a/trunk/arch/sparc/mm/sun4c.c b/trunk/arch/sparc/mm/sun4c.c index ee6708fc4492..005a3e72d4f2 100644 --- a/trunk/arch/sparc/mm/sun4c.c +++ b/trunk/arch/sparc/mm/sun4c.c @@ -17,8 +17,8 @@ #include #include #include -#include +#include #include #include #include @@ -1228,9 +1228,8 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus * { while (sz != 0) { --sz; - sg->dvma_address = (__u32)sun4c_lockarea(page_address(sg->page) + sg->offset, sg->length); - sg->dvma_length = sg->length; - sg = sg_next(sg); + sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); + sg[sz].dvma_length = sg[sz].length; } } @@ -1245,8 +1244,7 @@ static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b { while (sz != 0) { --sz; - sun4c_unlockarea((char *)sg->dvma_address, sg->length); - sg = sg_next(sg); + sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length); } } diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index 2f22fa90461a..33dabf588bdd 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -240,10 +240,10 @@ config ARCH_SELECT_MEMORY_MODEL config ARCH_SPARSEMEM_ENABLE def_bool y - select SPARSEMEM_VMEMMAP_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y + select SPARSEMEM_STATIC source "mm/Kconfig" diff --git a/trunk/arch/sparc64/Makefile b/trunk/arch/sparc64/Makefile index 6c92a42efe76..cad10c5b83d3 100644 --- a/trunk/arch/sparc64/Makefile +++ b/trunk/arch/sparc64/Makefile @@ -39,17 +39,17 @@ AS := $(AS) --undeclared-regs endif ifneq ($(NEW_GCC),y) - KBUILD_CFLAGS += -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ + CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare else - KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ + CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ $(CC_UNDECL) - KBUILD_AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) + AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) endif ifeq ($(CONFIG_MCOUNT),y) - KBUILD_CFLAGS += -pg + CFLAGS := $(CFLAGS) -pg endif head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o diff --git a/trunk/arch/sparc64/kernel/iommu.c b/trunk/arch/sparc64/kernel/iommu.c index db3ffcf7a120..b35a62167e9c 100644 --- a/trunk/arch/sparc64/kernel/iommu.c +++ b/trunk/arch/sparc64/kernel/iommu.c @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef CONFIG_PCI #include @@ -481,7 +480,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, unsigned long iopte_protection) { struct scatterlist *dma_sg = sg; - struct scatterlist *sg_end = sg_last(sg, nelems); + struct scatterlist *sg_end = sg + nelems; int i; for (i = 0; i < nused; i++) { @@ -516,7 +515,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } - sg = sg_next(sg); + sg++; } pteval = iopte_protection | (pteval & IOPTE_PAGE); @@ -529,24 +528,24 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, } pteval = (pteval & IOPTE_PAGE) + len; - sg = sg_next(sg); + sg++; /* Skip over any tail mappings we've fully mapped, * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while (sg != sg_end && + while (sg < sg_end && (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && (pteval == SG_ENT_PHYS_ADDRESS(sg)) && ((pteval ^ (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; - sg = sg_next(sg); + sg++; } if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); - dma_sg = sg_next(dma_sg); + dma_sg++; } } @@ -607,7 +606,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, sgtmp = sglist; while (used && sgtmp->dma_length) { sgtmp->dma_address += dma_base; - sgtmp = sg_next(sgtmp); + sgtmp++; used--; } used = nelems - used; @@ -643,7 +642,6 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist, struct strbuf *strbuf; iopte_t *base; unsigned long flags, ctx, i, npages; - struct scatterlist *sg, *sgprv; u32 bus_addr; if (unlikely(direction == DMA_NONE)) { @@ -656,14 +654,11 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist, bus_addr = sglist->dma_address & IO_PAGE_MASK; - sgprv = NULL; - for_each_sg(sglist, sg, nelems, i) { - if (sg->dma_length == 0) + for (i = 1; i < nelems; i++) + if (sglist[i].dma_length == 0) break; - sgprv = sg; - } - - npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) - + i--; + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; base = iommu->page_table + @@ -735,7 +730,6 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, struct iommu *iommu; struct strbuf *strbuf; unsigned long flags, ctx, npages, i; - struct scatterlist *sg, *sgprv; u32 bus_addr; iommu = dev->archdata.iommu; @@ -759,14 +753,11 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, /* Step 2: Kick data out of streaming buffers. */ bus_addr = sglist[0].dma_address & IO_PAGE_MASK; - sgprv = NULL; - for_each_sg(sglist, sg, nelems, i) { - if (sg->dma_length == 0) + for(i = 1; i < nelems; i++) + if (!sglist[i].dma_length) break; - sgprv = sg; - } - - npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) + i--; + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); diff --git a/trunk/arch/sparc64/kernel/kprobes.c b/trunk/arch/sparc64/kernel/kprobes.c index d94f901d321e..c93a15b785fa 100644 --- a/trunk/arch/sparc64/kernel/kprobes.c +++ b/trunk/arch/sparc64/kernel/kprobes.c @@ -42,8 +42,6 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; - int __kprobes arch_prepare_kprobe(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; diff --git a/trunk/arch/sparc64/kernel/ktlb.S b/trunk/arch/sparc64/kernel/ktlb.S index 964527d2ffa0..d4024ac0d619 100644 --- a/trunk/arch/sparc64/kernel/ktlb.S +++ b/trunk/arch/sparc64/kernel/ktlb.S @@ -226,15 +226,6 @@ kvmap_dtlb_load: ba,pt %xcc, sun4v_dtlb_load mov %g5, %g3 -kvmap_vmemmap: - sub %g4, %g5, %g5 - srlx %g5, 22, %g5 - sethi %hi(vmemmap_table), %g1 - sllx %g5, 3, %g5 - or %g1, %lo(vmemmap_table), %g1 - ba,pt %xcc, kvmap_dtlb_load - ldx [%g1 + %g5], %g5 - kvmap_dtlb_nonlinear: /* Catch kernel NULL pointer derefs. */ sethi %hi(PAGE_SIZE), %g5 @@ -242,13 +233,6 @@ kvmap_dtlb_nonlinear: bleu,pn %xcc, kvmap_dtlb_longpath nop - /* Do not use the TSB for vmemmap. */ - mov (VMEMMAP_BASE >> 24), %g5 - sllx %g5, 24, %g5 - cmp %g4,%g5 - bgeu,pn %xcc, kvmap_vmemmap - nop - KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load) kvmap_dtlb_tsbmiss: diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index cacacfae5451..95de1444ee67 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -374,7 +373,7 @@ static inline long fill_sg(long entry, struct device *dev, int nused, int nelems, unsigned long prot) { struct scatterlist *dma_sg = sg; - struct scatterlist *sg_end = sg_last(sg, nelems); + struct scatterlist *sg_end = sg + nelems; unsigned long flags; int i; @@ -414,7 +413,7 @@ static inline long fill_sg(long entry, struct device *dev, len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } - sg = sg_next(sg); + sg++; } pteval = (pteval & IOPTE_PAGE); @@ -432,25 +431,24 @@ static inline long fill_sg(long entry, struct device *dev, } pteval = (pteval & IOPTE_PAGE) + len; - sg = sg_next(sg); + sg++; /* Skip over any tail mappings we've fully mapped, * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && + while (sg < sg_end && + (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && (pteval == SG_ENT_PHYS_ADDRESS(sg)) && ((pteval ^ (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; - if (sg == sg_end) - break; - sg = sg_next(sg); + sg++; } if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); - dma_sg = sg_next(dma_sg); + dma_sg++; } if (unlikely(iommu_batch_end() < 0L)) @@ -512,7 +510,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, sgtmp = sglist; while (used && sgtmp->dma_length) { sgtmp->dma_address += dma_base; - sgtmp = sg_next(sgtmp); + sgtmp++; used--; } used = nelems - used; @@ -547,7 +545,6 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, struct pci_pbm_info *pbm; struct iommu *iommu; unsigned long flags, i, npages; - struct scatterlist *sg, *sgprv; long entry; u32 devhandle, bus_addr; @@ -561,15 +558,12 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, devhandle = pbm->devhandle; bus_addr = sglist->dma_address & IO_PAGE_MASK; - sgprv = NULL; - for_each_sg(sglist, sg, nelems, i) { - if (sg->dma_length == 0) - break; - sgprv = sg; - } - - npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) - + for (i = 1; i < nelems; i++) + if (sglist[i].dma_length == 0) + break; + i--; + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index 407d74a8a542..c73b7a48b036 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -52,13 +52,14 @@ int sparc64_multi_core __read_mostly; cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE; cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; -DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly = + { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; cpumask_t cpu_core_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_possible_map); EXPORT_SYMBOL(cpu_online_map); -EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); +EXPORT_SYMBOL(cpu_sibling_map); EXPORT_SYMBOL(cpu_core_map); static cpumask_t smp_commenced_mask; @@ -1260,16 +1261,16 @@ void __devinit smp_fill_in_sib_core_maps(void) for_each_present_cpu(i) { unsigned int j; - cpus_clear(per_cpu(cpu_sibling_map, i)); + cpus_clear(cpu_sibling_map[i]); if (cpu_data(i).proc_id == -1) { - cpu_set(i, per_cpu(cpu_sibling_map, i)); + cpu_set(i, cpu_sibling_map[i]); continue; } for_each_present_cpu(j) { if (cpu_data(i).proc_id == cpu_data(j).proc_id) - cpu_set(j, per_cpu(cpu_sibling_map, i)); + cpu_set(j, cpu_sibling_map[i]); } } } @@ -1341,9 +1342,9 @@ int __cpu_disable(void) cpu_clear(cpu, cpu_core_map[i]); cpus_clear(cpu_core_map[cpu]); - for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) - cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); - cpus_clear(per_cpu(cpu_sibling_map, cpu)); + for_each_cpu_mask(i, cpu_sibling_map[cpu]) + cpu_clear(cpu, cpu_sibling_map[i]); + cpus_clear(cpu_sibling_map[cpu]); c = &cpu_data(cpu); diff --git a/trunk/arch/sparc64/mm/fault.c b/trunk/arch/sparc64/mm/fault.c index e2027f27c0fe..9f7740eee8d2 100644 --- a/trunk/arch/sparc64/mm/fault.c +++ b/trunk/arch/sparc64/mm/fault.c @@ -463,7 +463,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) up_read(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); if (!(regs->tstate & TSTATE_PRIV)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto handle_kernel_fault; intr_or_no_mm: diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c index 100c4456ed1e..f0ab9aab308f 100644 --- a/trunk/arch/sparc64/mm/init.c +++ b/trunk/arch/sparc64/mm/init.c @@ -1645,58 +1645,6 @@ EXPORT_SYMBOL(_PAGE_E); unsigned long _PAGE_CACHE __read_mostly; EXPORT_SYMBOL(_PAGE_CACHE); -#ifdef CONFIG_SPARSEMEM_VMEMMAP - -#define VMEMMAP_CHUNK_SHIFT 22 -#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) -#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) -#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) - -#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ - sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) -unsigned long vmemmap_table[VMEMMAP_SIZE]; - -int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) -{ - unsigned long vstart = (unsigned long) start; - unsigned long vend = (unsigned long) (start + nr); - unsigned long phys_start = (vstart - VMEMMAP_BASE); - unsigned long phys_end = (vend - VMEMMAP_BASE); - unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK; - unsigned long end = VMEMMAP_ALIGN(phys_end); - unsigned long pte_base; - - pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U | - _PAGE_CP_4U | _PAGE_CV_4U | - _PAGE_P_4U | _PAGE_W_4U); - if (tlb_type == hypervisor) - pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V | - _PAGE_CP_4V | _PAGE_CV_4V | - _PAGE_P_4V | _PAGE_W_4V); - - for (; addr < end; addr += VMEMMAP_CHUNK) { - unsigned long *vmem_pp = - vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT); - void *block; - - if (!(*vmem_pp & _PAGE_VALID)) { - block = vmemmap_alloc_block(1UL << 22, node); - if (!block) - return -ENOMEM; - - *vmem_pp = pte_base | __pa(block); - - printk(KERN_INFO "[%p-%p] page_structs=%lu " - "node=%d entry=%lu/%lu\n", start, block, nr, - node, - addr >> VMEMMAP_CHUNK_SHIFT, - VMEMMAP_SIZE >> VMEMMAP_CHUNK_SHIFT); - } - } - return 0; -} -#endif /* CONFIG_SPARSEMEM_VMEMMAP */ - static void prot_init_common(unsigned long page_none, unsigned long page_shared, unsigned long page_copy, @@ -1961,4 +1909,9 @@ void online_page(struct page *page) num_physpages++; } +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} + #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/trunk/arch/um/Kconfig b/trunk/arch/um/Kconfig index 740d8a922e48..e6ff30266542 100644 --- a/trunk/arch/um/Kconfig +++ b/trunk/arch/um/Kconfig @@ -55,14 +55,6 @@ config GENERIC_BUG default y depends on BUG -config GENERIC_TIME - bool - default y - -config GENERIC_CLOCKEVENTS - bool - default y - # Used in kernel/irq/manage.c and include/linux/irq.h config IRQ_RELEASE_METHOD bool @@ -70,25 +62,63 @@ config IRQ_RELEASE_METHOD menu "UML-specific options" +config MODE_TT + bool "Tracing thread support (DEPRECATED)" + default n + depends on BROKEN + help + This option controls whether tracing thread support is compiled + into UML. This option is largely obsolete, given that skas0 provides + skas security and performance without needing to patch the host. + It is safe to say 'N' here; saying 'Y' may cause additional problems + with the resulting binary even if you run UML in SKAS mode, and running + in TT mode is strongly *NOT RECOMMENDED*. + config STATIC_LINK bool "Force a static link" default n + depends on !MODE_TT help - This option gives you the ability to force a static link of UML. - Normally, UML is linked as a shared binary. This is inconvenient for - use in a chroot jail. So, if you intend to run UML inside a chroot, - you probably want to say Y here. - Additionally, this option enables using higher memory spaces (up to - 2.75G) for UML. + If CONFIG_MODE_TT is disabled, then this option gives you the ability + to force a static link of UML. Normally, if only skas mode is built + in to UML, it will be linked as a shared binary. This is inconvenient + for use in a chroot jail. So, if you intend to run UML inside a + chroot, and you disable CONFIG_MODE_TT, you probably want to say Y + here. + Additionally, this option enables using higher memory spaces (up to + 2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads + to best results for this. + +config KERNEL_HALF_GIGS + int "Kernel address space size (in .5G units)" + default "1" + depends on MODE_TT + help + This determines the amount of address space that UML will allocate for + its own, measured in half Gigabyte units. The default is 1. + Change this only if you need to boot UML with an unusually large amount + of physical memory. + +config MODE_SKAS + bool "Separate Kernel Address Space support" if MODE_TT + default y + help + This option controls whether skas (separate kernel address space) + support is compiled in. + Unless you have specific needs to use TT mode (which applies almost only + to developers), you should say Y here. + SKAS mode will make use of the SKAS3 patch if it is applied on the host + (and your UML will run in SKAS3 mode), but if no SKAS patch is applied + on the host it will run in SKAS0 mode, which is anyway faster than TT + mode. source "arch/um/Kconfig.arch" source "mm/Kconfig" -source "kernel/time/Kconfig" config LD_SCRIPT_STATIC bool default y - depends on STATIC_LINK + depends on MODE_TT || STATIC_LINK config LD_SCRIPT_DYN bool @@ -98,18 +128,18 @@ config LD_SCRIPT_DYN config NET bool "Networking support" help - Unless you really know what you are doing, you should say Y here. - The reason is that some programs need kernel networking support even - when running on a stand-alone machine that isn't connected to any - other computer. If you are upgrading from an older kernel, you - should consider updating your networking tools too because changes - in the kernel and the tools often go hand in hand. The tools are - contained in the package net-tools, the location and version number - of which are given in . + Unless you really know what you are doing, you should say Y here. + The reason is that some programs need kernel networking support even + when running on a stand-alone machine that isn't connected to any + other computer. If you are upgrading from an older kernel, you + should consider updating your networking tools too because changes + in the kernel and the tools often go hand in hand. The tools are + contained in the package net-tools, the location and version number + of which are given in . - For a general introduction to Linux networking, it is highly - recommended to read the NET-HOWTO, available from - . + For a general introduction to Linux networking, it is highly + recommended to read the NET-HOWTO, available from + . source "fs/Kconfig.binfmt" @@ -117,99 +147,99 @@ source "fs/Kconfig.binfmt" config HOSTFS tristate "Host filesystem" help - While the User-Mode Linux port uses its own root file system for - booting and normal file access, this module lets the UML user - access files stored on the host. It does not require any - network connection between the Host and UML. An example use of - this might be: + While the User-Mode Linux port uses its own root file system for + booting and normal file access, this module lets the UML user + access files stored on the host. It does not require any + network connection between the Host and UML. An example use of + this might be: - mount none /tmp/fromhost -t hostfs -o /tmp/umlshare + mount none /tmp/fromhost -t hostfs -o /tmp/umlshare - where /tmp/fromhost is an empty directory inside UML and - /tmp/umlshare is a directory on the host with files the UML user - wishes to access. + where /tmp/fromhost is an empty directory inside UML and + /tmp/umlshare is a directory on the host with files the UML user + wishes to access. - For more information, see - . + For more information, see + . - If you'd like to be able to work with files stored on the host, - say Y or M here; otherwise say N. + If you'd like to be able to work with files stored on the host, + say Y or M here; otherwise say N. config HPPFS tristate "HoneyPot ProcFS (EXPERIMENTAL)" depends on EXPERIMENTAL help - hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc - entries to be overridden, removed, or fabricated from the host. - Its purpose is to allow a UML to appear to be a physical machine - by removing or changing anything in /proc which gives away the - identity of a UML. + hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc + entries to be overridden, removed, or fabricated from the host. + Its purpose is to allow a UML to appear to be a physical machine + by removing or changing anything in /proc which gives away the + identity of a UML. - See for more information. + See for more information. - You only need this if you are setting up a UML honeypot. Otherwise, - it is safe to say 'N' here. + You only need this if you are setting up a UML honeypot. Otherwise, + it is safe to say 'N' here. config MCONSOLE bool "Management console" default y help - The user mode linux management console is a low-level interface to - the kernel, somewhat like the i386 SysRq interface. Since there is - a full-blown operating system running under every user mode linux - instance, there is much greater flexibility possible than with the - SysRq mechanism. + The user mode linux management console is a low-level interface to + the kernel, somewhat like the i386 SysRq interface. Since there is + a full-blown operating system running under every user mode linux + instance, there is much greater flexibility possible than with the + SysRq mechanism. - If you answer 'Y' to this option, to use this feature, you need the - mconsole client (called uml_mconsole) which is present in CVS in - 2.4.5-9um and later (path /tools/mconsole), and is also in the - distribution RPM package in 2.4.6 and later. + If you answer 'Y' to this option, to use this feature, you need the + mconsole client (called uml_mconsole) which is present in CVS in + 2.4.5-9um and later (path /tools/mconsole), and is also in the + distribution RPM package in 2.4.6 and later. - It is safe to say 'Y' here. + It is safe to say 'Y' here. config MAGIC_SYSRQ bool "Magic SysRq key" depends on MCONSOLE - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). A key for each of the - possible requests is provided. + ---help--- + If you say Y here, you will have some control over the system even + if the system crashes for example during kernel debugging (e.g., you + will be able to flush the buffer cache to disk, reboot the system + immediately or dump some status information). A key for each of the + possible requests is provided. - This is the feature normally accomplished by pressing a key - while holding SysRq (Alt+PrintScreen). + This is the feature normally accomplished by pressing a key + while holding SysRq (Alt+PrintScreen). - On UML, this is accomplished by sending a "sysrq" command with - mconsole, followed by the letter for the requested command. + On UML, this is accomplished by sending a "sysrq" command with + mconsole, followed by the letter for the requested command. - The keys are documented in . Don't say Y - unless you really know what this hack does. + The keys are documented in . Don't say Y + unless you really know what this hack does. config SMP bool "Symmetric multi-processing support (EXPERIMENTAL)" default n #SMP_BROKEN is for x86_64. - depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) + depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) help - This option enables UML SMP support. - It is NOT related to having a real SMP box. Not directly, at least. + This option enables UML SMP support. + It is NOT related to having a real SMP box. Not directly, at least. - UML implements virtual SMP by allowing as many processes to run - simultaneously on the host as there are virtual processors configured. + UML implements virtual SMP by allowing as many processes to run + simultaneously on the host as there are virtual processors configured. - Obviously, if the host is a uniprocessor, those processes will - timeshare, but, inside UML, will appear to be running simultaneously. - If the host is a multiprocessor, then UML processes may run - simultaneously, depending on the host scheduler. + Obviously, if the host is a uniprocessor, those processes will + timeshare, but, inside UML, will appear to be running simultaneously. + If the host is a multiprocessor, then UML processes may run + simultaneously, depending on the host scheduler. - This, however, is supported only in TT mode. So, if you use the SKAS - patch on your host, switching to TT mode and enabling SMP usually - gives you worse performances. - Also, since the support for SMP has been under-developed, there could - be some bugs being exposed by enabling SMP. + This, however, is supported only in TT mode. So, if you use the SKAS + patch on your host, switching to TT mode and enabling SMP usually gives + you worse performances. + Also, since the support for SMP has been under-developed, there could + be some bugs being exposed by enabling SMP. - If you don't know what to do, say N. + If you don't know what to do, say N. config NR_CPUS int "Maximum number of CPUs (2-32)" @@ -221,24 +251,29 @@ config NEST_LEVEL int "Nesting level" default "0" help - This is set to the number of layers of UMLs that this UML will be run - in. Normally, this is zero, meaning that it will run directly on the - host. Setting it to one will build a UML that can run inside a UML - that is running on the host. Generally, if you intend this UML to run - inside another UML, set CONFIG_NEST_LEVEL to one more than the host - UML. + This is set to the number of layers of UMLs that this UML will be run + in. Normally, this is zero, meaning that it will run directly on the + host. Setting it to one will build a UML that can run inside a UML + that is running on the host. Generally, if you intend this UML to run + inside another UML, set CONFIG_NEST_LEVEL to one more than the host + UML. + + Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to + greater than one, then the guest UML should have its CONFIG_NEST_LEVEL + set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. + Only change this if you are running nested UMLs. config HIGHMEM bool "Highmem support (EXPERIMENTAL)" depends on !64BIT && EXPERIMENTAL default n help - This was used to allow UML to run with big amounts of memory. - Currently it is unstable, so if unsure say N. + This was used to allow UML to run with big amounts of memory. + Currently it is unstable, so if unsure say N. - To use big amounts of memory, it is recommended enable static - linking (i.e. CONFIG_STATIC_LINK) - this should allow the - guest to use up to 2.75G of memory. + To use big amounts of memory, it is recommended to disable TT mode (i.e. + CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) - + this should allow the guest to use up to 2.75G of memory. config KERNEL_STACK_ORDER int "Kernel stack size order" @@ -246,9 +281,20 @@ config KERNEL_STACK_ORDER range 1 10 if 64BIT default 0 if !64BIT help - This option determines the size of UML kernel stacks. They will - be 1 << order pages. The default is OK unless you're running Valgrind - on UML, in which case, set this to 3. + This option determines the size of UML kernel stacks. They will + be 1 << order pages. The default is OK unless you're running Valgrind + on UML, in which case, set this to 3. + +config UML_REAL_TIME_CLOCK + bool "Real-time Clock" + default y + help + This option makes UML time deltas match wall clock deltas. This should + normally be enabled. The exception would be if you are debugging with + UML and spend long times with UML stopped at a breakpoint. In this + case, when UML is restarted, it will call the timer enough times to make + up for the time spent at the breakpoint. This could result in a + noticeable lag. If this is a problem, then disable this option. endmenu diff --git a/trunk/arch/um/Kconfig.char b/trunk/arch/um/Kconfig.char index 9a78d354f0b4..a5b079d5e865 100644 --- a/trunk/arch/um/Kconfig.char +++ b/trunk/arch/um/Kconfig.char @@ -5,7 +5,7 @@ config STDERR_CONSOLE bool "stderr console" default y help - console driver which dumps all printk messages to stderr. + console driver which dumps all printk messages to stderr. config STDIO_CONSOLE bool @@ -14,58 +14,60 @@ config STDIO_CONSOLE config SSL bool "Virtual serial line" help - The User-Mode Linux environment allows you to create virtual serial - lines on the UML that are usually made to show up on the host as - ttys or ptys. + The User-Mode Linux environment allows you to create virtual serial + lines on the UML that are usually made to show up on the host as + ttys or ptys. - See for more - information and command line examples of how to use this facility. + See for more + information and command line examples of how to use this facility. - Unless you have a specific reason for disabling this, say Y. + Unless you have a specific reason for disabling this, say Y. config NULL_CHAN bool "null channel support" help - This option enables support for attaching UML consoles and serial - lines to a device similar to /dev/null. Data written to it disappears - and there is never any data to be read. + This option enables support for attaching UML consoles and serial + lines to a device similar to /dev/null. Data written to it disappears + and there is never any data to be read. config PORT_CHAN bool "port channel support" help - This option enables support for attaching UML consoles and serial - lines to host portals. They may be accessed with 'telnet - '. Any number of consoles and serial lines may be - attached to a single portal, although what UML device you get when - you telnet to that portal will be unpredictable. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host portals. They may be accessed with 'telnet + '. Any number of consoles and serial lines may be + attached to a single portal, although what UML device you get when + you telnet to that portal will be unpredictable. + It is safe to say 'Y' here. config PTY_CHAN bool "pty channel support" help - This option enables support for attaching UML consoles and serial - lines to host pseudo-terminals. Access to both traditional - pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled - with this option. The assignment of UML devices to host devices - will be announced in the kernel message log. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host pseudo-terminals. Access to both traditional + pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled + with this option. The assignment of UML devices to host devices + will be announced in the kernel message log. + It is safe to say 'Y' here. config TTY_CHAN bool "tty channel support" help - This option enables support for attaching UML consoles and serial - lines to host terminals. Access to both virtual consoles - (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and - /dev/pts/*) are controlled by this option. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host terminals. Access to both virtual consoles + (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and + /dev/pts/*) are controlled by this option. + It is safe to say 'Y' here. config XTERM_CHAN bool "xterm channel support" help - This option enables support for attaching UML consoles and serial - lines to xterms. Each UML device so assigned will be brought up in - its own xterm. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to xterms. Each UML device so assigned will be brought up in + its own xterm. + If you disable this option, then CONFIG_PT_PROXY will be disabled as + well, since UML's gdb currently requires an xterm. + It is safe to say 'Y' here. config NOCONFIG_CHAN bool @@ -75,39 +77,39 @@ config CON_ZERO_CHAN string "Default main console channel initialization" default "fd:0,fd:1" help - This is the string describing the channel to which the main console - will be attached by default. This value can be overridden from the - command line. The default value is "fd:0,fd:1", which attaches the - main console to stdin and stdout. - It is safe to leave this unchanged. + This is the string describing the channel to which the main console + will be attached by default. This value can be overridden from the + command line. The default value is "fd:0,fd:1", which attaches the + main console to stdin and stdout. + It is safe to leave this unchanged. config CON_CHAN string "Default console channel initialization" default "xterm" help - This is the string describing the channel to which all consoles - except the main console will be attached by default. This value can - be overridden from the command line. The default value is "xterm", - which brings them up in xterms. - It is safe to leave this unchanged, although you may wish to change - this if you expect the UML that you build to be run in environments - which don't have X or xterm available. + This is the string describing the channel to which all consoles + except the main console will be attached by default. This value can + be overridden from the command line. The default value is "xterm", + which brings them up in xterms. + It is safe to leave this unchanged, although you may wish to change + this if you expect the UML that you build to be run in environments + which don't have X or xterm available. config SSL_CHAN string "Default serial line channel initialization" default "pty" help - This is the string describing the channel to which the serial lines - will be attached by default. This value can be overridden from the - command line. The default value is "pty", which attaches them to - traditional pseudo-terminals. - It is safe to leave this unchanged, although you may wish to change - this if you expect the UML that you build to be run in environments - which don't have a set of /dev/pty* devices. + This is the string describing the channel to which the serial lines + will be attached by default. This value can be overridden from the + command line. The default value is "pty", which attaches them to + traditional pseudo-terminals. + It is safe to leave this unchanged, although you may wish to change + this if you expect the UML that you build to be run in environments + which don't have a set of /dev/pty* devices. config UNIX98_PTYS bool "Unix98 PTY support" - help + ---help--- A pseudo terminal (PTY) is a software device consisting of two halves: a master and a slave. The slave device behaves identical to a physical terminal; the master device is used by a process to @@ -130,7 +132,7 @@ config UNIX98_PTYS config LEGACY_PTYS bool "Legacy (BSD) PTY support" default y - help + ---help--- A pseudo terminal (PTY) is a software device consisting of two halves: a master and a slave. The slave device behaves identical to a physical terminal; the master device is used by a process to @@ -168,7 +170,7 @@ config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" depends on LEGACY_PTYS default "256" - help + ---help--- The maximum number of legacy PTYs that can be used at any one time. The default is 256, and should be more than enough. Embedded systems may want to reduce this to save memory. @@ -194,10 +196,10 @@ config UML_WATCHDOG config UML_SOUND tristate "Sound support" help - This option enables UML sound support. If enabled, it will pull in - soundcore and the UML hostaudio relay, which acts as a intermediary - between the host's dsp and mixer devices and the UML sound system. - It is safe to say 'Y' here. + This option enables UML sound support. If enabled, it will pull in + soundcore and the UML hostaudio relay, which acts as a intermediary + between the host's dsp and mixer devices and the UML sound system. + It is safe to say 'Y' here. config SOUND tristate @@ -215,21 +217,22 @@ config HW_RANDOM config UML_RANDOM tristate "Hardware random number generator" help - This option enables UML's "hardware" random number generator. It - attaches itself to the host's /dev/random, supplying as much entropy - as the host has, rather than the small amount the UML gets from its - own drivers. It registers itself as a standard hardware random number - generator, major 10, minor 183, and the canonical device name is - /dev/hwrng. - The way to make use of this is to install the rng-tools package - (check your distro, or download from - http://sourceforge.net/projects/gkernel/). rngd periodically reads - /dev/hwrng and injects the entropy into /dev/random. + This option enables UML's "hardware" random number generator. It + attaches itself to the host's /dev/random, supplying as much entropy + as the host has, rather than the small amount the UML gets from its + own drivers. It registers itself as a standard hardware random number + generator, major 10, minor 183, and the canonical device name is + /dev/hwrng. + The way to make use of this is to install the rng-tools package + (check your distro, or download from + http://sourceforge.net/projects/gkernel/). rngd periodically reads + /dev/hwrng and injects the entropy into /dev/random. config MMAPPER tristate "iomem emulation driver" help - This driver allows a host file to be used as emulated IO memory inside - UML. + This driver allows a host file to be used as emulated IO memory inside + UML. endmenu + diff --git a/trunk/arch/um/Kconfig.debug b/trunk/arch/um/Kconfig.debug index 1f6462ffd3e8..c86f5eb29fd5 100644 --- a/trunk/arch/um/Kconfig.debug +++ b/trunk/arch/um/Kconfig.debug @@ -2,31 +2,50 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config CMDLINE_ON_HOST + bool "Show command line arguments on the host in TT mode" + depends on MODE_TT + default !DEBUG_INFO + help + This controls whether arguments in guest processes should be shown on + the host's ps output. + Enabling this option hinders debugging on some recent GDB versions + (because GDB gets "confused" when we do an execvp()). So probably you + should disable it. + +config PT_PROXY + bool "Enable ptrace proxy" + depends on XTERM_CHAN && DEBUG_INFO && MODE_TT + help + This option enables a debugging interface which allows gdb to debug + the kernel without needing to actually attach to kernel threads. + If you want to do kernel debugging, say Y here; otherwise say N. + config GPROF bool "Enable gprof support" - depends on DEBUG_INFO + depends on DEBUG_INFO && MODE_SKAS && !MODE_TT help - This allows profiling of a User-Mode Linux kernel with the gprof - utility. + This allows profiling of a User-Mode Linux kernel with the gprof + utility. - See for more - details. + See for more + details. - If you're involved in UML kernel development and want to use gprof, - say Y. If you're unsure, say N. + If you're involved in UML kernel development and want to use gprof, + say Y. If you're unsure, say N. config GCOV bool "Enable gcov support" - depends on DEBUG_INFO + depends on DEBUG_INFO && MODE_SKAS help - This option allows developers to retrieve coverage data from a UML - session. + This option allows developers to retrieve coverage data from a UML + session. - See for more - details. + See for more + details. - If you're involved in UML kernel development and want to use gcov, - say Y. If you're unsure, say N. + If you're involved in UML kernel development and want to use gcov, + say Y. If you're unsure, say N. config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" diff --git a/trunk/arch/um/Kconfig.i386 b/trunk/arch/um/Kconfig.i386 index 9876d80d85dd..d6cffb27fff8 100644 --- a/trunk/arch/um/Kconfig.i386 +++ b/trunk/arch/um/Kconfig.i386 @@ -65,6 +65,20 @@ config 3_LEVEL_PGTABLES However, this it experimental on 32-bit architectures, so if unsure say N (on x86-64 it's automatically enabled, instead, as it's safe there). +config STUB_CODE + hex + default 0xbfffe000 if !HOST_VMSPLIT_2G + default 0x7fffe000 if HOST_VMSPLIT_2G + +config STUB_DATA + hex + default 0xbffff000 if !HOST_VMSPLIT_2G + default 0x7ffff000 if HOST_VMSPLIT_2G + +config STUB_START + hex + default STUB_CODE + config ARCH_HAS_SC_SIGNALS bool default y diff --git a/trunk/arch/um/Kconfig.net b/trunk/arch/um/Kconfig.net index 66e50026ade9..14a04ebdeae9 100644 --- a/trunk/arch/um/Kconfig.net +++ b/trunk/arch/um/Kconfig.net @@ -108,28 +108,6 @@ config UML_NET_DAEMON more than one without conflict. If you don't need UML networking, say N. -config UML_NET_VDE - bool "VDE transport" - depends on UML_NET - help - This User-Mode Linux network transport allows one or more running - UMLs on a single host to communicate with each other and also - with the rest of the world using Virtual Distributed Ethernet, - an improved fork of uml_switch. - - You must have libvdeplug installed in order to build the vde - transport into UML. - - To use this form of networking, you will need to run vde_switch - on the host. - - For more information, see - That site has a good overview of what VDE is and also examples - of the UML command line to use to enable VDE networking. - - If you need UML networking with VDE, - say Y. - config UML_NET_MCAST bool "Multicast transport" depends on UML_NET diff --git a/trunk/arch/um/Kconfig.x86_64 b/trunk/arch/um/Kconfig.x86_64 index d632e9a89cc3..f60e9e506424 100644 --- a/trunk/arch/um/Kconfig.x86_64 +++ b/trunk/arch/um/Kconfig.x86_64 @@ -17,12 +17,24 @@ config SEMAPHORE_SLEEPERS config TOP_ADDR hex - default 0x7fc0000000 + default 0x80000000 config 3_LEVEL_PGTABLES bool default y +config STUB_CODE + hex + default 0x7fbfffe000 + +config STUB_DATA + hex + default 0x7fbffff000 + +config STUB_START + hex + default STUB_CODE + config ARCH_HAS_SC_SIGNALS bool default n diff --git a/trunk/arch/um/Makefile b/trunk/arch/um/Makefile index 82c2ac48040d..0666729eb976 100644 --- a/trunk/arch/um/Makefile +++ b/trunk/arch/um/Makefile @@ -2,7 +2,7 @@ # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. # -# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -31,9 +31,18 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/skas +um-modes-$(CONFIG_MODE_TT) += tt +um-modes-$(CONFIG_MODE_SKAS) += skas -include $(srctree)/$(ARCH_DIR)/Makefile-skas +MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ + -I$(srctree)/$(ARCH_DIR)/include/$(mode)) + +MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ + $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) + +ifneq ($(MAKEFILES-INCL),) + include $(MAKEFILES-INCL) +endif ARCH_INCLUDE := -I$(ARCH_DIR)/include ifneq ($(KBUILD_SRC),) @@ -49,15 +58,14 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) # # These apply to USER_CFLAGS to. -KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ +CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ - -Din6addr_loopback=kernel_in6addr_loopback \ - -Din6addr_any=kernel_in6addr_any + -Din6addr_loopback=kernel_in6addr_loopback -KBUILD_AFLAGS += $(ARCH_INCLUDE) +AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ - $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ + $(patsubst -I%,,$(CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ -D_FILE_OFFSET_BITS=64 include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) @@ -67,21 +75,22 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common -# in KBUILD_CFLAGS. Otherwise, it would cause ld to complain about the two different +# in CFLAGS. Otherwise, it would cause ld to complain about the two different # errnos. # These apply to kernelspace only. KERNEL_DEFINES = -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES) -KBUILD_CFLAGS += $(KERNEL_DEFINES) -KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,) +CFLAGS += $(KERNEL_DEFINES) +CFLAGS += $(call cc-option,-fno-unit-at-a-time,) # These are needed for clean and mrproper, since in that case .config is not # included; the values here are meaningless CONFIG_NEST_LEVEL ?= 0 +CONFIG_KERNEL_HALF_GIGS ?= 0 -SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000) +SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) PHONY += linux @@ -114,6 +123,7 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) $(call cc-option, -fno-stack-protector,) \ $(call cc-option, -fno-stack-protector-all,) +CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT CONFIG_KERNEL_STACK_ORDER ?= 2 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) @@ -121,10 +131,13 @@ ifndef START START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] ) endif -CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ - -DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE) +CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \ + -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ + -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \ + -DKERNEL_STACK_SIZE=$(STACK_SIZE) \ + -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o -# The wrappers will select whether using "malloc" or the kernel allocator. +#The wrappers will select whether using "malloc" or the kernel allocator. LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) @@ -137,8 +150,8 @@ define cmd_vmlinux__ FORCE ,$^) ; rm -f linux endef -# When cleaning we don't include .config, so we don't include -# TT or skas makefiles and don't clean skas_ptregs.h. +#When cleaning we don't include .config, so we don't include +#TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ $(ARCH_DIR)/include/user_constants.h \ $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch diff --git a/trunk/arch/um/Makefile-i386 b/trunk/arch/um/Makefile-i386 index 0178df306939..60107ed4905b 100644 --- a/trunk/arch/um/Makefile-i386 +++ b/trunk/arch/um/Makefile-i386 @@ -2,7 +2,11 @@ core-y += arch/um/sys-i386/ arch/x86/crypto/ TOP_ADDR := $(CONFIG_TOP_ADDR) -START := 0x8048000 +ifeq ($(CONFIG_MODE_SKAS),y) + ifneq ($(CONFIG_MODE_TT),y) + START := 0x8048000 + endif +endif LDFLAGS += -m elf_i386 ELF_ARCH := $(SUBARCH) @@ -12,8 +16,8 @@ HEADER_ARCH := x86 ifeq ("$(origin SUBARCH)", "command line") ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") -KBUILD_CFLAGS += $(call cc-option,-m32) -KBUILD_AFLAGS += $(call cc-option,-m32) +CFLAGS += $(call cc-option,-m32) +AFLAGS += $(call cc-option,-m32) LINK-y += $(call cc-option,-m32) UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) @@ -38,4 +42,4 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) # an unresolved reference. cflags-y += -ffreestanding -KBUILD_CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) diff --git a/trunk/arch/um/Makefile-os-Linux b/trunk/arch/um/Makefile-os-Linux index 52859487c95d..0c0f9a1cbbad 100644 --- a/trunk/arch/um/Makefile-os-Linux +++ b/trunk/arch/um/Makefile-os-Linux @@ -5,4 +5,4 @@ # To get a definition of F_SETSIG USER_CFLAGS += -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -KBUILD_CFLAGS += -D_LARGEFILE64_SOURCE +CFLAGS += -D_LARGEFILE64_SOURCE diff --git a/trunk/arch/um/Makefile-x86_64 b/trunk/arch/um/Makefile-x86_64 index fe5316f0c6a5..8a00e5f6934c 100644 --- a/trunk/arch/um/Makefile-x86_64 +++ b/trunk/arch/um/Makefile-x86_64 @@ -9,12 +9,12 @@ _extra_flags_ = -fno-builtin -m64 #We #undef __x86_64__ for kernelspace, not for userspace where #it's needed for headers to work! ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__ -KBUILD_CFLAGS += $(_extra_flags_) +CFLAGS += $(_extra_flags_) CHECKFLAGS += -m64 -KBUILD_AFLAGS += -m64 +AFLAGS += -m64 LDFLAGS += -m elf_x86_64 -KBUILD_CPPFLAGS += -m64 +CPPFLAGS += -m64 ELF_ARCH := i386:x86-64 ELF_FORMAT := elf64-x86-64 diff --git a/trunk/arch/um/defconfig b/trunk/arch/um/defconfig index f609edede065..1e0f677c2f46 100644 --- a/trunk/arch/um/defconfig +++ b/trunk/arch/um/defconfig @@ -12,7 +12,9 @@ CONFIG_IRQ_RELEASE_METHOD=y # # UML-specific options # +# CONFIG_MODE_TT is not set # CONFIG_STATIC_LINK is not set +CONFIG_MODE_SKAS=y # # Host processor type and features @@ -59,6 +61,9 @@ CONFIG_SEMAPHORE_SLEEPERS=y # CONFIG_HOST_2G_2G is not set CONFIG_TOP_ADDR=0xc0000000 # CONFIG_3_LEVEL_PGTABLES is not set +CONFIG_STUB_CODE=0xbfffe000 +CONFIG_STUB_DATA=0xbffff000 +CONFIG_STUB_START=0xbfffe000 CONFIG_ARCH_HAS_SC_SIGNALS=y CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y CONFIG_GENERIC_HWEIGHT=y @@ -70,9 +75,6 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_LD_SCRIPT_DYN=y CONFIG_NET=y CONFIG_BINFMT_ELF=y @@ -80,10 +82,11 @@ CONFIG_BINFMT_MISC=m # CONFIG_HOSTFS is not set # CONFIG_HPPFS is not set CONFIG_MCONSOLE=y -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set CONFIG_NEST_LEVEL=0 # CONFIG_HIGHMEM is not set CONFIG_KERNEL_STACK_ORDER=0 +CONFIG_UML_REAL_TIME_CLOCK=y # # Code maturity level options diff --git a/trunk/arch/um/drivers/Makefile b/trunk/arch/um/drivers/Makefile index d283e7b022a0..de17d4c6e02d 100644 --- a/trunk/arch/um/drivers/Makefile +++ b/trunk/arch/um/drivers/Makefile @@ -17,18 +17,12 @@ ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o harddog-objs := harddog_kern.o harddog_user.o -LDFLAGS_pcap.o := -r $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a) +LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) -LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a) - -targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o +targets := pcap_kern.o pcap_user.o $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) - -$(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o - $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_vde.o) - #XXX: The call below does not work because the flags are added before the # object name, so nothing from the library gets linked. #$(call if_changed,ld) @@ -43,7 +37,6 @@ obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o obj-$(CONFIG_UML_NET_DAEMON) += daemon.o -obj-$(CONFIG_UML_NET_VDE) += vde.o obj-$(CONFIG_UML_NET_MCAST) += mcast.o obj-$(CONFIG_UML_NET_PCAP) += pcap.o obj-$(CONFIG_UML_NET) += net.o @@ -61,6 +54,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-$(CONFIG_UML_RANDOM) += random.o # pcap_user.o must be added explicitly. -USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o +USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/drivers/chan_kern.c b/trunk/arch/um/drivers/chan_kern.c index db3082b4da46..629b00e3b0b0 100644 --- a/trunk/arch/um/drivers/chan_kern.c +++ b/trunk/arch/um/drivers/chan_kern.c @@ -1,19 +1,28 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include +#include +#include #include #include +#include #include +#include #include "chan_kern.h" +#include "kern.h" +#include "irq_user.h" +#include "sigio.h" +#include "line.h" #include "os.h" #ifdef CONFIG_NOCONFIG_CHAN static void *not_configged_init(char *str, int device, const struct chan_opts *opts) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return NULL; } @@ -21,34 +30,34 @@ static void *not_configged_init(char *str, int device, static int not_configged_open(int input, int output, int primary, void *data, char **dev_out) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_close(int fd, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); } static int not_configged_read(int fd, char *c_out, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_write(int fd, const char *buf, int len, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_console_write(int fd, const char *buf, int len) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } @@ -56,14 +65,14 @@ static int not_configged_console_write(int fd, const char *buf, int len) static int not_configged_window_size(int fd, void *data, unsigned short *rows, unsigned short *cols) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_free(void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); } @@ -80,17 +89,64 @@ static const struct chan_ops not_configged_ops = { }; #endif /* CONFIG_NOCONFIG_CHAN */ +void generic_close(int fd, void *unused) +{ + os_close_file(fd); +} + +int generic_read(int fd, char *c_out, void *unused) +{ + int n; + + n = os_read_file(fd, c_out, sizeof(*c_out)); + + if(n == -EAGAIN) + return 0; + else if(n == 0) + return -EIO; + return n; +} + +/* XXX Trivial wrapper around os_write_file */ + +int generic_write(int fd, const char *buf, int n, void *unused) +{ + return os_write_file(fd, buf, n); +} + +int generic_window_size(int fd, void *unused, unsigned short *rows_out, + unsigned short *cols_out) +{ + int rows, cols; + int ret; + + ret = os_window_size(fd, &rows, &cols); + if(ret < 0) + return ret; + + ret = ((*rows_out != rows) || (*cols_out != cols)); + + *rows_out = rows; + *cols_out = cols; + + return ret; +} + +void generic_free(void *data) +{ + kfree(data); +} + static void tty_receive_char(struct tty_struct *tty, char ch) { - if (tty == NULL) - return; + if(tty == NULL) return; - if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { - if (ch == STOP_CHAR(tty)) { + if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { + if(ch == STOP_CHAR(tty)){ stop_tty(tty); return; } - else if (ch == START_CHAR(tty)) { + else if(ch == START_CHAR(tty)){ start_tty(tty); return; } @@ -103,14 +159,14 @@ static int open_one_chan(struct chan *chan) { int fd, err; - if (chan->opened) + if(chan->opened) return 0; - if (chan->ops->open == NULL) + if(chan->ops->open == NULL) fd = 0; else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, chan->data, &chan->dev); - if (fd < 0) + if(fd < 0) return fd; err = os_set_fd_block(fd, 0); @@ -131,10 +187,10 @@ int open_chan(struct list_head *chans) struct chan *chan; int ret, err = 0; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); ret = open_one_chan(chan); - if (chan->primary) + if(chan->primary) err = ret; } return err; @@ -145,9 +201,9 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) struct list_head *ele; struct chan *chan; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if (chan->primary && chan->output && chan->ops->winch) { + if(chan->primary && chan->output && chan->ops->winch){ register_winch(chan->fd, tty); return; } @@ -160,7 +216,7 @@ int enable_chan(struct line *line) struct chan *chan; int err; - list_for_each(ele, &line->chan_list) { + list_for_each(ele, &line->chan_list){ chan = list_entry(ele, struct chan, list); err = open_one_chan(chan); if (err) { @@ -170,7 +226,7 @@ int enable_chan(struct line *line) continue; } - if (chan->enabled) + if(chan->enabled) continue; err = line_setup_irq(chan->fd, chan->input, chan->output, line, chan); @@ -207,12 +263,12 @@ void free_irqs(void) list_splice_init(&irqs_to_free, &list); spin_unlock_irqrestore(&irqs_to_free_lock, flags); - list_for_each(ele, &list) { + list_for_each(ele, &list){ chan = list_entry(ele, struct chan, free_list); - if (chan->input) + if(chan->input) free_irq(chan->line->driver->read_irq, chan); - if (chan->output) + if(chan->output) free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } @@ -222,22 +278,22 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) { unsigned long flags; - if (!chan->opened) + if(!chan->opened) return; - if (delay_free_irq) { + if(delay_free_irq){ spin_lock_irqsave(&irqs_to_free_lock, flags); list_add(&chan->free_list, &irqs_to_free); spin_unlock_irqrestore(&irqs_to_free_lock, flags); } else { - if (chan->input) + if(chan->input) free_irq(chan->line->driver->read_irq, chan); - if (chan->output) + if(chan->output) free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } - if (chan->ops->close != NULL) + if(chan->ops->close != NULL) (*chan->ops->close)(chan->fd, chan->data); chan->opened = 0; @@ -266,7 +322,7 @@ void deactivate_chan(struct list_head *chans, int irq) list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if (chan->enabled && chan->input) + if(chan->enabled && chan->input) deactivate_fd(chan->fd, irq); } } @@ -279,7 +335,7 @@ void reactivate_chan(struct list_head *chans, int irq) list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if (chan->enabled && chan->input) + if(chan->enabled && chan->input) reactivate_fd(chan->fd, irq); } } @@ -291,14 +347,10 @@ int write_chan(struct list_head *chans, const char *buf, int len, struct chan *chan = NULL; int n, ret = 0; - if (len == 0) - return 0; - list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); if (!chan->output || (chan->ops->write == NULL)) continue; - n = chan->ops->write(chan->fd, buf, len, chan->data); if (chan->primary) { ret = n; @@ -315,14 +367,12 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) struct chan *chan; int n, ret = 0; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if (!chan->output || (chan->ops->console_write == NULL)) + if(!chan->output || (chan->ops->console_write == NULL)) continue; - n = chan->ops->console_write(chan->fd, buf, len); - if (chan->primary) - ret = n; + if(chan->primary) ret = n; } return ret; } @@ -332,11 +382,10 @@ int console_open_chan(struct line *line, struct console *co) int err; err = open_chan(&line->chan_list); - if (err) + if(err) return err; - printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name, - co->index); + printk("Console initialized on /dev/%s%d\n", co->name, co->index); return 0; } @@ -346,10 +395,10 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, struct list_head *ele; struct chan *chan; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if (chan->primary) { - if (chan->ops->window_size == NULL) + if(chan->primary){ + if(chan->ops->window_size == NULL) return 0; return chan->ops->window_size(chan->fd, chan->data, rows_out, cols_out); @@ -364,11 +413,10 @@ static void free_one_chan(struct chan *chan, int delay_free_irq) close_one_chan(chan, delay_free_irq); - if (chan->ops->free != NULL) + if(chan->ops->free != NULL) (*chan->ops->free)(chan->data); - if (chan->primary && chan->output) - ignore_sigio_fd(chan->fd); + if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); kfree(chan); } @@ -377,7 +425,7 @@ static void free_chan(struct list_head *chans, int delay_free_irq) struct list_head *ele, *next; struct chan *chan; - list_for_each_safe(ele, next, chans) { + list_for_each_safe(ele, next, chans){ chan = list_entry(ele, struct chan, list); free_one_chan(chan, delay_free_irq); } @@ -388,14 +436,14 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, { int n = 0; - if (chan == NULL) { + if(chan == NULL){ CONFIG_CHUNK(str, size, n, "none", 1); return n; } CONFIG_CHUNK(str, size, n, chan->ops->type, 0); - if (chan->dev == NULL) { + if(chan->dev == NULL){ CONFIG_CHUNK(str, size, n, "", 1); return n; } @@ -415,7 +463,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, str += n; size -= n; - if (in == out) { + if(in == out){ CONFIG_CHUNK(str, size, n, "", 1); return n; } @@ -435,13 +483,13 @@ int chan_config_string(struct list_head *chans, char *str, int size, struct list_head *ele; struct chan *chan, *in = NULL, *out = NULL; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if (!chan->primary) + if(!chan->primary) continue; - if (chan->input) + if(chan->input) in = chan; - if (chan->output) + if(chan->output) out = chan; } @@ -500,27 +548,27 @@ static struct chan *parse_chan(struct line *line, char *str, int device, ops = NULL; data = NULL; - for(i = 0; i < ARRAY_SIZE(chan_table); i++) { + for(i = 0; i < ARRAY_SIZE(chan_table); i++){ entry = &chan_table[i]; - if (!strncmp(str, entry->key, strlen(entry->key))) { + if(!strncmp(str, entry->key, strlen(entry->key))){ ops = entry->ops; str += strlen(entry->key); break; } } - if (ops == NULL) { + if(ops == NULL){ *error_out = "No match for configured backends"; return NULL; } data = (*ops->init)(str, device, opts); - if (data == NULL) { + if(data == NULL){ *error_out = "Configuration failed"; return NULL; } chan = kmalloc(sizeof(*chan), GFP_ATOMIC); - if (chan == NULL) { + if(chan == NULL){ *error_out = "Memory allocation failed"; return NULL; } @@ -546,26 +594,26 @@ int parse_chan_pair(char *str, struct line *line, int device, struct chan *new, *chan; char *in, *out; - if (!list_empty(chans)) { + if(!list_empty(chans)){ chan = list_entry(chans->next, struct chan, list); free_chan(chans, 0); INIT_LIST_HEAD(chans); } out = strchr(str, ','); - if (out != NULL) { + if(out != NULL){ in = str; *out = '\0'; out++; new = parse_chan(line, in, device, opts, error_out); - if (new == NULL) + if(new == NULL) return -1; new->input = 1; list_add(&new->list, chans); new = parse_chan(line, out, device, opts, error_out); - if (new == NULL) + if(new == NULL) return -1; list_add(&new->list, chans); @@ -573,7 +621,7 @@ int parse_chan_pair(char *str, struct line *line, int device, } else { new = parse_chan(line, str, device, opts, error_out); - if (new == NULL) + if(new == NULL) return -1; list_add(&new->list, chans); @@ -588,9 +636,9 @@ int chan_out_fd(struct list_head *chans) struct list_head *ele; struct chan *chan; - list_for_each(ele, chans) { + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if (chan->primary && chan->output) + if(chan->primary && chan->output) return chan->fd; } return -1; @@ -604,25 +652,23 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, int err; char c; - list_for_each_safe(ele, next, chans) { + list_for_each_safe(ele, next, chans){ chan = list_entry(ele, struct chan, list); - if (!chan->input || (chan->ops->read == NULL)) - continue; + if(!chan->input || (chan->ops->read == NULL)) continue; do { if (tty && !tty_buffer_request_room(tty, 1)) { schedule_delayed_work(task, 1); goto out; } err = chan->ops->read(chan->fd, &c, chan->data); - if (err > 0) + if(err > 0) tty_receive_char(tty, c); - } while (err > 0); + } while(err > 0); - if (err == 0) - reactivate_fd(chan->fd, irq); - if (err == -EIO) { - if (chan->primary) { - if (tty != NULL) + if(err == 0) reactivate_fd(chan->fd, irq); + if(err == -EIO){ + if(chan->primary){ + if(tty != NULL) tty_hangup(tty); close_chan(chans, 1); return; @@ -631,6 +677,5 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, } } out: - if (tty) - tty_flip_buffer_push(tty); + if(tty) tty_flip_buffer_push(tty); } diff --git a/trunk/arch/um/drivers/chan_user.c b/trunk/arch/um/drivers/chan_user.c index b88e93b3a39f..4d438f36ea2e 100644 --- a/trunk/arch/um/drivers/chan_user.c +++ b/trunk/arch/um/drivers/chan_user.c @@ -1,107 +1,51 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include #include +#include #include -#include -#include #include +#include +#include +#include +#include #include +#include +#include "kern_util.h" #include "chan_user.h" -#include "os.h" -#include "um_malloc.h" #include "user.h" - -void generic_close(int fd, void *unused) -{ - close(fd); -} - -int generic_read(int fd, char *c_out, void *unused) -{ - int n; - - n = read(fd, c_out, sizeof(*c_out)); - if (n > 0) - return n; - else if (errno == EAGAIN) - return 0; - else if (n == 0) - return -EIO; - return -errno; -} - -/* XXX Trivial wrapper around write */ - -int generic_write(int fd, const char *buf, int n, void *unused) -{ - int err; - - err = write(fd, buf, n); - if (err > 0) - return err; - else if (errno == EAGAIN) - return 0; - else if (err == 0) - return -EIO; - return -errno; -} - -int generic_window_size(int fd, void *unused, unsigned short *rows_out, - unsigned short *cols_out) -{ - struct winsize size; - int ret; - - if (ioctl(fd, TIOCGWINSZ, &size) < 0) - return -errno; - - ret = ((*rows_out != size.ws_row) || (*cols_out != size.ws_col)); - - *rows_out = size.ws_row; - *cols_out = size.ws_col; - - return ret; -} - -void generic_free(void *data) -{ - kfree(data); -} +#include "os.h" +#include "choose-mode.h" +#include "mode.h" int generic_console_write(int fd, const char *buf, int n) { struct termios save, new; int err; - if (isatty(fd)) { + if(isatty(fd)){ CATCH_EINTR(err = tcgetattr(fd, &save)); if (err) goto error; new = save; - /* - * The terminal becomes a bit less raw, to handle \n also as + /* The terminal becomes a bit less raw, to handle \n also as * "Carriage Return", not only as "New Line". Otherwise, the new - * line won't start at the first column. - */ + * line won't start at the first column.*/ new.c_oflag |= OPOST; CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new)); if (err) goto error; } err = generic_write(fd, buf, n, NULL); - /* - * Restore raw mode, in any case; we *must* ignore any error apart - * EINTR, except for debug. - */ - if (isatty(fd)) + /* Restore raw mode, in any case; we *must* ignore any error apart + * EINTR, except for debug.*/ + if(isatty(fd)) CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); - return err; + return(err); error: - return -errno; + return(-errno); } /* @@ -138,73 +82,62 @@ static int winch_thread(void *arg) struct winch_data *data = arg; sigset_t sigs; int pty_fd, pipe_fd; - int count; + int count, err; char c = 1; pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; - count = write(pipe_fd, &c, sizeof(c)); - if (count != sizeof(c)) - printk(UM_KERN_ERR "winch_thread : failed to write " - "synchronization byte, err = %d\n", -count); + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("winch_thread : failed to write synchronization " + "byte, err = %d\n", -count); - /* - * We are not using SIG_IGN on purpose, so don't fix it as I thought to + /* We are not using SIG_IGN on purpose, so don't fix it as I thought to * do! If using SIG_IGN, the sigsuspend() call below would not stop on - * SIGWINCH. - */ + * SIGWINCH. */ signal(SIGWINCH, winch_handler); sigfillset(&sigs); /* Block all signals possible. */ - if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) { - printk(UM_KERN_ERR "winch_thread : sigprocmask failed, " - "errno = %d\n", errno); + if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ + printk("winch_thread : sigprocmask failed, errno = %d\n", + errno); exit(1); } /* In sigsuspend(), block anything else than SIGWINCH. */ sigdelset(&sigs, SIGWINCH); - if (setsid() < 0) { - printk(UM_KERN_ERR "winch_thread : setsid failed, errno = %d\n", - errno); - exit(1); - } - - if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) { - printk(UM_KERN_ERR "winch_thread : TIOCSCTTY failed on " - "fd %d err = %d\n", pty_fd, errno); + if(setsid() < 0){ + printk("winch_thread : setsid failed, errno = %d\n", errno); exit(1); } - if (tcsetpgrp(pty_fd, os_getpid()) < 0) { - printk(UM_KERN_ERR "winch_thread : tcsetpgrp failed on " - "fd %d err = %d\n", pty_fd, errno); + err = os_new_tty_pgrp(pty_fd, os_getpid()); + if(err < 0){ + printk("winch_thread : new_tty_pgrp failed on fd %d, " + "err = %d\n", pty_fd, -err); exit(1); } - /* - * These are synchronization calls between various UML threads on the + /* These are synchronization calls between various UML threads on the * host - since they are not different kernel threads, we cannot use * kernel semaphores. We don't use SysV semaphores because they are - * persistent. - */ - count = read(pipe_fd, &c, sizeof(c)); - if (count != sizeof(c)) - printk(UM_KERN_ERR "winch_thread : failed to read " - "synchronization byte, err = %d\n", errno); - - while(1) { - /* - * This will be interrupted by SIGWINCH only, since + * persistent. */ + count = os_read_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("winch_thread : failed to read synchronization byte, " + "err = %d\n", -count); + + while(1){ + /* This will be interrupted by SIGWINCH only, since * other signals are blocked. */ sigsuspend(&sigs); - count = write(pipe_fd, &c, sizeof(c)); - if (count != sizeof(c)) - printk(UM_KERN_ERR "winch_thread : write failed, " - "err = %d\n", errno); + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("winch_thread : write failed, err = %d\n", + -count); } } @@ -216,49 +149,44 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, char c; err = os_pipe(fds, 1, 1); - if (err < 0) { - printk(UM_KERN_ERR "winch_tramp : os_pipe failed, err = %d\n", - -err); + if(err < 0){ + printk("winch_tramp : os_pipe failed, err = %d\n", -err); goto out; } data = ((struct winch_data) { .pty_fd = fd, .pipe_fd = fds[1] } ); - /* - * CLONE_FILES so this thread doesn't hold open files which are open + /* CLONE_FILES so this thread doesn't hold open files which are open * now, but later closed in a different thread. This is a * problem with /dev/net/tun, which if held open by this * thread, prevents the TUN/TAP device from being reused. */ err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out); - if (err < 0) { - printk(UM_KERN_ERR "fork of winch_thread failed - errno = %d\n", - -err); + if(err < 0){ + printk("fork of winch_thread failed - errno = %d\n", -err); goto out_close; } *fd_out = fds[0]; - n = read(fds[0], &c, sizeof(c)); - if (n != sizeof(c)) { - printk(UM_KERN_ERR "winch_tramp : failed to read " - "synchronization byte\n"); - printk(UM_KERN_ERR "read failed, err = %d\n", errno); - printk(UM_KERN_ERR "fd %d will not support SIGWINCH\n", fd); - err = -EINVAL; + n = os_read_file(fds[0], &c, sizeof(c)); + if(n != sizeof(c)){ + printk("winch_tramp : failed to read synchronization byte\n"); + printk("read failed, err = %d\n", -n); + printk("fd %d will not support SIGWINCH\n", fd); + err = -EINVAL; goto out_close; } if (os_set_fd_block(*fd_out, 0)) { - printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd " - "non-blocking.\n"); + printk("winch_tramp: failed to set thread_fd non-blocking.\n"); goto out_close; } return err; out_close: - close(fds[1]); - close(fds[0]); + os_close_file(fds[1]); + os_close_file(fds[0]); out: return err; } @@ -269,20 +197,21 @@ void register_winch(int fd, struct tty_struct *tty) int pid, thread, count, thread_fd = -1; char c = 1; - if (!isatty(fd)) + if(!isatty(fd)) return; pid = tcgetpgrp(fd); - if (!is_skas_winch(pid, fd, tty) && (pid == -1)) { + if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) && + (pid == -1)) { thread = winch_tramp(fd, tty, &thread_fd, &stack); if (thread < 0) return; register_winch_irq(thread_fd, fd, thread, tty, stack); - count = write(thread_fd, &c, sizeof(c)); - if (count != sizeof(c)) - printk(UM_KERN_ERR "register_winch : failed to write " - "synchronization byte, err = %d\n", errno); + count = os_write_file(thread_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("register_winch : failed to write " + "synchronization byte, err = %d\n", -count); } } diff --git a/trunk/arch/um/drivers/cow_user.c b/trunk/arch/um/drivers/cow_user.c index 93f227a25ba4..0ec4052db9c5 100644 --- a/trunk/arch/um/drivers/cow_user.c +++ b/trunk/arch/um/drivers/cow_user.c @@ -1,18 +1,17 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) - * Licensed under the GPL - */ - -/* - * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines +#include +#include +#include +/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines * that. */ #include #include -#include -#include -#include -#include +#include +#include +#include + +#include "os.h" + #include "cow.h" #include "cow_sys.h" @@ -29,8 +28,7 @@ struct cow_header_v1 { __s32 sectorsize; } __attribute__((packed)); -/* - * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in +/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in * case other systems have different values for MAXPATHLEN. * * The same must hold for V2 - we want file format compatibility, not anything @@ -48,8 +46,7 @@ struct cow_header_v2 { __s32 sectorsize; } __attribute__((packed)); -/* - * Changes from V2 - +/* Changes from V2 - * PATH_LEN_V3 as described above * Explicitly specify field bit lengths for systems with different * lengths for the usual C types. Not sure whether char or @@ -73,8 +70,7 @@ struct cow_header_v2 { * Fixed (finally!) the rounding bug */ -/* - * Until Dec2005, __attribute__((packed)) was left out from the below +/* Until Dec2005, __attribute__((packed)) was left out from the below * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to * align size to 8-byte alignment. This shifted all fields above (no padding * was present on 32-bit, no other padding was added). @@ -126,7 +122,7 @@ void cow_sizes(int version, __u64 size, int sectorsize, int align, int bitmap_offset, unsigned long *bitmap_len_out, int *data_offset_out) { - if (version < 3) { + if(version < 3){ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); *data_offset_out = bitmap_offset + *bitmap_len_out; @@ -148,46 +144,46 @@ static int absolutize(char *to, int size, char *from) char save_cwd[256], *slash; int remaining; - if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) { + if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { cow_printf("absolutize : unable to get cwd - errno = %d\n", errno); - return -1; + return(-1); } slash = strrchr(from, '/'); - if (slash != NULL) { + if(slash != NULL){ *slash = '\0'; - if (chdir(from)) { + if(chdir(from)){ *slash = '/'; cow_printf("absolutize : Can't cd to '%s' - " "errno = %d\n", from, errno); - return -1; + return(-1); } *slash = '/'; - if (getcwd(to, size) == NULL) { + if(getcwd(to, size) == NULL){ cow_printf("absolutize : unable to get cwd of '%s' - " "errno = %d\n", from, errno); - return -1; + return(-1); } remaining = size - strlen(to); - if (strlen(slash) + 1 > remaining) { + if(strlen(slash) + 1 > remaining){ cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); - return -1; + return(-1); } strcat(to, slash); } else { - if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) { + if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); - return -1; + return(-1); } strcpy(to, save_cwd); strcat(to, "/"); strcat(to, from); } chdir(save_cwd); - return 0; + return(0); } int write_cow_header(char *cow_file, int fd, char *backing_file, @@ -198,23 +194,22 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, int err; err = cow_seek_file(fd, 0); - if (err < 0) { + if(err < 0){ cow_printf("write_cow_header - lseek failed, err = %d\n", -err); goto out; } err = -ENOMEM; header = cow_malloc(sizeof(*header)); - if (header == NULL) { - cow_printf("write_cow_header - failed to allocate COW V3 " - "header\n"); + if(header == NULL){ + cow_printf("write_cow_header - failed to allocate COW V3 header\n"); goto out; } header->magic = htonl(COW_MAGIC); header->version = htonl(COW_VERSION); err = -EINVAL; - if (strlen(backing_file) > sizeof(header->backing_file) - 1) { + if(strlen(backing_file) > sizeof(header->backing_file) - 1){ /* Below, %zd is for a size_t value */ cow_printf("Backing file name \"%s\" is too long - names are " "limited to %zd characters\n", backing_file, @@ -222,12 +217,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, goto out_free; } - if (absolutize(header->backing_file, sizeof(header->backing_file), + if(absolutize(header->backing_file, sizeof(header->backing_file), backing_file)) goto out_free; err = os_file_modtime(header->backing_file, &modtime); - if (err < 0) { + if(err < 0){ cow_printf("write_cow_header - backing file '%s' mtime " "request failed, err = %d\n", header->backing_file, -err); @@ -235,7 +230,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, } err = cow_file_size(header->backing_file, size); - if (err < 0) { + if(err < 0){ cow_printf("write_cow_header - couldn't get size of " "backing file '%s', err = %d\n", header->backing_file, -err); @@ -249,7 +244,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, header->cow_format = COW_BITMAP; err = cow_write_file(fd, header, sizeof(*header)); - if (err != sizeof(*header)) { + if(err != sizeof(*header)){ cow_printf("write_cow_header - write of header to " "new COW file '%s' failed, err = %d\n", cow_file, -err); @@ -259,14 +254,14 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, out_free: cow_free(header); out: - return err; + return(err); } int file_reader(__u64 offset, char *buf, int len, void *arg) { int fd = *((int *) arg); - return pread(fd, buf, len, offset); + return(pread(fd, buf, len, offset)); } /* XXX Need to sanity-check the values read from the header */ @@ -283,29 +278,31 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, unsigned long version, magic; header = cow_malloc(sizeof(*header)); - if (header == NULL) { + if(header == NULL){ cow_printf("read_cow_header - Failed to allocate header\n"); - return -ENOMEM; + return(-ENOMEM); } err = -EINVAL; n = (*reader)(0, (char *) header, sizeof(*header), arg); - if (n < offsetof(typeof(header->v1), backing_file)) { + if(n < offsetof(typeof(header->v1), backing_file)){ cow_printf("read_cow_header - short header\n"); goto out; } magic = header->v1.magic; - if (magic == COW_MAGIC) + if(magic == COW_MAGIC) { version = header->v1.version; - else if (magic == ntohl(COW_MAGIC)) + } + else if(magic == ntohl(COW_MAGIC)){ version = ntohl(header->v1.version); + } /* No error printed because the non-COW case comes through here */ else goto out; *version_out = version; - if (version == 1) { - if (n < sizeof(header->v1)) { + if(version == 1){ + if(n < sizeof(header->v1)){ cow_printf("read_cow_header - failed to read V1 " "header\n"); goto out; @@ -317,8 +314,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, *align_out = *sectorsize_out; file = header->v1.backing_file; } - else if (version == 2) { - if (n < sizeof(header->v2)) { + else if(version == 2){ + if(n < sizeof(header->v2)){ cow_printf("read_cow_header - failed to read V2 " "header\n"); goto out; @@ -331,8 +328,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, file = header->v2.backing_file; } /* This is very subtle - see above at union cow_header definition */ - else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) { - if (n < sizeof(header->v3)) { + else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){ + if(n < sizeof(header->v3)){ cow_printf("read_cow_header - failed to read V3 " "header\n"); goto out; @@ -348,18 +345,17 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); file = header->v3.backing_file; } - else if (version == 3) { + else if(version == 3){ cow_printf("read_cow_header - broken V3 file with" " 64-bit layout - recovering content.\n"); - if (n < sizeof(header->v3_b)) { + if(n < sizeof(header->v3_b)){ cow_printf("read_cow_header - failed to read V3 " "header\n"); goto out; } - /* - * this was used until Dec2005 - 64bits are needed to represent + /* this was used until Dec2005 - 64bits are needed to represent * 2038+. I.e. we can safely do this truncating cast. * * Additionally, we must use ntohl() instead of ntohll(), since @@ -385,7 +381,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, } err = -ENOMEM; *backing_file_out = cow_strdup(file); - if (*backing_file_out == NULL) { + if(*backing_file_out == NULL){ cow_printf("read_cow_header - failed to allocate backing " "file\n"); goto out; @@ -393,7 +389,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, err = 0; out: cow_free(header); - return err; + return(err); } int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, @@ -406,7 +402,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, err = write_cow_header(cow_file, fd, backing_file, sectorsize, alignment, &size); - if (err) + if(err) goto out; *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); @@ -415,18 +411,17 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, offset = *data_offset_out + size - sizeof(zero); err = cow_seek_file(fd, offset); - if (err < 0) { + if(err < 0){ cow_printf("cow bitmap lseek failed : err = %d\n", -err); goto out; } - /* - * does not really matter how much we write it is just to set EOF + /* does not really matter how much we write it is just to set EOF * this also sets the entire COW bitmap * to zero without having to allocate it */ err = cow_write_file(fd, &zero, sizeof(zero)); - if (err != sizeof(zero)) { + if(err != sizeof(zero)){ cow_printf("Write of bitmap to new COW file '%s' failed, " "err = %d\n", cow_file, -err); if (err >= 0) @@ -434,7 +429,15 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, goto out; } - return 0; + return(0); + out: - return err; + return(err); } + +/* + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/daemon.h b/trunk/arch/um/drivers/daemon.h index 6e0e891f8a00..3bc3cf6b94aa 100644 --- a/trunk/arch/um/drivers/daemon.h +++ b/trunk/arch/um/drivers/daemon.h @@ -1,11 +1,8 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#ifndef __DAEMON_H__ -#define __DAEMON_H__ - #include "net_user.h" #define SWITCH_VERSION 3 @@ -23,7 +20,16 @@ struct daemon_data { extern const struct net_user_info daemon_user_info; -extern int daemon_user_write(int fd, void *buf, int len, +extern int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri); -#endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/daemon_kern.c b/trunk/arch/um/drivers/daemon_kern.c index d53ff52bb404..adeece11e596 100644 --- a/trunk/arch/um/drivers/daemon_kern.c +++ b/trunk/arch/um/drivers/daemon_kern.c @@ -1,14 +1,16 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ +#include "linux/kernel.h" #include "linux/init.h" -#include +#include "linux/netdevice.h" +#include "linux/etherdevice.h" #include "net_kern.h" +#include "net_user.h" #include "daemon.h" struct daemon_init { @@ -34,21 +36,25 @@ static void daemon_init(struct net_device *dev, void *data) dpri->data_addr = NULL; dpri->local_addr = NULL; - printk("daemon backend (uml_switch version %d) - %s:%s", + printk("daemon backend (uml_switch version %d) - %s:%s", SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); printk("\n"); } -static int daemon_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int daemon_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return net_recvfrom(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) return(-ENOMEM); + return(net_recvfrom(fd, skb_mac_header(*skb), + (*skb)->dev->mtu + ETH_HEADER_OTHER)); } -static int daemon_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int daemon_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return daemon_user_write(fd, skb->data, skb->len, - (struct daemon_data *) &lp->user); + return(daemon_user_write(fd, (*skb)->data, (*skb)->len, + (struct daemon_data *) &lp->user)); } static const struct net_kern_info daemon_kern_info = { @@ -66,14 +72,14 @@ static int daemon_setup(char *str, char **mac_out, void *data) *init = ((struct daemon_init) { .sock_type = "unix", .ctl_sock = "/tmp/uml.ctl" }); - + remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, NULL); - if (remain != NULL) + if(remain != NULL) printk(KERN_WARNING "daemon_setup : Ignoring data socket " "specification\n"); - - return 1; + + return(1); } static struct transport daemon_transport = { diff --git a/trunk/arch/um/drivers/daemon_user.c b/trunk/arch/um/drivers/daemon_user.c index f23c109a055c..8d2008f06682 100644 --- a/trunk/arch/um/drivers/daemon_user.c +++ b/trunk/arch/um/drivers/daemon_user.c @@ -1,23 +1,24 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ -#include -#include #include -#include +#include +#include #include -#include #include -#include "daemon.h" +#include #include "net_user.h" +#include "daemon.h" +#include "kern_util.h" +#include "user.h" #include "os.h" #include "um_malloc.h" -#include "user.h" + +#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) enum request_type { REQ_NEW_CONTROL }; @@ -35,9 +36,8 @@ static struct sockaddr_un *new_addr(void *name, int len) struct sockaddr_un *sun; sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); - if (sun == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " - "failed\n"); + if(sun == NULL){ + printk("new_addr: allocation of sockaddr_un failed\n"); return NULL; } sun->sun_family = AF_UNIX; @@ -54,39 +54,38 @@ static int connect_to_switch(struct daemon_data *pri) int fd, n, err; pri->control = socket(AF_UNIX, SOCK_STREAM, 0); - if (pri->control < 0) { + if(pri->control < 0){ err = -errno; - printk(UM_KERN_ERR "daemon_open : control socket failed, " - "errno = %d\n", -err); + printk("daemon_open : control socket failed, errno = %d\n", + -err); return err; } - if (connect(pri->control, (struct sockaddr *) ctl_addr, - sizeof(*ctl_addr)) < 0) { + if(connect(pri->control, (struct sockaddr *) ctl_addr, + sizeof(*ctl_addr)) < 0){ err = -errno; - printk(UM_KERN_ERR "daemon_open : control connect failed, " - "errno = %d\n", -err); + printk("daemon_open : control connect failed, errno = %d\n", + -err); goto out; } fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { + if(fd < 0){ err = -errno; - printk(UM_KERN_ERR "daemon_open : data socket failed, " - "errno = %d\n", -err); + printk("daemon_open : data socket failed, errno = %d\n", + -err); goto out; } - if (bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0) { + if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ err = -errno; - printk(UM_KERN_ERR "daemon_open : data bind failed, " - "errno = %d\n", -err); + printk("daemon_open : data bind failed, errno = %d\n", + -err); goto out_close; } sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); - if (sun == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " - "failed\n"); + if(sun == NULL){ + printk("new_addr: allocation of sockaddr_un failed\n"); err = -ENOMEM; goto out_close; } @@ -95,18 +94,18 @@ static int connect_to_switch(struct daemon_data *pri) req.version = SWITCH_VERSION; req.type = REQ_NEW_CONTROL; req.sock = *local_addr; - n = write(pri->control, &req, sizeof(req)); - if (n != sizeof(req)) { - printk(UM_KERN_ERR "daemon_open : control setup request " - "failed, err = %d\n", -errno); + n = os_write_file(pri->control, &req, sizeof(req)); + if(n != sizeof(req)){ + printk("daemon_open : control setup request failed, err = %d\n", + -n); err = -ENOTCONN; goto out_free; } - n = read(pri->control, sun, sizeof(*sun)); - if (n != sizeof(*sun)) { - printk(UM_KERN_ERR "daemon_open : read of data socket failed, " - "err = %d\n", -errno); + n = os_read_file(pri->control, sun, sizeof(*sun)); + if(n != sizeof(*sun)){ + printk("daemon_open : read of data socket failed, err = %d\n", + -n); err = -ENOTCONN; goto out_free; } @@ -117,9 +116,9 @@ static int connect_to_switch(struct daemon_data *pri) out_free: kfree(sun); out_close: - close(fd); + os_close_file(fd); out: - close(pri->control); + os_close_file(pri->control); return err; } @@ -133,8 +132,8 @@ static int daemon_user_init(void *data, void *dev) int usecs; } name; - if (!strcmp(pri->sock_type, "unix")) - pri->ctl_addr = new_addr(pri->ctl_sock, + if(!strcmp(pri->sock_type, "unix")) + pri->ctl_addr = new_addr(pri->ctl_sock, strlen(pri->ctl_sock) + 1); name.zero = 0; name.pid = os_getpid(); @@ -143,7 +142,7 @@ static int daemon_user_init(void *data, void *dev) pri->local_addr = new_addr(&name, sizeof(name)); pri->dev = dev; pri->fd = connect_to_switch(pri); - if (pri->fd < 0) { + if(pri->fd < 0){ kfree(pri->local_addr); pri->local_addr = NULL; return pri->fd; @@ -162,9 +161,9 @@ static void daemon_remove(void *data) { struct daemon_data *pri = data; - close(pri->fd); + os_close_file(pri->fd); pri->fd = -1; - close(pri->control); + os_close_file(pri->control); pri->control = -1; kfree(pri->data_addr); @@ -182,13 +181,18 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); } +static int daemon_set_mtu(int mtu, void *data) +{ + return mtu; +} + const struct net_user_info daemon_user_info = { .init = daemon_user_init, .open = daemon_open, .close = NULL, .remove = daemon_remove, + .set_mtu = daemon_set_mtu, .add_address = NULL, .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, + .max_packet = MAX_PACKET - ETH_HEADER_OTHER }; diff --git a/trunk/arch/um/drivers/fd.c b/trunk/arch/um/drivers/fd.c index 0a2bb5b64b82..39c01ffd45c9 100644 --- a/trunk/arch/um/drivers/fd.c +++ b/trunk/arch/um/drivers/fd.c @@ -1,18 +1,17 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #include #include #include -#include #include +#include +#include "user.h" #include "chan_user.h" -#include "kern_constants.h" #include "os.h" #include "um_malloc.h" -#include "user.h" struct fd_chan { int fd; @@ -27,26 +26,22 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts) char *end; int n; - if (*str != ':') { - printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a " - "file descriptor\n"); - return NULL; + if(*str != ':'){ + printk("fd_init : channel type 'fd' must specify a file " + "descriptor\n"); + return(NULL); } str++; n = strtoul(str, &end, 0); - if ((*end != '\0') || (end == str)) { - printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor " - "'%s'\n", str); - return NULL; + if((*end != '\0') || (end == str)){ + printk("fd_init : couldn't parse file descriptor '%s'\n", str); + return(NULL); } - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if (data == NULL) - return NULL; - + if(data == NULL) return(NULL); *data = ((struct fd_chan) { .fd = n, .raw = opts->raw }); - return data; + return(data); } static int fd_open(int input, int output, int primary, void *d, char **dev_out) @@ -54,18 +49,18 @@ static int fd_open(int input, int output, int primary, void *d, char **dev_out) struct fd_chan *data = d; int err; - if (data->raw && isatty(data->fd)) { + if(data->raw && isatty(data->fd)){ CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); - if (err) - return err; + if(err) + return(err); err = raw(data->fd); - if (err) - return err; + if(err) + return(err); } sprintf(data->str, "%d", data->fd); *dev_out = data->str; - return data->fd; + return(data->fd); } static void fd_close(int fd, void *d) @@ -73,14 +68,13 @@ static void fd_close(int fd, void *d) struct fd_chan *data = d; int err; - if (!data->raw || !isatty(fd)) - return; - - CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); - if (err) - printk(UM_KERN_ERR "Failed to restore terminal state - " - "errno = %d\n", -err); - data->raw = 0; + if(data->raw && isatty(fd)){ + CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); + if(err) + printk("Failed to restore terminal state - " + "errno = %d\n", -err); + data->raw = 0; + } } const struct chan_ops fd_ops = { @@ -95,3 +89,14 @@ const struct chan_ops fd_ops = { .free = generic_free, .winch = 1, }; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/harddog_kern.c b/trunk/arch/um/drivers/harddog_kern.c index a9ad4bd6d953..55601687b3bc 100644 --- a/trunk/arch/um/drivers/harddog_kern.c +++ b/trunk/arch/um/drivers/harddog_kern.c @@ -69,7 +69,7 @@ static int harddog_open(struct inode *inode, struct file *file) spin_lock(&lock); if(timer_alive) goto err; -#ifdef CONFIG_WATCHDOG_NOWAYOUT +#ifdef CONFIG_HARDDOG_NOWAYOUT __module_get(THIS_MODULE); #endif diff --git a/trunk/arch/um/drivers/harddog_user.c b/trunk/arch/um/drivers/harddog_user.c index b56f8e0196a9..1171790f742c 100644 --- a/trunk/arch/um/drivers/harddog_user.c +++ b/trunk/arch/um/drivers/harddog_user.c @@ -1,13 +1,16 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #include #include #include -#include "os.h" #include "user.h" +#include "mconsole.h" +#include "os.h" +#include "choose-mode.h" +#include "mode.h" struct dog_data { int stdin; @@ -22,10 +25,10 @@ static void pre_exec(void *d) dup2(data->stdin, 0); dup2(data->stdout, 1); dup2(data->stdout, 2); - close(data->stdin); - close(data->stdout); - close(data->close_me[0]); - close(data->close_me[1]); + os_close_file(data->stdin); + os_close_file(data->stdout); + os_close_file(data->close_me[0]); + os_close_file(data->close_me[1]); } int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) @@ -39,13 +42,13 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) char **args = NULL; err = os_pipe(in_fds, 1, 0); - if (err < 0) { + if(err < 0){ printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out; } err = os_pipe(out_fds, 1, 0); - if (err < 0) { + if(err < 0){ printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out_close_in; } @@ -55,37 +58,37 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) data.close_me[0] = out_fds[1]; data.close_me[1] = in_fds[0]; - if (sock != NULL) { + if(sock != NULL){ mconsole_args[2] = sock; args = mconsole_args; } else { /* XXX The os_getpid() is not SMP correct */ - sprintf(pid_buf, "%d", os_getpid()); + sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); args = pid_args; } pid = run_helper(pre_exec, &data, args); - close(out_fds[0]); - close(in_fds[1]); + os_close_file(out_fds[0]); + os_close_file(in_fds[1]); - if (pid < 0) { + if(pid < 0){ err = -pid; printk("harddog_open - run_helper failed, errno = %d\n", -err); goto out_close_out; } - n = read(in_fds[0], &c, sizeof(c)); - if (n == 0) { + n = os_read_file(in_fds[0], &c, sizeof(c)); + if(n == 0){ printk("harddog_open - EOF on watchdog pipe\n"); helper_wait(pid); err = -EIO; goto out_close_out; } - else if (n < 0) { + else if(n < 0){ printk("harddog_open - read of watchdog pipe failed, " - "err = %d\n", errno); + "err = %d\n", -n); helper_wait(pid); err = n; goto out_close_out; @@ -95,19 +98,19 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) return 0; out_close_in: - close(in_fds[0]); - close(in_fds[1]); + os_close_file(in_fds[0]); + os_close_file(in_fds[1]); out_close_out: - close(out_fds[0]); - close(out_fds[1]); + os_close_file(out_fds[0]); + os_close_file(out_fds[1]); out: return err; } void stop_watchdog(int in_fd, int out_fd) { - close(in_fd); - close(out_fd); + os_close_file(in_fd); + os_close_file(out_fd); } int ping_watchdog(int fd) @@ -115,11 +118,10 @@ int ping_watchdog(int fd) int n; char c = '\n'; - n = write(fd, &c, sizeof(c)); - if (n != sizeof(c)) { - printk("ping_watchdog - write failed, ret = %d, err = %d\n", - n, errno); - if (n < 0) + n = os_write_file(fd, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("ping_watchdog - write failed, err = %d\n", -n); + if(n < 0) return n; return -EIO; } diff --git a/trunk/arch/um/drivers/hostaudio_kern.c b/trunk/arch/um/drivers/hostaudio_kern.c index ff1b22b69e9c..10e08a8c17c3 100644 --- a/trunk/arch/um/drivers/hostaudio_kern.c +++ b/trunk/arch/um/drivers/hostaudio_kern.c @@ -1,14 +1,16 @@ -/* - * Copyright (C) 2002 Steve Schmidtke +/* + * Copyright (C) 2002 Steve Schmidtke * Licensed under the GPL */ -#include "linux/fs.h" #include "linux/module.h" +#include "linux/init.h" #include "linux/slab.h" +#include "linux/fs.h" #include "linux/sound.h" #include "linux/soundcard.h" #include "asm/uaccess.h" +#include "kern_util.h" #include "init.h" #include "os.h" @@ -23,8 +25,7 @@ struct hostmixer_state { #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -/* - * Changed either at boot time or module load time. At boot, this is +/* Changed either at boot time or module load time. At boot, this is * single-threaded; at module load, multiple modules would each have * their own copy of these variables. */ @@ -43,7 +44,7 @@ static char *mixer = HOSTAUDIO_DEV_MIXER; static int set_dsp(char *name, int *add) { dsp = name; - return 0; + return(0); } __uml_setup("dsp=", set_dsp, "dsp=\n" DSP_HELP); @@ -51,7 +52,7 @@ __uml_setup("dsp=", set_dsp, "dsp=\n" DSP_HELP); static int set_mixer(char *name, int *add) { mixer = name; - return 0; + return(0); } __uml_setup("mixer=", set_mixer, "mixer=\n" MIXER_HELP); @@ -76,23 +77,23 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer, int err; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count); + printk("hostaudio: read called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); - if (kbuf == NULL) - return -ENOMEM; + if(kbuf == NULL) + return(-ENOMEM); err = os_read_file(state->fd, kbuf, count); - if (err < 0) + if(err < 0) goto out; - if (copy_to_user(buffer, kbuf, err)) + if(copy_to_user(buffer, kbuf, err)) err = -EFAULT; out: kfree(kbuf); - return err; + return(err); } static ssize_t hostaudio_write(struct file *file, const char __user *buffer, @@ -103,40 +104,40 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer, int err; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count); + printk("hostaudio: write called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); - if (kbuf == NULL) - return -ENOMEM; + if(kbuf == NULL) + return(-ENOMEM); err = -EFAULT; - if (copy_from_user(kbuf, buffer, count)) + if(copy_from_user(kbuf, buffer, count)) goto out; err = os_write_file(state->fd, kbuf, count); - if (err < 0) + if(err < 0) goto out; *ppos += err; out: kfree(kbuf); - return err; + return(err); } -static unsigned int hostaudio_poll(struct file *file, +static unsigned int hostaudio_poll(struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n"); + printk("hostaudio: poll called (unimplemented)\n"); #endif - return mask; + return(mask); } -static int hostaudio_ioctl(struct inode *inode, struct file *file, +static int hostaudio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hostaudio_state *state = file->private_data; @@ -144,7 +145,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, int err; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd); + printk("hostaudio: ioctl called, cmd = %u\n", cmd); #endif switch(cmd){ case SNDCTL_DSP_SPEED: @@ -153,8 +154,8 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_CHANNELS: case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: - if (get_user(data, (int __user *) arg)) - return EFAULT; + if(get_user(data, (int __user *) arg)) + return(-EFAULT); break; default: break; @@ -169,14 +170,14 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_CHANNELS: case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: - if (put_user(data, (int __user *) arg)) - return -EFAULT; + if(put_user(data, (int __user *) arg)) + return(-EFAULT); break; default: break; } - return err; + return(err); } static int hostaudio_open(struct inode *inode, struct file *file) @@ -186,26 +187,24 @@ static int hostaudio_open(struct inode *inode, struct file *file) int ret; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); + printk("hostaudio: open called (host: %s)\n", dsp); #endif state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; + if(state == NULL) + return(-ENOMEM); - if (file->f_mode & FMODE_READ) - r = 1; - if (file->f_mode & FMODE_WRITE) - w = 1; + if(file->f_mode & FMODE_READ) r = 1; + if(file->f_mode & FMODE_WRITE) w = 1; ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); - if (ret < 0) { + if(ret < 0){ kfree(state); - return ret; + return(ret); } state->fd = ret; file->private_data = state; - return 0; + return(0); } static int hostaudio_release(struct inode *inode, struct file *file) @@ -213,26 +212,26 @@ static int hostaudio_release(struct inode *inode, struct file *file) struct hostaudio_state *state = file->private_data; #ifdef DEBUG - printk(KERN_DEBUG "hostaudio: release called\n"); + printk("hostaudio: release called\n"); #endif os_close_file(state->fd); kfree(state); - return 0; + return(0); } /* /dev/mixer file operations */ -static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, +static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk(KERN_DEBUG "hostmixer: ioctl called\n"); + printk("hostmixer: ioctl called\n"); #endif - return os_ioctl_generic(state->fd, cmd, arg); + return(os_ioctl_generic(state->fd, cmd, arg)); } static int hostmixer_open_mixdev(struct inode *inode, struct file *file) @@ -242,29 +241,26 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) int ret; #ifdef DEBUG - printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer); + printk("hostmixer: open called (host: %s)\n", mixer); #endif state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; + if(state == NULL) return(-ENOMEM); - if (file->f_mode & FMODE_READ) - r = 1; - if (file->f_mode & FMODE_WRITE) - w = 1; + if(file->f_mode & FMODE_READ) r = 1; + if(file->f_mode & FMODE_WRITE) w = 1; ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); - - if (ret < 0) { - printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " - "err = %d\n", dsp, -ret); + + if(ret < 0){ + printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", + dsp, -ret); kfree(state); - return ret; + return(ret); } file->private_data = state; - return 0; + return(0); } static int hostmixer_release(struct inode *inode, struct file *file) @@ -272,13 +268,13 @@ static int hostmixer_release(struct inode *inode, struct file *file) struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk(KERN_DEBUG "hostmixer: release called\n"); + printk("hostmixer: release called\n"); #endif os_close_file(state->fd); kfree(state); - return 0; + return(0); } /* kernel module operations */ @@ -318,13 +314,13 @@ static int __init hostaudio_init_module(void) dsp, mixer); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); - if (module_data.dev_audio < 0) { + if(module_data.dev_audio < 0){ printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); return -ENODEV; } module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); - if (module_data.dev_mixer < 0) { + if(module_data.dev_mixer < 0){ printk(KERN_ERR "hostmixer: couldn't register mixer " "device!\n"); unregister_sound_dsp(module_data.dev_audio); diff --git a/trunk/arch/um/drivers/line.c b/trunk/arch/um/drivers/line.c index 76fe0b0da996..3e0b68e297f2 100644 --- a/trunk/arch/um/drivers/line.c +++ b/trunk/arch/um/drivers/line.c @@ -1,14 +1,22 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/irqreturn.h" +#include "linux/kernel.h" +#include "linux/sched.h" +#include "linux/slab.h" +#include "linux/list.h" #include "linux/kd.h" +#include "linux/interrupt.h" +#include "asm/uaccess.h" #include "chan_kern.h" -#include "irq_kern.h" #include "irq_user.h" +#include "line.h" +#include "kern.h" +#include "kern_util.h" #include "os.h" +#include "irq_kern.h" #define LINE_BUFSIZE 4096 @@ -27,13 +35,12 @@ static void line_timer_cb(struct work_struct *work) { struct line *line = container_of(work, struct line, task.work); - if (!line->throttled) + if(!line->throttled) chan_interrupt(&line->chan_list, &line->task, line->tty, line->driver->read_irq); } -/* - * Returns the free space inside the ring buffer of this line. +/* Returns the free space inside the ring buffer of this line. * * Should be called while holding line->lock (this does not modify datas). */ @@ -100,12 +107,11 @@ static int buffer_data(struct line *line, const char *buf, int len) { int end, room; - if (line->buffer == NULL) { + if(line->buffer == NULL){ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); if (line->buffer == NULL) { - printk(KERN_ERR "buffer_data - atomic allocation " - "failed\n"); - return 0; + printk("buffer_data - atomic allocation failed\n"); + return(0); } line->head = line->buffer; line->tail = line->buffer; @@ -116,7 +122,7 @@ static int buffer_data(struct line *line, const char *buf, int len) end = line->buffer + LINE_BUFSIZE - line->tail; - if (len < end) { + if (len < end){ memcpy(line->tail, buf, len); line->tail += len; } @@ -156,10 +162,8 @@ static int flush_buffer(struct line *line) if (n < 0) return n; if (n == count) { - /* - * We have flushed from ->head to buffer end, now we - * must flush only from the beginning to ->tail. - */ + /* We have flushed from ->head to buffer end, now we + * must flush only from the beginning to ->tail.*/ line->head = line->buffer; } else { line->head += n; @@ -171,7 +175,7 @@ static int flush_buffer(struct line *line) n = write_chan(&line->chan_list, line->head, count, line->driver->write_irq); - if (n < 0) + if(n < 0) return n; line->head += n; @@ -185,18 +189,19 @@ void line_flush_buffer(struct tty_struct *tty) int err; /*XXX: copied from line_write, verify if it is correct!*/ - if (tty->stopped) + if(tty->stopped) return; spin_lock_irqsave(&line->lock, flags); err = flush_buffer(line); + /*if (err == 1) + err = 0;*/ spin_unlock_irqrestore(&line->lock, flags); + //return err; } -/* - * We map both ->flush_chars and ->put_char (which go in pair) onto - * ->flush_buffer and ->write. Hope it's not that bad. - */ +/* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer + * and ->write. Hope it's not that bad.*/ void line_flush_chars(struct tty_struct *tty) { line_flush_buffer(tty); @@ -211,15 +216,18 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) { struct line *line = tty->driver_data; unsigned long flags; - int n, ret = 0; + int n, err, ret = 0; - if (tty->stopped) + if(tty->stopped) return 0; spin_lock_irqsave(&line->lock, flags); - if (line->head != line->tail) + if (line->head != line->tail) { ret = buffer_data(line, buf, len); - else { + err = flush_buffer(line); + if (err <= 0 && (err != -EAGAIN || !ret)) + ret = err; + } else { n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if (n < 0) { @@ -249,17 +257,17 @@ static const struct { } tty_ioctls[] = { /* don't print these, they flood the log ... */ { TCGETS, NULL, "TCGETS" }, - { TCSETS, NULL, "TCSETS" }, - { TCSETSW, NULL, "TCSETSW" }, - { TCFLSH, NULL, "TCFLSH" }, - { TCSBRK, NULL, "TCSBRK" }, + { TCSETS, NULL, "TCSETS" }, + { TCSETSW, NULL, "TCSETSW" }, + { TCFLSH, NULL, "TCFLSH" }, + { TCSBRK, NULL, "TCSBRK" }, /* general tty stuff */ - { TCSETSF, KERN_DEBUG, "TCSETSF" }, - { TCGETA, KERN_DEBUG, "TCGETA" }, - { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, - { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, - { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, + { TCSETSF, KERN_DEBUG, "TCSETSF" }, + { TCGETA, KERN_DEBUG, "TCGETA" }, + { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, + { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, + { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, /* linux-specific ones */ { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, @@ -316,7 +324,12 @@ int line_ioctl(struct tty_struct *tty, struct file * file, for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) if (cmd == tty_ioctls[i].cmd) break; - if (i == ARRAY_SIZE(tty_ioctls)) { + if (i < ARRAY_SIZE(tty_ioctls)) { + if (NULL != tty_ioctls[i].level) + printk("%s%s: %s: ioctl %s called\n", + tty_ioctls[i].level, __FUNCTION__, + tty->name, tty_ioctls[i].name); + } else { printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", __FUNCTION__, tty->name, cmd); } @@ -342,12 +355,11 @@ void line_unthrottle(struct tty_struct *tty) chan_interrupt(&line->chan_list, &line->task, tty, line->driver->read_irq); - /* - * Maybe there is enough stuff pending that calling the interrupt + /* Maybe there is enough stuff pending that calling the interrupt * throttles us again. In this case, line->throttled will be 1 * again and we shouldn't turn the interrupt back on. */ - if (!line->throttled) + if(!line->throttled) reactivate_chan(&line->chan_list, line->driver->read_irq); } @@ -358,30 +370,27 @@ static irqreturn_t line_write_interrupt(int irq, void *data) struct tty_struct *tty = line->tty; int err; - /* - * Interrupts are disabled here because we registered the interrupt with - * IRQF_DISABLED (see line_setup_irq). - */ + /* Interrupts are disabled here because we registered the interrupt with + * IRQF_DISABLED (see line_setup_irq).*/ spin_lock(&line->lock); err = flush_buffer(line); if (err == 0) { return IRQ_NONE; - } else if (err < 0) { + } else if(err < 0) { line->head = line->buffer; line->tail = line->buffer; } spin_unlock(&line->lock); - if (tty == NULL) + if(tty == NULL) return IRQ_NONE; if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) (tty->ldisc.write_wakeup)(tty); - /* - * BLOCKING mode + /* BLOCKING mode * In blocking mode, everything sleeps on tty->write_wait. * Sleeping in the console driver would break non-blocking * writes. @@ -411,8 +420,7 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) return err; } -/* - * Normally, a driver like this can rely mostly on the tty layer +/* Normally, a driver like this can rely mostly on the tty layer * locking, particularly when it comes to the driver structure. * However, in this case, mconsole requests can come in "from the * side", and race with opens and closes. @@ -434,11 +442,11 @@ int line_open(struct line *lines, struct tty_struct *tty) int err = -ENODEV; spin_lock(&line->count_lock); - if (!line->valid) + if(!line->valid) goto out_unlock; err = 0; - if (tty->count > 1) + if(tty->count > 1) goto out_unlock; spin_unlock(&line->count_lock); @@ -452,7 +460,7 @@ int line_open(struct line *lines, struct tty_struct *tty) INIT_DELAYED_WORK(&line->task, line_timer_cb); - if (!line->sigio) { + if(!line->sigio){ chan_enable_winch(&line->chan_list, tty); line->sigio = 1; } @@ -473,21 +481,20 @@ void line_close(struct tty_struct *tty, struct file * filp) { struct line *line = tty->driver_data; - /* - * If line_open fails (and tty->driver_data is never set), + /* If line_open fails (and tty->driver_data is never set), * tty_open will call line_close. So just return in this case. */ - if (line == NULL) + if(line == NULL) return; /* We ignore the error anyway! */ flush_buffer(line); spin_lock(&line->count_lock); - if (!line->valid) + if(!line->valid) goto out_unlock; - if (tty->count > 1) + if(tty->count > 1) goto out_unlock; spin_unlock(&line->count_lock); @@ -495,10 +502,10 @@ void line_close(struct tty_struct *tty, struct file * filp) line->tty = NULL; tty->driver_data = NULL; - if (line->sigio) { + if(line->sigio){ unregister_winch(tty); line->sigio = 0; - } + } return; @@ -522,12 +529,12 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, spin_lock(&line->count_lock); - if (line->tty != NULL) { + if(line->tty != NULL){ *error_out = "Device is already open"; goto out; } - if (line->init_pri <= init_prio) { + if (line->init_pri <= init_prio){ line->init_pri = init_prio; if (!strcmp(init, "none")) line->valid = 0; @@ -542,8 +549,7 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, return err; } -/* - * Common setup code for both startup command line and mconsole initialization. +/* Common setup code for both startup command line and mconsole initialization. * @lines contains the array (of size @num) to modify; * @init is the setup string; * @error_out is an error string in the case of failure; @@ -555,16 +561,14 @@ int line_setup(struct line *lines, unsigned int num, char *init, int i, n, err; char *end; - if (*init == '=') { - /* - * We said con=/ssl= instead of con#=, so we are configuring all - * consoles at once. - */ + if(*init == '=') { + /* We said con=/ssl= instead of con#=, so we are configuring all + * consoles at once.*/ n = -1; } else { n = simple_strtoul(init, &end, 0); - if (*end != '=') { + if(*end != '='){ *error_out = "Couldn't parse device number"; return -EINVAL; } @@ -576,16 +580,16 @@ int line_setup(struct line *lines, unsigned int num, char *init, *error_out = "Device number out of range"; return -EINVAL; } - else if (n >= 0) { + else if (n >= 0){ err = setup_one_line(lines, n, init, INIT_ONE, error_out); - if (err) + if(err) return err; } else { - for(i = 0; i < num; i++) { + for(i = 0; i < num; i++){ err = setup_one_line(lines, i, init, INIT_ALL, error_out); - if (err) + if(err) return err; } } @@ -599,18 +603,18 @@ int line_config(struct line *lines, unsigned int num, char *str, char *new; int n; - if (*str == '=') { + if(*str == '='){ *error_out = "Can't configure all devices from mconsole"; return -EINVAL; } new = kstrdup(str, GFP_KERNEL); - if (new == NULL) { + if(new == NULL){ *error_out = "Failed to allocate memory"; return -ENOMEM; } n = line_setup(lines, num, new, error_out); - if (n < 0) + if(n < 0) return n; line = &lines[n]; @@ -625,12 +629,12 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, int dev, n = 0; dev = simple_strtoul(name, &end, 0); - if ((*end != '\0') || (end == name)) { + if((*end != '\0') || (end == name)){ *error_out = "line_get_config failed to parse device number"; return 0; } - if ((dev < 0) || (dev >= num)) { + if((dev < 0) || (dev >= num)){ *error_out = "device number out of range"; return 0; } @@ -638,9 +642,9 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, line = &lines[dev]; spin_lock(&line->count_lock); - if (!line->valid) + if(!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); - else if (line->tty == NULL) + else if(line->tty == NULL) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); spin_unlock(&line->count_lock); @@ -651,16 +655,16 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, int line_id(char **str, int *start_out, int *end_out) { char *end; - int n; + int n; n = simple_strtoul(*str, &end, 0); - if ((*end != '\0') || (end == *str)) - return -1; + if((*end != '\0') || (end == *str)) + return -1; - *str = end; - *start_out = n; - *end_out = n; - return n; + *str = end; + *start_out = n; + *end_out = n; + return n; } int line_remove(struct line *lines, unsigned int num, int n, char **error_out) @@ -670,7 +674,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) sprintf(config, "%d=none", n); err = line_setup(lines, num, config, error_out); - if (err >= 0) + if(err >= 0) err = 0; return err; } @@ -696,14 +700,14 @@ struct tty_driver *register_lines(struct line_driver *line_driver, tty_set_operations(driver, ops); if (tty_register_driver(driver)) { - printk(KERN_ERR "register_lines : can't register %s driver\n", - line_driver->name); + printk("%s: can't register %s driver\n", + __FUNCTION__,line_driver->name); put_tty_driver(driver); return NULL; } - for(i = 0; i < nlines; i++) { - if (!lines[i].valid) + for(i = 0; i < nlines; i++){ + if(!lines[i].valid) tty_unregister_device(driver, i); } @@ -720,20 +724,20 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) char *error; int i; - for(i = 0; i < nlines; i++) { + for(i = 0; i < nlines; i++){ line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); - if (line->init_str == NULL) + if(line->init_str == NULL) continue; line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if (line->init_str == NULL) - printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); + if(line->init_str == NULL) + printk("lines_init - kstrdup returned NULL\n"); - if (parse_chan_pair(line->init_str, line, i, opts, &error)) { - printk(KERN_ERR "parse_chan_pair failed for " - "device %d : %s\n", i, error); + if(parse_chan_pair(line->init_str, line, i, opts, &error)){ + printk("parse_chan_pair failed for device %d : %s\n", + i, error); line->valid = 0; } } @@ -771,14 +775,14 @@ static irqreturn_t winch_interrupt(int irq, void *data) int err; char c; - if (winch->fd != -1) { + if(winch->fd != -1){ err = generic_read(winch->fd, &c, NULL); - if (err < 0) { - if (err != -EAGAIN) { - printk(KERN_ERR "winch_interrupt : " - "read failed, errno = %d\n", -err); - printk(KERN_ERR "fd %d is losing SIGWINCH " - "support\n", winch->tty_fd); + if(err < 0){ + if(err != -EAGAIN){ + printk("winch_interrupt : read failed, " + "errno = %d\n", -err); + printk("fd %d is losing SIGWINCH support\n", + winch->tty_fd); free_winch(winch, 0); return IRQ_HANDLED; } @@ -793,7 +797,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) kill_pgrp(tty->pgrp, SIGWINCH, 1); } out: - if (winch->fd != -1) + if(winch->fd != -1) reactivate_fd(winch->fd, WINCH_IRQ); return IRQ_HANDLED; } @@ -805,7 +809,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, winch = kmalloc(sizeof(*winch), GFP_KERNEL); if (winch == NULL) { - printk(KERN_ERR "register_winch_irq - kmalloc failed\n"); + printk("register_winch_irq - kmalloc failed\n"); goto cleanup; } @@ -819,8 +823,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "winch", winch) < 0) { - printk(KERN_ERR "register_winch_irq - failed to register " - "IRQ\n"); + printk("register_winch_irq - failed to register IRQ\n"); goto out_free; } @@ -846,13 +849,13 @@ static void unregister_winch(struct tty_struct *tty) spin_lock(&winch_handler_lock); - list_for_each(ele, &winch_handlers) { + list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); - if (winch->tty == tty) { + if(winch->tty == tty){ free_winch(winch, 1); break; - } - } + } + } spin_unlock(&winch_handler_lock); } @@ -863,7 +866,7 @@ static void winch_cleanup(void) spin_lock(&winch_handler_lock); - list_for_each_safe(ele, next, &winch_handlers) { + list_for_each_safe(ele, next, &winch_handlers){ winch = list_entry(ele, struct winch, list); free_winch(winch, 1); } @@ -878,13 +881,13 @@ char *add_xterm_umid(char *base) int len; umid = get_umid(); - if (*umid == '\0') + if(*umid == '\0') return base; len = strlen(base) + strlen(" ()") + strlen(umid) + 1; title = kmalloc(len, GFP_KERNEL); - if (title == NULL) { - printk(KERN_ERR "Failed to allocate buffer for xterm title\n"); + if(title == NULL){ + printk("Failed to allocate buffer for xterm title\n"); return base; } diff --git a/trunk/arch/um/drivers/mcast.h b/trunk/arch/um/drivers/mcast.h index 6fa282e896be..bc56af9d3e53 100644 --- a/trunk/arch/um/drivers/mcast.h +++ b/trunk/arch/um/drivers/mcast.h @@ -1,11 +1,8 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#ifndef __DRIVERS_MCAST_H -#define __DRIVERS_MCAST_H - #include "net_user.h" struct mcast_data { @@ -21,4 +18,13 @@ extern const struct net_user_info mcast_user_info; extern int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri); -#endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/mcast_kern.c b/trunk/arch/um/drivers/mcast_kern.c index 822092f149be..e6b8e0dd72a8 100644 --- a/trunk/arch/um/drivers/mcast_kern.c +++ b/trunk/arch/um/drivers/mcast_kern.c @@ -1,20 +1,24 @@ /* * user-mode-linux networking multicast transport * Copyright (C) 2001 by Harald Welte - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * * Licensed under the GPL. */ +#include "linux/kernel.h" #include "linux/init.h" -#include -#include "mcast.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "linux/in.h" +#include "linux/inet.h" #include "net_kern.h" +#include "net_user.h" +#include "mcast.h" struct mcast_init { char *addr; @@ -35,20 +39,26 @@ static void mcast_init(struct net_device *dev, void *data) dpri->ttl = init->ttl; dpri->dev = dev; - printk("mcast backend multicast address: %s:%u, TTL:%u\n", + printk("mcast backend "); + printk("multicast address: %s:%u, TTL:%u ", dpri->addr, dpri->port, dpri->ttl); + + printk("\n"); } -static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return net_recvfrom(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) return(-ENOMEM); + return(net_recvfrom(fd, skb_mac_header(*skb), + (*skb)->dev->mtu + ETH_HEADER_OTHER)); } -static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int mcast_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return mcast_user_write(fd, skb->data, skb->len, - (struct mcast_data *) &lp->user); + return mcast_user_write(fd, (*skb)->data, (*skb)->len, + (struct mcast_data *) &lp->user); } static const struct net_kern_info mcast_kern_info = { @@ -71,34 +81,34 @@ int mcast_setup(char *str, char **mac_out, void *data) remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, NULL); - if (remain != NULL) { + if(remain != NULL){ printk(KERN_ERR "mcast_setup - Extra garbage on " "specification : '%s'\n", remain); - return 0; + return(0); } - - if (port_str != NULL) { + + if(port_str != NULL){ init->port = simple_strtoul(port_str, &last, 10); - if ((*last != '\0') || (last == port_str)) { - printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", + if((*last != '\0') || (last == port_str)){ + printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", port_str); - return 0; + return(0); } } - if (ttl_str != NULL) { + if(ttl_str != NULL){ init->ttl = simple_strtoul(ttl_str, &last, 10); - if ((*last != '\0') || (last == ttl_str)) { - printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", + if((*last != '\0') || (last == ttl_str)){ + printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", ttl_str); - return 0; + return(0); } } printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, init->port, init->ttl); - return 1; + return(1); } static struct transport mcast_transport = { diff --git a/trunk/arch/um/drivers/mcast_user.c b/trunk/arch/um/drivers/mcast_user.c index 5f647d7a7292..236a3dfc297d 100644 --- a/trunk/arch/um/drivers/mcast_user.c +++ b/trunk/arch/um/drivers/mcast_user.c @@ -1,10 +1,9 @@ /* * user-mode-linux networking multicast transport - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by Harald Welte * * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * @@ -12,22 +11,28 @@ * */ -#include #include +#include +#include +#include +#include #include -#include "mcast.h" #include "net_user.h" -#include "um_malloc.h" +#include "mcast.h" +#include "kern_util.h" #include "user.h" +#include "os.h" +#include "um_malloc.h" + +#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) static struct sockaddr_in *new_addr(char *addr, unsigned short port) { struct sockaddr_in *sin; sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); - if (sin == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " - "failed\n"); + if(sin == NULL){ + printk("new_addr: allocation of sockaddr_in failed\n"); return NULL; } sin->sin_family = AF_INET; @@ -66,17 +71,17 @@ static int mcast_open(void *data) fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { + if (fd < 0){ err = -errno; - printk(UM_KERN_ERR "mcast_open : data socket failed, " - "errno = %d\n", errno); + printk("mcast_open : data socket failed, errno = %d\n", + errno); goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { err = -errno; - printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " - "errno = %d\n", errno); + printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", + errno); goto out_close; } @@ -84,46 +89,45 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, sizeof(pri->ttl)) < 0) { err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " - "error = %d\n", errno); + printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", + errno); goto out_close; } /* set LOOP, so data does get fed back to local sockets */ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " - "error = %d\n", errno); + printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", + errno); goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { err = -errno; - printk(UM_KERN_ERR "mcast_open : data bind failed, " - "errno = %d\n", errno); + printk("mcast_open : data bind failed, errno = %d\n", errno); goto out_close; } /* subscribe to the multicast group */ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " - "error = %d\n", errno); - printk(UM_KERN_ERR "There appears not to be a multicast-" - "capable network interface on the host.\n"); - printk(UM_KERN_ERR "eth0 should be configured in order to use " - "the multicast transport.\n"); + printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", + errno); + printk("There appears not to be a multicast-capable network " + "interface on the host.\n"); + printk("eth0 should be configured in order to use the " + "multicast transport.\n"); goto out_close; } return fd; out_close: - close(fd); + os_close_file(fd); out: return err; } @@ -138,11 +142,11 @@ static void mcast_close(int fd, void *data) mreq.imr_interface.s_addr = 0; if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " - "error = %d\n", errno); + printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", + errno); } - close(fd); + os_close_file(fd); } int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) @@ -152,13 +156,18 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); } +static int mcast_set_mtu(int mtu, void *data) +{ + return mtu; +} + const struct net_user_info mcast_user_info = { .init = mcast_user_init, .open = mcast_open, .close = mcast_close, .remove = mcast_remove, + .set_mtu = mcast_set_mtu, .add_address = NULL, .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, + .max_packet = MAX_PACKET - ETH_HEADER_OTHER }; diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index 0f3c7d14a6e3..d87090507401 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -1,35 +1,44 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include "linux/console.h" +#include "linux/kernel.h" +#include "linux/slab.h" +#include "linux/init.h" +#include "linux/notifier.h" +#include "linux/reboot.h" +#include "linux/utsname.h" #include "linux/ctype.h" #include "linux/interrupt.h" -#include "linux/list.h" -#include "linux/mm.h" +#include "linux/sysrq.h" +#include "linux/workqueue.h" #include "linux/module.h" -#include "linux/notifier.h" -#include "linux/reboot.h" +#include "linux/file.h" +#include "linux/fs.h" +#include "linux/namei.h" #include "linux/proc_fs.h" -#include "linux/slab.h" #include "linux/syscalls.h" -#include "linux/utsname.h" -#include "linux/workqueue.h" +#include "linux/list.h" +#include "linux/mm.h" +#include "linux/console.h" +#include "asm/irq.h" #include "asm/uaccess.h" -#include "init.h" -#include "irq_kern.h" -#include "irq_user.h" #include "kern_util.h" +#include "kern.h" #include "mconsole.h" #include "mconsole_kern.h" +#include "irq_user.h" +#include "init.h" #include "os.h" +#include "irq_kern.h" +#include "choose-mode.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) { - return mconsole_unlink_socket(); + return(mconsole_unlink_socket()); } @@ -50,9 +59,10 @@ static void mc_work_proc(struct work_struct *unused) struct mconsole_entry *req; unsigned long flags; - while (!list_empty(&mc_requests)) { + while(!list_empty(&mc_requests)){ local_irq_save(flags); - req = list_entry(mc_requests.next, struct mconsole_entry, list); + req = list_entry(mc_requests.next, struct mconsole_entry, + list); list_del(&req->list); local_irq_restore(flags); req->request.cmd->handler(&req->request); @@ -70,12 +80,12 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) static struct mc_request req; /* that's OK */ fd = (long) dev_id; - while (mconsole_get_request(fd, &req)) { - if (req.cmd->context == MCONSOLE_INTR) + while (mconsole_get_request(fd, &req)){ + if(req.cmd->context == MCONSOLE_INTR) (*req.cmd->handler)(&req); else { new = kmalloc(sizeof(*new), GFP_NOWAIT); - if (new == NULL) + if(new == NULL) mconsole_reply(&req, "Out of memory", 1, 0); else { new->request = req; @@ -84,10 +94,10 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) } } } - if (!list_empty(&mc_requests)) + if(!list_empty(&mc_requests)) schedule_work(&mconsole_work); reactivate_fd(fd, MCONSOLE_IRQ); - return IRQ_HANDLED; + return(IRQ_HANDLED); } void mconsole_version(struct mc_request *req) @@ -95,8 +105,8 @@ void mconsole_version(struct mc_request *req) char version[256]; sprintf(version, "%s %s %s %s %s", utsname()->sysname, - utsname()->nodename, utsname()->release, utsname()->version, - utsname()->machine); + utsname()->nodename, utsname()->release, + utsname()->version, utsname()->machine); mconsole_reply(req, version, 0, 0); } @@ -108,7 +118,7 @@ void mconsole_log(struct mc_request *req) ptr += strlen("log "); len = req->len - (ptr - req->request.data); - printk(KERN_WARNING "%.*s", len, ptr); + printk("%.*s", len, ptr); mconsole_reply(req, "", 0, 0); } @@ -127,17 +137,17 @@ void mconsole_proc(struct mc_request *req) char *ptr = req->request.data, *buf; ptr += strlen("proc"); - while (isspace(*ptr)) ptr++; + while(isspace(*ptr)) ptr++; proc = get_fs_type("proc"); - if (proc == NULL) { + if(proc == NULL){ mconsole_reply(req, "procfs not registered", 1, 0); goto out; } super = (*proc->get_sb)(proc, 0, NULL, NULL); put_filesystem(proc); - if (super == NULL) { + if(super == NULL){ mconsole_reply(req, "Failed to get procfs superblock", 1, 0); goto out; } @@ -152,29 +162,29 @@ void mconsole_proc(struct mc_request *req) * if commenting out these two calls + the below read cycle. To * make UML crash again, it was enough to readd either one.*/ err = link_path_walk(ptr, &nd); - if (err) { + if(err){ mconsole_reply(req, "Failed to look up file", 1, 0); goto out_kill; } file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); - if (IS_ERR(file)) { + if(IS_ERR(file)){ mconsole_reply(req, "Failed to open file", 1, 0); goto out_kill; } /*END*/ buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (buf == NULL) { + if(buf == NULL){ mconsole_reply(req, "Failed to allocate buffer", 1, 0); goto out_fput; } - if ((file->f_op != NULL) && (file->f_op->read != NULL)) { + if((file->f_op != NULL) && (file->f_op->read != NULL)){ do { n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, &file->f_pos); - if (n >= 0) { + if(n >= 0){ buf[n] = '\0'; mconsole_reply(req, buf, 0, (n > 0)); } @@ -183,7 +193,7 @@ void mconsole_proc(struct mc_request *req) 1, 0); goto out_free; } - } while (n > 0); + } while(n > 0); } else mconsole_reply(req, "", 0, 0); @@ -207,19 +217,18 @@ void mconsole_proc(struct mc_request *req) char *ptr = req->request.data; ptr += strlen("proc"); - while (isspace(*ptr)) - ptr++; + while(isspace(*ptr)) ptr++; snprintf(path, sizeof(path), "/proc/%s", ptr); fd = sys_open(path, 0, 0); if (fd < 0) { mconsole_reply(req, "Failed to open file", 1, 0); - printk(KERN_ERR "open %s: %d\n",path,fd); + printk("open %s: %d\n",path,fd); goto out; } buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (buf == NULL) { + if(buf == NULL){ mconsole_reply(req, "Failed to allocate buffer", 1, 0); goto out_close; } @@ -230,7 +239,7 @@ void mconsole_proc(struct mc_request *req) mconsole_reply(req, "Read of file failed", 1, 0); goto out_free; } - /* Begin the file content on his own line. */ + /*Begin the file content on his own line.*/ if (first_chunk) { mconsole_reply(req, "\n", 0, 1); first_chunk = 0; @@ -342,12 +351,12 @@ static struct mc_device *mconsole_find_dev(char *name) struct list_head *ele; struct mc_device *dev; - list_for_each(ele, &mconsole_devices) { + list_for_each(ele, &mconsole_devices){ dev = list_entry(ele, struct mc_device, list); - if (!strncmp(name, dev->name, strlen(dev->name))) - return dev; + if(!strncmp(name, dev->name, strlen(dev->name))) + return(dev); } - return NULL; + return(NULL); } #define UNPLUGGED_PER_PAGE \ @@ -369,15 +378,15 @@ static int mem_config(char *str, char **error_out) int err = -EINVAL, i, add; char *ret; - if (str[0] != '=') { + if(str[0] != '='){ *error_out = "Expected '=' after 'mem'"; goto out; } str++; - if (str[0] == '-') + if(str[0] == '-') add = 0; - else if (str[0] == '+') { + else if(str[0] == '+'){ add = 1; } else { @@ -387,7 +396,7 @@ static int mem_config(char *str, char **error_out) str++; diff = memparse(str, &ret); - if (*ret != '\0') { + if(*ret != '\0'){ *error_out = "Failed to parse memory increment"; goto out; } @@ -395,17 +404,17 @@ static int mem_config(char *str, char **error_out) diff /= PAGE_SIZE; down(&plug_mem_mutex); - for (i = 0; i < diff; i++) { + for(i = 0; i < diff; i++){ struct unplugged_pages *unplugged; void *addr; - if (add) { - if (list_empty(&unplugged_pages)) + if(add){ + if(list_empty(&unplugged_pages)) break; unplugged = list_entry(unplugged_pages.next, struct unplugged_pages, list); - if (unplug_index > 0) + if(unplug_index > 0) addr = unplugged->pages[--unplug_index]; else { list_del(&unplugged->list); @@ -420,11 +429,11 @@ static int mem_config(char *str, char **error_out) struct page *page; page = alloc_page(GFP_ATOMIC); - if (page == NULL) + if(page == NULL) break; unplugged = page_address(page); - if (unplug_index == UNPLUGGED_PER_PAGE) { + if(unplug_index == UNPLUGGED_PER_PAGE){ list_add(&unplugged->list, &unplugged_pages); unplug_index = 0; } @@ -436,9 +445,9 @@ static int mem_config(char *str, char **error_out) struct unplugged_pages, list); err = os_drop_memory(addr, PAGE_SIZE); - if (err) { - printk(KERN_ERR "Failed to release " - "memory - errno = %d\n", err); + if(err){ + printk("Failed to release memory - " + "errno = %d\n", err); *error_out = "Failed to release memory"; goto out_unlock; } @@ -492,10 +501,10 @@ static struct mc_device mem_mc = { static int __init mem_mc_init(void) { - if (can_drop_memory()) + if(can_drop_memory()) mconsole_register_dev(&mem_mc); - else printk(KERN_ERR "Can't release memory to the host - memory " - "hotplug won't be supported\n"); + else printk("Can't release memory to the host - memory hotplug won't " + "be supported\n"); return 0; } @@ -510,7 +519,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, char default_buf[CONFIG_BUF_SIZE], *error, *buf; int n, size; - if (get_config == NULL) { + if(get_config == NULL){ mconsole_reply(req, "No get_config routine defined", 1, 0); return; } @@ -519,30 +528,30 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, size = ARRAY_SIZE(default_buf); buf = default_buf; - while (1) { + while(1){ n = (*get_config)(name, buf, size, &error); - if (error != NULL) { + if(error != NULL){ mconsole_reply(req, error, 1, 0); goto out; } - if (n <= size) { + if(n <= size){ mconsole_reply(req, buf, 0, 0); goto out; } - if (buf != default_buf) + if(buf != default_buf) kfree(buf); size = n; buf = kmalloc(size, GFP_KERNEL); - if (buf == NULL) { + if(buf == NULL){ mconsole_reply(req, "Failed to allocate buffer", 1, 0); return; } } out: - if (buf != default_buf) + if(buf != default_buf) kfree(buf); } @@ -553,20 +562,19 @@ void mconsole_config(struct mc_request *req) int err; ptr += strlen("config"); - while (isspace(*ptr)) - ptr++; + while(isspace(*ptr)) ptr++; dev = mconsole_find_dev(ptr); - if (dev == NULL) { + if(dev == NULL){ mconsole_reply(req, "Bad configuration option", 1, 0); return; } name = &ptr[strlen(dev->name)]; ptr = name; - while ((*ptr != '=') && (*ptr != '\0')) + while((*ptr != '=') && (*ptr != '\0')) ptr++; - if (*ptr == '=') { + if(*ptr == '='){ err = (*dev->config)(name, &error_string); mconsole_reply(req, error_string, err, 0); } @@ -581,9 +589,9 @@ void mconsole_remove(struct mc_request *req) int err, start, end, n; ptr += strlen("remove"); - while (isspace(*ptr)) ptr++; + while(isspace(*ptr)) ptr++; dev = mconsole_find_dev(ptr); - if (dev == NULL) { + if(dev == NULL){ mconsole_reply(req, "Bad remove option", 1, 0); return; } @@ -592,11 +600,11 @@ void mconsole_remove(struct mc_request *req) err = 1; n = (*dev->id)(&ptr, &start, &end); - if (n < 0) { + if(n < 0){ err_msg = "Couldn't parse device number"; goto out; } - else if ((n < start) || (n > end)) { + else if((n < start) || (n > end)){ sprintf(error, "Invalid device number - must be between " "%d and %d", start, end); err_msg = error; @@ -605,16 +613,16 @@ void mconsole_remove(struct mc_request *req) err_msg = NULL; err = (*dev->remove)(n, &err_msg); - switch(err) { + switch(err){ case 0: err_msg = ""; break; case -ENODEV: - if (err_msg == NULL) + if(err_msg == NULL) err_msg = "Device doesn't exist"; break; case -EBUSY: - if (err_msg == NULL) + if(err_msg == NULL) err_msg = "Device is currently open"; break; default: @@ -632,28 +640,35 @@ struct mconsole_output { static DEFINE_SPINLOCK(client_lock); static LIST_HEAD(clients); static char console_buf[MCONSOLE_MAX_DATA]; +static int console_index = 0; static void console_write(struct console *console, const char *string, - unsigned int len) + unsigned len) { struct list_head *ele; int n; - if (list_empty(&clients)) + if(list_empty(&clients)) return; - while (len > 0) { - n = min((size_t) len, ARRAY_SIZE(console_buf)); - strncpy(console_buf, string, n); + while(1){ + n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index); + strncpy(&console_buf[console_index], string, n); + console_index += n; string += n; len -= n; + if(len == 0) + return; - list_for_each(ele, &clients) { + list_for_each(ele, &clients){ struct mconsole_output *entry; entry = list_entry(ele, struct mconsole_output, list); - mconsole_reply_len(entry->req, console_buf, n, 0, 1); + mconsole_reply_len(entry->req, console_buf, + console_index, 0, 1); } + + console_index = 0; } } @@ -683,7 +698,8 @@ static void with_console(struct mc_request *req, void (*proc)(void *), (*proc)(arg); - mconsole_reply_len(req, "", 0, 0, 0); + mconsole_reply_len(req, console_buf, console_index, 0, 0); + console_index = 0; spin_lock_irqsave(&client_lock, flags); list_del(&entry.list); @@ -691,9 +707,6 @@ static void with_console(struct mc_request *req, void (*proc)(void *), } #ifdef CONFIG_MAGIC_SYSRQ - -#include - static void sysrq_proc(void *arg) { char *op = arg; @@ -705,13 +718,12 @@ void mconsole_sysrq(struct mc_request *req) char *ptr = req->request.data; ptr += strlen("sysrq"); - while (isspace(*ptr)) ptr++; + while(isspace(*ptr)) ptr++; - /* - * With 'b', the system will shut down without a chance to reply, + /* With 'b', the system will shut down without a chance to reply, * so in this case, we reply first. */ - if (*ptr == 'b') + if(*ptr == 'b') mconsole_reply(req, "", 0, 0); with_console(req, sysrq_proc, ptr); @@ -723,6 +735,8 @@ void mconsole_sysrq(struct mc_request *req) } #endif +#ifdef CONFIG_MODE_SKAS + static void stack_proc(void *arg) { struct task_struct *from = current, *to = arg; @@ -731,34 +745,29 @@ static void stack_proc(void *arg) switch_to(from, to, from); } -/* - * Mconsole stack trace +/* Mconsole stack trace * Added by Allan Graves, Jeff Dike * Dumps a stacks registers to the linux console. * Usage stack . */ -void mconsole_stack(struct mc_request *req) +static void do_stack_trace(struct mc_request *req) { char *ptr = req->request.data; int pid_requested= -1; struct task_struct *from = NULL; struct task_struct *to = NULL; - /* - * Would be nice: + /* Would be nice: * 1) Send showregs output to mconsole. * 2) Add a way to stack dump all pids. */ ptr += strlen("stack"); - while (isspace(*ptr)) - ptr++; + while(isspace(*ptr)) ptr++; - /* - * Should really check for multiple pids or reject bad args here - */ + /* Should really check for multiple pids or reject bad args here */ /* What do the arguments in mconsole_reply mean? */ - if (sscanf(ptr, "%d", &pid_requested) == 0) { + if(sscanf(ptr, "%d", &pid_requested) == 0){ mconsole_reply(req, "Please specify a pid", 1, 0); return; } @@ -766,15 +775,25 @@ void mconsole_stack(struct mc_request *req) from = current; to = find_task_by_pid(pid_requested); - if ((to == NULL) || (pid_requested == 0)) { + if((to == NULL) || (pid_requested == 0)) { mconsole_reply(req, "Couldn't find that pid", 1, 0); return; } with_console(req, stack_proc, to); } +#endif /* CONFIG_MODE_SKAS */ -/* - * Changed by mconsole_setup, which is __setup, and called before SMP is +void mconsole_stack(struct mc_request *req) +{ + /* This command doesn't work in TT mode, so let's check and then + * get out of here + */ + CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", + 1, 0), + do_stack_trace(req)); +} + +/* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ static char *notify_socket = NULL; @@ -786,14 +805,13 @@ static int __init mconsole_init(void) int err; char file[256]; - if (umid_file_name("mconsole", file, sizeof(file))) - return -1; + if(umid_file_name("mconsole", file, sizeof(file))) return(-1); snprintf(mconsole_socket_name, sizeof(file), "%s", file); sock = os_create_unix_socket(file, sizeof(file), 1); - if (sock < 0) { - printk(KERN_ERR "Failed to initialize management console\n"); - return 1; + if (sock < 0){ + printk("Failed to initialize management console\n"); + return(1); } register_reboot_notifier(&reboot_notifier); @@ -801,14 +819,14 @@ static int __init mconsole_init(void) err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "mconsole", (void *)sock); - if (err) { - printk(KERN_ERR "Failed to get IRQ for management console\n"); - return 1; + if (err){ + printk("Failed to get IRQ for management console\n"); + return(1); } - if (notify_socket != NULL) { + if(notify_socket != NULL){ notify_socket = kstrdup(notify_socket, GFP_KERNEL); - if (notify_socket != NULL) + if(notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, mconsole_socket_name, strlen(mconsole_socket_name) + 1); @@ -816,9 +834,9 @@ static int __init mconsole_init(void) "string\n"); } - printk(KERN_INFO "mconsole (version %d) initialized on %s\n", + printk("mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); - return 0; + return(0); } __initcall(mconsole_init); @@ -829,10 +847,10 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, char *buf; buf = kmalloc(count + 1, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; + if(buf == NULL) + return(-ENOMEM); - if (copy_from_user(buf, buffer, count)) { + if(copy_from_user(buf, buffer, count)){ count = -EFAULT; goto out; } @@ -842,26 +860,24 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); out: kfree(buf); - return count; + return(count); } static int create_proc_mconsole(void) { struct proc_dir_entry *ent; - if (notify_socket == NULL) - return 0; + if(notify_socket == NULL) return(0); ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); - if (ent == NULL) { - printk(KERN_INFO "create_proc_mconsole : create_proc_entry " - "failed\n"); - return 0; + if(ent == NULL){ + printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n"); + return(0); } ent->read_proc = NULL; ent->write_proc = write_proc_mconsole; - return 0; + return(0); } static DEFINE_SPINLOCK(notify_spinlock); @@ -878,19 +894,19 @@ void unlock_notify(void) __initcall(create_proc_mconsole); -#define NOTIFY "notify:" +#define NOTIFY "=notify:" static int mconsole_setup(char *str) { - if (!strncmp(str, NOTIFY, strlen(NOTIFY))) { + if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ str += strlen(NOTIFY); notify_socket = str; } else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); - return 1; + return(1); } -__setup("mconsole=", mconsole_setup); +__setup("mconsole", mconsole_setup); __uml_help(mconsole_setup, "mconsole=notify:\n" @@ -905,12 +921,11 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, { char *message = ptr; - if (notify_socket == NULL) - return 0; + if(notify_socket == NULL) return(0); mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); - return 0; + return(0); } static struct notifier_block panic_exit_notifier = { @@ -923,14 +938,14 @@ static int add_notifier(void) { atomic_notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); - return 0; + return(0); } __initcall(add_notifier); char *mconsole_notify_socket(void) { - return notify_socket; + return(notify_socket); } EXPORT_SYMBOL(mconsole_notify_socket); diff --git a/trunk/arch/um/drivers/mconsole_user.c b/trunk/arch/um/drivers/mconsole_user.c index 430c024a19b0..f31e71546e52 100644 --- a/trunk/arch/um/drivers/mconsole_user.c +++ b/trunk/arch/um/drivers/mconsole_user.c @@ -1,22 +1,25 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ +#include +#include #include -#include -#include +#include #include +#include #include #include -#include "kern_constants.h" -#include "mconsole.h" +#include #include "user.h" +#include "sysdep/ptrace.h" +#include "mconsole.h" +#include "os.h" static struct mconsole_command commands[] = { - /* - * With uts namespaces, uts information becomes process-specific, so + /* With uts namespaces, uts information becomes process-specific, so * we need a process context. If we try handling this in interrupt * context, we may hit an exiting process without a valid uts * namespace. @@ -33,7 +36,7 @@ static struct mconsole_command commands[] = { { "go", mconsole_go, MCONSOLE_INTR }, { "log", mconsole_log, MCONSOLE_INTR }, { "proc", mconsole_proc, MCONSOLE_PROC }, - { "stack", mconsole_stack, MCONSOLE_INTR }, + { "stack", mconsole_stack, MCONSOLE_INTR }, }; /* Initialized in mconsole_init, which is an initcall */ @@ -41,21 +44,21 @@ char mconsole_socket_name[256]; int mconsole_reply_v0(struct mc_request *req, char *reply) { - struct iovec iov; - struct msghdr msg; + struct iovec iov; + struct msghdr msg; - iov.iov_base = reply; - iov.iov_len = strlen(reply); + iov.iov_base = reply; + iov.iov_len = strlen(reply); - msg.msg_name = &(req->origin); - msg.msg_namelen = req->originlen; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; + msg.msg_name = &(req->origin); + msg.msg_namelen = req->originlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; - return sendmsg(req->originating_fd, &msg, 0); + return sendmsg(req->originating_fd, &msg, 0); } static struct mconsole_command *mconsole_parse(struct mc_request *req) @@ -63,10 +66,10 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req) struct mconsole_command *cmd; int i; - for (i = 0; i < ARRAY_SIZE(commands); i++) { + for(i = 0; i < ARRAY_SIZE(commands); i++){ cmd = &commands[i]; - if (!strncmp(req->request.data, cmd->command, - strlen(cmd->command))) { + if(!strncmp(req->request.data, cmd->command, + strlen(cmd->command))){ return cmd; } } @@ -91,9 +94,9 @@ int mconsole_get_request(int fd, struct mc_request *req) req->originating_fd = fd; - if (req->request.magic != MCONSOLE_MAGIC) { + if(req->request.magic != MCONSOLE_MAGIC){ /* Unversioned request */ - len = MIN(sizeof(req->request.data) - 1, + len = MIN(sizeof(req->request.data) - 1, strlen((char *) &req->request)); memmove(req->request.data, &req->request, len); req->request.data[len] = '\0'; @@ -104,33 +107,32 @@ int mconsole_get_request(int fd, struct mc_request *req) mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " "not supported by this driver"); - return 0; + return(0); } - if (req->request.len >= MCONSOLE_MAX_DATA) { + if(req->request.len >= MCONSOLE_MAX_DATA){ mconsole_reply(req, "Request too large", 1, 0); - return 0; + return(0); } - if (req->request.version != MCONSOLE_VERSION) { - mconsole_reply(req, "This driver only supports version " - STRING(MCONSOLE_VERSION) " clients", 1, 0); + if(req->request.version != MCONSOLE_VERSION){ + mconsole_reply(req, "This driver only supports version " + STRING(MCONSOLE_VERSION) " clients", 1, 0); } - + req->request.data[req->request.len] = '\0'; req->cmd = mconsole_parse(req); - if (req->cmd == NULL) { + if(req->cmd == NULL){ mconsole_reply(req, "Unknown command", 1, 0); - return 0; + return(0); } - return 1; + return(1); } int mconsole_reply_len(struct mc_request *req, const char *str, int total, int err, int more) { - /* - * XXX This is a stack consumption problem. It'd be nice to + /* XXX This is a stack consumption problem. It'd be nice to * make it global and serialize access to it, but there are a * ton of callers to this function. */ @@ -145,7 +147,7 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, len = MIN(total, MCONSOLE_MAX_DATA - 1); - if (len == total) reply.more = more; + if(len == total) reply.more = more; else reply.more = 1; memcpy(reply.data, str, len); @@ -159,10 +161,9 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, n = sendto(req->originating_fd, &reply, len, 0, (struct sockaddr *) req->origin, req->originlen); - if (n < 0) - return -errno; - } while (total > 0); - return 0; + if(n < 0) return(-errno); + } while(total > 0); + return(0); } int mconsole_reply(struct mc_request *req, const char *str, int err, int more) @@ -186,18 +187,18 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) int n, err = 0; lock_notify(); - if (notify_sock < 0) { + if(notify_sock < 0){ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (notify_sock < 0) { + if(notify_sock < 0){ err = -errno; - printk(UM_KERN_ERR "mconsole_notify - socket failed, " - "errno = %d\n", errno); + printk("mconsole_notify - socket failed, errno = %d\n", + err); } } unlock_notify(); - - if (err) - return err; + + if(err) + return(err); target.sun_family = AF_UNIX; strcpy(target.sun_path, sock_name); @@ -211,12 +212,22 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) err = 0; len = sizeof(packet) + packet.len - sizeof(packet.data); - n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, + n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, sizeof(target)); - if (n < 0) { + if(n < 0){ err = -errno; - printk(UM_KERN_ERR "mconsole_notify - sendto failed, " - "errno = %d\n", errno); + printk("mconsole_notify - sendto failed, errno = %d\n", errno); } - return err; + return(err); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/mmapper_kern.c b/trunk/arch/um/drivers/mmapper_kern.c index 67b2f55a602f..867666a02339 100644 --- a/trunk/arch/um/drivers/mmapper_kern.c +++ b/trunk/arch/um/drivers/mmapper_kern.c @@ -9,29 +9,27 @@ * */ -#include -#include +#include +#include +#include #include -#include #include -#include -#include #include #include "mem_user.h" - + /* These are set in mmapper_init, which is called at boot time */ static unsigned long mmapper_size; -static unsigned long p_buf; -static char *v_buf; +static unsigned long p_buf = 0; +static char *v_buf = NULL; -static ssize_t mmapper_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) +static ssize_t +mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size); } -static ssize_t mmapper_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t +mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { if (*ppos > mmapper_size) return -EINVAL; @@ -41,46 +39,48 @@ static ssize_t mmapper_write(struct file *file, const char __user *buf, if (copy_from_user(&v_buf[*ppos], buf, count)) return -EFAULT; - + return count; } -static int mmapper_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int +mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) { - return -ENOIOCTLCMD; + return(-ENOIOCTLCMD); } -static int mmapper_mmap(struct file *file, struct vm_area_struct *vma) +static int +mmapper_mmap(struct file *file, struct vm_area_struct * vma) { int ret = -EINVAL; int size; if (vma->vm_pgoff != 0) goto out; - + size = vma->vm_end - vma->vm_start; - if (size > mmapper_size) - return -EFAULT; + if(size > mmapper_size) return(-EFAULT); - /* - * XXX A comment above remap_pfn_range says it should only be + /* XXX A comment above remap_pfn_range says it should only be * called when the mm semaphore is held */ if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size, - vma->vm_page_prot)) + vma->vm_page_prot)) goto out; ret = 0; out: return ret; } -static int mmapper_open(struct inode *inode, struct file *file) +static int +mmapper_open(struct inode *inode, struct file *file) { return 0; } -static int mmapper_release(struct inode *inode, struct file *file) +static int +mmapper_release(struct inode *inode, struct file *file) { return 0; } @@ -95,9 +95,7 @@ static const struct file_operations mmapper_fops = { .release = mmapper_release, }; -/* - * No locking needed - only used (and modified) by below initcall and exitcall. - */ +/* No locking needed - only used (and modified) by below initcall and exitcall. */ static struct miscdevice mmapper_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "mmapper", @@ -111,13 +109,13 @@ static int __init mmapper_init(void) printk(KERN_INFO "Mapper v0.1\n"); v_buf = (char *) find_iomem("mmapper", &mmapper_size); - if (mmapper_size == 0) { + if(mmapper_size == 0){ printk(KERN_ERR "mmapper_init - find_iomem failed\n"); goto out; } err = misc_register(&mmapper_dev); - if (err) { + if(err){ printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", err); goto out; @@ -138,3 +136,9 @@ module_exit(mmapper_exit); MODULE_AUTHOR("Greg Lonnon "); MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); +/* + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/net_kern.c b/trunk/arch/um/drivers/net_kern.c index 8c01fa81a1ae..d35d0c1ee7f4 100644 --- a/trunk/arch/um/drivers/net_kern.c +++ b/trunk/arch/um/drivers/net_kern.c @@ -1,28 +1,33 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "init.h" -#include "irq_kern.h" -#include "irq_user.h" -#include "mconsole_kern.h" +#include "linux/kernel.h" +#include "linux/netdevice.h" +#include "linux/rtnetlink.h" +#include "linux/skbuff.h" +#include "linux/socket.h" +#include "linux/spinlock.h" +#include "linux/module.h" +#include "linux/init.h" +#include "linux/etherdevice.h" +#include "linux/list.h" +#include "linux/inetdevice.h" +#include "linux/ctype.h" +#include "linux/bootmem.h" +#include "linux/ethtool.h" +#include "linux/platform_device.h" +#include "asm/uaccess.h" +#include "kern_util.h" #include "net_kern.h" #include "net_user.h" +#include "mconsole_kern.h" +#include "init.h" +#include "irq_user.h" +#include "irq_kern.h" static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) { @@ -34,46 +39,6 @@ static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) static DEFINE_SPINLOCK(opened_lock); static LIST_HEAD(opened); -/* - * The drop_skb is used when we can't allocate an skb. The - * packet is read into drop_skb in order to get the data off the - * connection to the host. - * It is reallocated whenever a maximum packet size is seen which is - * larger than any seen before. update_drop_skb is called from - * eth_configure when a new interface is added. - */ -static DEFINE_SPINLOCK(drop_lock); -static struct sk_buff *drop_skb; -static int drop_max; - -static int update_drop_skb(int max) -{ - struct sk_buff *new; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&drop_lock, flags); - - if (max <= drop_max) - goto out; - - err = -ENOMEM; - new = dev_alloc_skb(max); - if (new == NULL) - goto out; - - skb_put(new, max); - - kfree_skb(drop_skb); - drop_skb = new; - drop_max = max; - err = 0; -out: - spin_unlock_irqrestore(&drop_lock, flags); - - return err; -} - static int uml_net_rx(struct net_device *dev) { struct uml_net_private *lp = dev->priv; @@ -81,19 +46,16 @@ static int uml_net_rx(struct net_device *dev) struct sk_buff *skb; /* If we can't allocate memory, try again next round. */ - skb = dev_alloc_skb(lp->max_packet); + skb = dev_alloc_skb(dev->mtu); if (skb == NULL) { - drop_skb->dev = dev; - /* Read a packet into drop_skb and don't do anything with it. */ - (*lp->read)(lp->fd, drop_skb, lp); lp->stats.rx_dropped++; return 0; } skb->dev = dev; - skb_put(skb, lp->max_packet); + skb_put(skb, dev->mtu); skb_reset_mac_header(skb); - pkt_len = (*lp->read)(lp->fd, skb, lp); + pkt_len = (*lp->read)(lp->fd, &skb, lp); if (pkt_len > 0) { skb_trim(skb, pkt_len); @@ -122,12 +84,12 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) struct uml_net_private *lp = dev->priv; int err; - if (!netif_running(dev)) - return IRQ_NONE; + if(!netif_running(dev)) + return(IRQ_NONE); spin_lock(&lp->lock); - while ((err = uml_net_rx(dev)) > 0) ; - if (err < 0) { + while((err = uml_net_rx(dev)) > 0) ; + if(err < 0) { printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); @@ -153,20 +115,20 @@ static int uml_net_open(struct net_device *dev) struct uml_net_private *lp = dev->priv; int err; - if (lp->fd >= 0) { + if(lp->fd >= 0){ err = -ENXIO; goto out; } lp->fd = (*lp->open)(&lp->user); - if (lp->fd < 0) { + if(lp->fd < 0){ err = lp->fd; goto out; } err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, IRQF_DISABLED | IRQF_SHARED, dev->name, dev); - if (err != 0) { + if(err != 0){ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); err = -ENETUNREACH; goto out_close; @@ -179,7 +141,7 @@ static int uml_net_open(struct net_device *dev) * is full when we get here. In this case, new data is never queued, * SIGIOs never arrive, and the net never works. */ - while ((err = uml_net_rx(dev)) > 0) ; + while((err = uml_net_rx(dev)) > 0) ; spin_lock(&opened_lock); list_add(&lp->list, &opened); @@ -187,7 +149,7 @@ static int uml_net_open(struct net_device *dev) return 0; out_close: - if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user); + if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; out: return err; @@ -200,7 +162,7 @@ static int uml_net_close(struct net_device *dev) netif_stop_queue(dev); free_irq(dev->irq, dev); - if (lp->close != NULL) + if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; @@ -221,9 +183,9 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); - len = (*lp->write)(lp->fd, skb, lp); + len = (*lp->write)(lp->fd, &skb, lp); - if (len == skb->len) { + if(len == skb->len) { lp->stats.tx_packets++; lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; @@ -232,7 +194,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) /* this is normally done in the interrupt when tx finishes */ netif_wake_queue(dev); } - else if (len == 0) { + else if(len == 0){ netif_start_queue(dev); lp->stats.tx_dropped++; } @@ -256,10 +218,8 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev) static void uml_net_set_multicast_list(struct net_device *dev) { - if (dev->flags & IFF_PROMISC) - return; - else if (dev->mc_count) - dev->flags |= IFF_ALLMULTI; + if (dev->flags & IFF_PROMISC) return; + else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; else dev->flags &= ~IFF_ALLMULTI; } @@ -283,9 +243,22 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) static int uml_net_change_mtu(struct net_device *dev, int new_mtu) { + struct uml_net_private *lp = dev->priv; + int err = 0; + + spin_lock_irq(&lp->lock); + + new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); + if(new_mtu < 0){ + err = new_mtu; + goto out; + } + dev->mtu = new_mtu; - return 0; + out: + spin_unlock_irq(&lp->lock); + return err; } static void uml_net_get_drvinfo(struct net_device *dev, @@ -315,13 +288,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) char *end; int i; - if (str == NULL) + if(str == NULL) goto random; - for (i = 0;i < 6; i++) { + for(i=0;i<6;i++){ addr[i] = simple_strtoul(str, &end, 16); - if ((end == str) || - ((*end != ':') && (*end != ',') && (*end != '\0'))) { + if((end == str) || + ((*end != ':') && (*end != ',') && (*end != '\0'))){ printk(KERN_ERR "setup_etheraddr: failed to parse '%s' " "as an ethernet address\n", str); @@ -376,7 +349,7 @@ static void net_device_release(struct device *dev) struct net_device *netdev = device->dev; struct uml_net_private *lp = netdev->priv; - if (lp->remove != NULL) + if(lp->remove != NULL) (*lp->remove)(&lp->user); list_del(&device->list); kfree(device); @@ -440,7 +413,7 @@ static void eth_configure(int n, void *init, char *mac, device->pdev.name = DRIVER_NAME; device->pdev.dev.release = net_device_release; device->pdev.dev.driver_data = device; - if (platform_device_register(&device->pdev)) + if(platform_device_register(&device->pdev)) goto out_free_netdev; SET_NETDEV_DEV(dev,&device->pdev.dev); @@ -457,7 +430,6 @@ static void eth_configure(int n, void *init, char *mac, .dev = dev, .fd = -1, .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, - .max_packet = transport->user->max_packet, .protocol = transport->kern->protocol, .open = transport->user->open, .close = transport->user->close, @@ -465,7 +437,8 @@ static void eth_configure(int n, void *init, char *mac, .read = transport->kern->read, .write = transport->kern->write, .add_address = transport->user->add_address, - .delete_address = transport->user->delete_address }); + .delete_address = transport->user->delete_address, + .set_mtu = transport->user->set_mtu }); init_timer(&lp->tl); spin_lock_init(&lp->lock); @@ -477,7 +450,7 @@ static void eth_configure(int n, void *init, char *mac, goto out_unregister; set_ether_mac(dev, device->mac); - dev->mtu = transport->user->mtu; + dev->mtu = transport->user->max_packet; dev->open = uml_net_open; dev->hard_start_xmit = uml_net_start_xmit; dev->stop = uml_net_close; @@ -490,10 +463,6 @@ static void eth_configure(int n, void *init, char *mac, dev->watchdog_timeo = (HZ >> 1); dev->irq = UM_ETH_IRQ; - err = update_drop_skb(lp->max_packet); - if (err) - goto out_undo_user_init; - rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); @@ -524,9 +493,9 @@ static struct uml_net *find_device(int n) struct list_head *ele; spin_lock(&devices_lock); - list_for_each(ele, &devices) { + list_for_each(ele, &devices){ device = list_entry(ele, struct uml_net, list); - if (device->index == n) + if(device->index == n) goto out; } device = NULL; @@ -542,19 +511,19 @@ static int eth_parse(char *str, int *index_out, char **str_out, int n, err = -EINVAL;; n = simple_strtoul(str, &end, 0); - if (end == str) { + if(end == str){ *error_out = "Bad device number"; return err; } str = end; - if (*str != '=') { + if(*str != '='){ *error_out = "Expected '=' after device number"; return err; } str++; - if (find_device(n)) { + if(find_device(n)){ *error_out = "Device already configured"; return err; } @@ -582,20 +551,20 @@ static int check_transport(struct transport *transport, char *eth, int n, int len; len = strlen(transport->name); - if (strncmp(eth, transport->name, len)) + if(strncmp(eth, transport->name, len)) return 0; eth += len; - if (*eth == ',') + if(*eth == ',') eth++; - else if (*eth != '\0') + else if(*eth != '\0') return 0; *init_out = kmalloc(transport->setup_size, GFP_KERNEL); - if (*init_out == NULL) + if(*init_out == NULL) return 1; - if (!transport->setup(eth, mac_out, *init_out)) { + if(!transport->setup(eth, mac_out, *init_out)){ kfree(*init_out); *init_out = NULL; } @@ -615,13 +584,13 @@ void register_transport(struct transport *new) list_add(&new->list, &transports); spin_unlock(&transports_lock); - list_for_each_safe(ele, next, ð_cmd_line) { + list_for_each_safe(ele, next, ð_cmd_line){ eth = list_entry(ele, struct eth_init, list); match = check_transport(new, eth->init, eth->index, &init, &mac); - if (!match) + if(!match) continue; - else if (init != NULL) { + else if(init != NULL){ eth_configure(eth->index, init, mac, new); kfree(init); } @@ -638,11 +607,11 @@ static int eth_setup_common(char *str, int index) int found = 0; spin_lock(&transports_lock); - list_for_each(ele, &transports) { + list_for_each(ele, &transports){ transport = list_entry(ele, struct transport, list); - if (!check_transport(transport, str, index, &init, &mac)) + if(!check_transport(transport, str, index, &init, &mac)) continue; - if (init != NULL) { + if(init != NULL){ eth_configure(index, init, mac, transport); kfree(init); } @@ -661,15 +630,15 @@ static int __init eth_setup(char *str) int n, err; err = eth_parse(str, &n, &str, &error); - if (err) { + if(err){ printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", str, error); return 1; } new = alloc_bootmem(sizeof(*new)); - if (new == NULL) { - printk(KERN_ERR "eth_init : alloc_bootmem failed\n"); + if (new == NULL){ + printk("eth_init : alloc_bootmem failed\n"); return 1; } @@ -692,36 +661,36 @@ static int net_config(char *str, char **error_out) int n, err; err = eth_parse(str, &n, &str, error_out); - if (err) + if(err) return err; /* This string is broken up and the pieces used by the underlying * driver. So, it is freed only if eth_setup_common fails. */ str = kstrdup(str, GFP_KERNEL); - if (str == NULL) { + if(str == NULL){ *error_out = "net_config failed to strdup string"; return -ENOMEM; } err = !eth_setup_common(str, n); - if (err) + if(err) kfree(str); - return err; + return(err); } static int net_id(char **str, int *start_out, int *end_out) { - char *end; - int n; + char *end; + int n; n = simple_strtoul(*str, &end, 0); - if ((*end != '\0') || (end == *str)) + if((*end != '\0') || (end == *str)) return -1; - *start_out = n; - *end_out = n; - *str = end; - return n; + *start_out = n; + *end_out = n; + *str = end; + return n; } static int net_remove(int n, char **error_out) @@ -731,12 +700,12 @@ static int net_remove(int n, char **error_out) struct uml_net_private *lp; device = find_device(n); - if (device == NULL) + if(device == NULL) return -ENODEV; dev = device->dev; lp = dev->priv; - if (lp->fd > 0) + if(lp->fd > 0) return -EBUSY; unregister_netdev(dev); platform_device_unregister(&device->pdev); @@ -762,13 +731,13 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, void (*proc)(unsigned char *, unsigned char *, void *); unsigned char addr_buf[4], netmask_buf[4]; - if (dev->open != uml_net_open) + if(dev->open != uml_net_open) return NOTIFY_DONE; lp = dev->priv; proc = NULL; - switch (event) { + switch (event){ case NETDEV_UP: proc = lp->add_address; break; @@ -776,7 +745,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, proc = lp->delete_address; break; } - if (proc != NULL) { + if(proc != NULL){ memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf)); memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); (*proc)(addr_buf, netmask_buf, &lp->user); @@ -804,13 +773,13 @@ static int uml_net_init(void) * addresses which have already been set up get handled properly. */ spin_lock(&opened_lock); - list_for_each(ele, &opened) { + list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); ip = lp->dev->ip_ptr; - if (ip == NULL) + if(ip == NULL) continue; in = ip->ifa_list; - while (in != NULL) { + while(in != NULL){ uml_inetaddr_event(NULL, NETDEV_UP, in); in = in->ifa_next; } @@ -828,12 +797,12 @@ static void close_devices(void) struct uml_net_private *lp; spin_lock(&opened_lock); - list_for_each(ele, &opened) { + list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); free_irq(lp->dev->irq, lp->dev); - if ((lp->close != NULL) && (lp->fd >= 0)) + if((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); - if (lp->remove != NULL) + if(lp->remove != NULL) (*lp->remove)(&lp->user); } spin_unlock(&opened_lock); @@ -841,6 +810,19 @@ static void close_devices(void) __uml_exitcall(close_devices); +struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) +{ + if((skb != NULL) && (skb_tailroom(skb) < extra)){ + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); + dev_kfree_skb(skb); + skb = skb2; + } + if(skb != NULL) skb_put(skb, extra); + return(skb); +} + void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, void *), void *arg) @@ -850,9 +832,9 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, struct in_ifaddr *in; unsigned char address[4], netmask[4]; - if (ip == NULL) return; + if(ip == NULL) return; in = ip->ifa_list; - while (in != NULL) { + while(in != NULL){ memcpy(address, &in->ifa_address, sizeof(address)); memcpy(netmask, &in->ifa_mask, sizeof(netmask)); (*cb)(address, netmask, arg); @@ -867,15 +849,15 @@ int dev_netmask(void *d, void *m) struct in_ifaddr *in; __be32 *mask_out = m; - if (ip == NULL) - return 1; + if(ip == NULL) + return(1); in = ip->ifa_list; - if (in == NULL) - return 1; + if(in == NULL) + return(1); *mask_out = in->ifa_mask; - return 0; + return(0); } void *get_output_buffer(int *len_out) @@ -883,7 +865,7 @@ void *get_output_buffer(int *len_out) void *ret; ret = (void *) __get_free_pages(GFP_KERNEL, 0); - if (ret) *len_out = PAGE_SIZE; + if(ret) *len_out = PAGE_SIZE; else *len_out = 0; return ret; } @@ -899,16 +881,16 @@ int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char *remain; remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); - if (remain != NULL) { - printk(KERN_ERR "tap_setup_common - Extra garbage on " - "specification : '%s'\n", remain); - return 1; + if(remain != NULL){ + printk("tap_setup_common - Extra garbage on specification : " + "'%s'\n", remain); + return(1); } - return 0; + return(0); } unsigned short eth_protocol(struct sk_buff *skb) { - return eth_type_trans(skb, skb->dev); + return(eth_type_trans(skb, skb->dev)); } diff --git a/trunk/arch/um/drivers/net_user.c b/trunk/arch/um/drivers/net_user.c index 90d7f2e8ead8..da946e3e1bf2 100644 --- a/trunk/arch/um/drivers/net_user.c +++ b/trunk/arch/um/drivers/net_user.c @@ -1,32 +1,34 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include +#include #include +#include +#include #include -#include +#include #include #include #include +#include +#include "user.h" +#include "kern_util.h" #include "net_user.h" -#include "kern_constants.h" #include "os.h" #include "um_malloc.h" -#include "user.h" +#include "kern_constants.h" int tap_open_common(void *dev, char *gate_addr) { int tap_addr[4]; - if (gate_addr == NULL) + if(gate_addr == NULL) return 0; - if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], - &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) { - printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n", - gate_addr); + if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], + &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ + printk("Invalid tap IP address - '%s'\n", gate_addr); return -EINVAL; } return 0; @@ -36,15 +38,15 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr) { int tap_addr[4]; - if ((gate_addr != NULL) && - (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], - &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && - (eth_addr[0] == tap_addr[0]) && - (eth_addr[1] == tap_addr[1]) && - (eth_addr[2] == tap_addr[2]) && - (eth_addr[3] == tap_addr[3])) { - printk(UM_KERN_ERR "The tap IP address and the UML eth IP " - "address must be different\n"); + if((gate_addr != NULL) && + (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], + &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && + (eth_addr[0] == tap_addr[0]) && + (eth_addr[1] == tap_addr[1]) && + (eth_addr[2] == tap_addr[2]) && + (eth_addr[3] == tap_addr[3])){ + printk("The tap IP address and the UML eth IP address" + " must be different\n"); } } @@ -55,28 +57,24 @@ void read_output(int fd, char *output, int len) char c; char *str; - if (output == NULL) { + if(output == NULL){ output = &c; len = sizeof(c); } - + *output = '\0'; - ret = read(fd, &remain, sizeof(remain)); + ret = os_read_file(fd, &remain, sizeof(remain)); if (ret != sizeof(remain)) { - if (ret < 0) - ret = -errno; expected = sizeof(remain); str = "length"; goto err; } - while (remain != 0) { + while(remain != 0){ expected = (remain < len) ? remain : len; - ret = read(fd, output, expected); + ret = os_read_file(fd, output, expected); if (ret != expected) { - if (ret < 0) - ret = -errno; str = "data"; goto err; } @@ -87,22 +85,20 @@ void read_output(int fd, char *output, int len) err: if (ret < 0) - printk(UM_KERN_ERR "read_output - read of %s failed, " - "errno = %d\n", str, -ret); + printk("read_output - read of %s failed, errno = %d\n", str, -ret); else - printk(UM_KERN_ERR "read_output - read of %s failed, read only " - "%d of %d bytes\n", str, ret, expected); + printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected); } int net_read(int fd, void *buf, int len) { int n; - n = read(fd, buf, len); + n = os_read_file(fd, buf, len); - if ((n < 0) && (errno == EAGAIN)) + if(n == -EAGAIN) return 0; - else if (n == 0) + else if(n == 0) return -ENOTCONN; return n; } @@ -112,12 +108,12 @@ int net_recvfrom(int fd, void *buf, int len) int n; CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); - if (n < 0) { - if (errno == EAGAIN) + if(n < 0){ + if(errno == EAGAIN) return 0; return -errno; } - else if (n == 0) + else if(n == 0) return -ENOTCONN; return n; } @@ -126,11 +122,11 @@ int net_write(int fd, void *buf, int len) { int n; - n = write(fd, buf, len); + n = os_write_file(fd, buf, len); - if ((n < 0) && (errno == EAGAIN)) + if(n == -EAGAIN) return 0; - else if (n == 0) + else if(n == 0) return -ENOTCONN; return n; } @@ -140,12 +136,12 @@ int net_send(int fd, void *buf, int len) int n; CATCH_EINTR(n = send(fd, buf, len, 0)); - if (n < 0) { - if (errno == EAGAIN) + if(n < 0){ + if(errno == EAGAIN) return 0; return -errno; } - else if (n == 0) + else if(n == 0) return -ENOTCONN; return n; } @@ -156,12 +152,12 @@ int net_sendto(int fd, void *buf, int len, void *to, int sock_len) CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, sock_len)); - if (n < 0) { - if (errno == EAGAIN) + if(n < 0){ + if(errno == EAGAIN) return 0; return -errno; } - else if (n == 0) + else if(n == 0) return -ENOTCONN; return n; } @@ -175,7 +171,7 @@ static void change_pre_exec(void *arg) { struct change_pre_exec_data *data = arg; - close(data->close_me); + os_close_file(data->close_me); dup2(data->stdout, 1); } @@ -185,9 +181,8 @@ static int change_tramp(char **argv, char *output, int output_len) struct change_pre_exec_data pe_data; err = os_pipe(fds, 1, 0); - if (err < 0) { - printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n", - -err); + if(err < 0){ + printk("change_tramp - pipe failed, err = %d\n", -err); return err; } pe_data.close_me = fds[0]; @@ -197,8 +192,8 @@ static int change_tramp(char **argv, char *output, int output_len) if (pid > 0) /* Avoid hang as we won't get data in failure case. */ read_output(fds[0], output, output_len); - close(fds[0]); - close(fds[1]); + os_close_file(fds[0]); + os_close_file(fds[1]); if (pid > 0) CATCH_EINTR(err = waitpid(pid, NULL, 0)); @@ -211,26 +206,25 @@ static void change(char *dev, char *what, unsigned char *addr, char addr_buf[sizeof("255.255.255.255\0")]; char netmask_buf[sizeof("255.255.255.255\0")]; char version[sizeof("nnnnn\0")]; - char *argv[] = { "uml_net", version, what, dev, addr_buf, + char *argv[] = { "uml_net", version, what, dev, addr_buf, netmask_buf, NULL }; char *output; int output_len, pid; sprintf(version, "%d", UML_NET_VERSION); sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], + sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], netmask[2], netmask[3]); output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); - if (output == NULL) - printk(UM_KERN_ERR "change : failed to allocate output " - "buffer\n"); + if(output == NULL) + printk("change : failed to allocate output buffer\n"); pid = change_tramp(argv, output, output_len); - if (pid < 0) return; + if(pid < 0) return; - if (output != NULL) { + if(output != NULL){ printk("%s", output); kfree(output); } @@ -252,13 +246,13 @@ char *split_if_spec(char *str, ...) va_list ap; va_start(ap, str); - while ((arg = va_arg(ap, char **)) != NULL) { - if (*str == '\0') + while((arg = va_arg(ap, char **)) != NULL){ + if(*str == '\0') return NULL; end = strchr(str, ','); - if (end != str) + if(end != str) *arg = str; - if (end == NULL) + if(end == NULL) return NULL; *end++ = '\0'; str = end; diff --git a/trunk/arch/um/drivers/null.c b/trunk/arch/um/drivers/null.c index 21ad3d7932b3..9016c68beee8 100644 --- a/trunk/arch/um/drivers/null.c +++ b/trunk/arch/um/drivers/null.c @@ -1,11 +1,10 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include +#include #include -#include #include "chan_user.h" #include "os.h" @@ -14,23 +13,19 @@ static int null_chan; static void *null_init(char *str, int device, const struct chan_opts *opts) { - return &null_chan; + return(&null_chan); } static int null_open(int input, int output, int primary, void *d, char **dev_out) { - int fd; - *dev_out = NULL; - - fd = open(DEV_NULL, O_RDWR); - return (fd < 0) ? -errno : fd; + return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); } static int null_read(int fd, char *c_out, void *unused) { - return -ENODEV; + return(-ENODEV); } static void null_free(void *data) @@ -49,3 +44,14 @@ const struct chan_ops null_ops = { .free = null_free, .winch = 0, }; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/pcap_kern.c b/trunk/arch/um/drivers/pcap_kern.c index 3a750dd39be1..c329931673d6 100644 --- a/trunk/arch/um/drivers/pcap_kern.c +++ b/trunk/arch/um/drivers/pcap_kern.c @@ -1,11 +1,13 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike * Licensed under the GPL. */ #include "linux/init.h" -#include +#include "linux/netdevice.h" +#include "linux/etherdevice.h" #include "net_kern.h" +#include "net_user.h" #include "pcap_user.h" struct pcap_init { @@ -31,14 +33,19 @@ void pcap_init(struct net_device *dev, void *data) printk("pcap backend, host interface %s\n", ppri->host_if); } -static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int pcap_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return pcap_user_read(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER, + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) + return -ENOMEM; + + return pcap_user_read(fd, skb_mac_header(*skb), + (*skb)->dev->mtu + ETH_HEADER_OTHER, (struct pcap_data *) &lp->user); } -static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { return -EPERM; } @@ -64,29 +71,28 @@ int pcap_setup(char *str, char **mac_out, void *data) remain = split_if_spec(str, &host_if, &init->filter, &options[0], &options[1], mac_out, NULL); - if (remain != NULL) { + if(remain != NULL){ printk(KERN_ERR "pcap_setup - Extra garbage on " "specification : '%s'\n", remain); return 0; } - if (host_if != NULL) + if(host_if != NULL) init->host_if = host_if; - for (i = 0; i < ARRAY_SIZE(options); i++) { - if (options[i] == NULL) + for(i = 0; i < ARRAY_SIZE(options); i++){ + if(options[i] == NULL) continue; - if (!strcmp(options[i], "promisc")) + if(!strcmp(options[i], "promisc")) init->promisc = 1; - else if (!strcmp(options[i], "nopromisc")) + else if(!strcmp(options[i], "nopromisc")) init->promisc = 0; - else if (!strcmp(options[i], "optimize")) + else if(!strcmp(options[i], "optimize")) init->optimize = 1; - else if (!strcmp(options[i], "nooptimize")) + else if(!strcmp(options[i], "nooptimize")) init->optimize = 0; else { - printk(KERN_ERR "pcap_setup : bad option - '%s'\n", - options[i]); + printk("pcap_setup : bad option - '%s'\n", options[i]); return 0; } } diff --git a/trunk/arch/um/drivers/pcap_user.c b/trunk/arch/um/drivers/pcap_user.c index e9809356c530..1316456e2a28 100644 --- a/trunk/arch/um/drivers/pcap_user.c +++ b/trunk/arch/um/drivers/pcap_user.c @@ -1,17 +1,21 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike * Licensed under the GPL. */ +#include +#include +#include #include #include -#include #include #include "net_user.h" #include "pcap_user.h" -#include "kern_constants.h" -#include "um_malloc.h" #include "user.h" +#include "um_malloc.h" +#include "kern_constants.h" + +#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) #define PCAP_FD(p) (*(int *)(p)) @@ -21,9 +25,8 @@ static int pcap_user_init(void *data, void *dev) pcap_t *p; char errors[PCAP_ERRBUF_SIZE]; - p = pcap_open_live(pri->host_if, ETH_MAX_PACKET + ETH_HEADER_OTHER, - pri->promisc, 0, errors); - if (p == NULL) { + p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); + if(p == NULL){ printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - " "'%s'\n", errors); return -EINVAL; @@ -40,55 +43,50 @@ static int pcap_open(void *data) __u32 netmask; int err; - if (pri->pcap == NULL) + if(pri->pcap == NULL) return -ENODEV; - if (pri->filter != NULL) { + if(pri->filter != NULL){ err = dev_netmask(pri->dev, &netmask); - if (err < 0) { + if(err < 0){ printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n"); return -EIO; } - pri->compiled = kmalloc(sizeof(struct bpf_program), - UM_GFP_KERNEL); - if (pri->compiled == NULL) { + pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL); + if(pri->compiled == NULL){ printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); return -ENOMEM; } - err = pcap_compile(pri->pcap, - (struct bpf_program *) pri->compiled, + err = pcap_compile(pri->pcap, + (struct bpf_program *) pri->compiled, pri->filter, pri->optimize, netmask); - if (err < 0) { + if(err < 0){ printk(UM_KERN_ERR "pcap_open : pcap_compile failed - " "'%s'\n", pcap_geterr(pri->pcap)); - goto out; + return -EIO; } err = pcap_setfilter(pri->pcap, pri->compiled); - if (err < 0) { + if(err < 0){ printk(UM_KERN_ERR "pcap_open : pcap_setfilter " "failed - '%s'\n", pcap_geterr(pri->pcap)); - goto out; + return -EIO; } } return PCAP_FD(pri->pcap); - - out: - kfree(pri->compiled); - return -EIO; } static void pcap_remove(void *data) { struct pcap_data *pri = data; - if (pri->compiled != NULL) + if(pri->compiled != NULL) pcap_freecode(pri->compiled); - if (pri->pcap != NULL) + if(pri->pcap != NULL) pcap_close(pri->pcap); } @@ -97,7 +95,7 @@ struct pcap_handler_data { int len; }; -static void handler(u_char *data, const struct pcap_pkthdr *header, +static void handler(u_char *data, const struct pcap_pkthdr *header, const u_char *packet) { int len; @@ -117,12 +115,12 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) int n; n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); - if (n < 0) { + if(n < 0){ printk(UM_KERN_ERR "pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); return -EIO; } - else if (n == 0) + else if(n == 0) return 0; return hdata.len; } @@ -132,8 +130,8 @@ const struct net_user_info pcap_user_info = { .open = pcap_open, .close = NULL, .remove = pcap_remove, + .set_mtu = NULL, .add_address = NULL, .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, + .max_packet = MAX_PACKET - ETH_HEADER_OTHER }; diff --git a/trunk/arch/um/drivers/port_kern.c b/trunk/arch/um/drivers/port_kern.c index 330543b3129b..1c8efd95c421 100644 --- a/trunk/arch/um/drivers/port_kern.c +++ b/trunk/arch/um/drivers/port_kern.c @@ -1,16 +1,24 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/completion.h" -#include "linux/interrupt.h" #include "linux/list.h" +#include "linux/sched.h" +#include "linux/slab.h" +#include "linux/interrupt.h" +#include "linux/spinlock.h" +#include "linux/errno.h" #include "asm/atomic.h" -#include "init.h" +#include "asm/semaphore.h" +#include "asm/errno.h" +#include "kern_util.h" +#include "kern.h" +#include "irq_user.h" #include "irq_kern.h" -#include "os.h" #include "port.h" +#include "init.h" +#include "os.h" struct port_list { struct list_head list; @@ -45,8 +53,8 @@ static irqreturn_t pipe_interrupt(int irq, void *data) int fd; fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); - if (fd < 0) { - if (fd == -EAGAIN) + if(fd < 0){ + if(fd == -EAGAIN) return IRQ_NONE; printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", @@ -73,18 +81,18 @@ static irqreturn_t pipe_interrupt(int irq, void *data) static int port_accept(struct port_list *port) { struct connection *conn; - int fd, socket[2], pid; + int fd, socket[2], pid, ret = 0; fd = port_connection(port->fd, socket, &pid); - if (fd < 0) { - if (fd != -EAGAIN) + if(fd < 0){ + if(fd != -EAGAIN) printk(KERN_ERR "port_accept : port_connection " "returned %d\n", -fd); goto out; } conn = kmalloc(sizeof(*conn), GFP_ATOMIC); - if (conn == NULL) { + if(conn == NULL){ printk(KERN_ERR "port_accept : failed to allocate " "connection\n"); goto out_close; @@ -96,17 +104,17 @@ static int port_accept(struct port_list *port) .telnetd_pid = pid, .port = port }); - if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, + if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "telnetd", conn)) { + "telnetd", conn)){ printk(KERN_ERR "port_accept : failed to get IRQ for " "telnetd\n"); goto out_free; } - if (atomic_read(&port->wait_count) == 0) { + if(atomic_read(&port->wait_count) == 0){ os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); - printk(KERN_ERR "No one waiting for port\n"); + printk("No one waiting for port\n"); } list_add(&conn->list, &port->pending); return 1; @@ -115,29 +123,28 @@ static int port_accept(struct port_list *port) kfree(conn); out_close: os_close_file(fd); - os_kill_process(pid, 1); + if(pid != -1) + os_kill_process(pid, 1); out: - return 0; + return ret; } static DECLARE_MUTEX(ports_sem); static LIST_HEAD(ports); -static void port_work_proc(struct work_struct *unused) +void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; unsigned long flags; local_irq_save(flags); - list_for_each(ele, &ports) { + list_for_each(ele, &ports){ port = list_entry(ele, struct port_list, list); - if (!port->has_connection) + if(!port->has_connection) continue; - reactivate_fd(port->fd, ACCEPT_IRQ); - while (port_accept(port)) - ; + while(port_accept(port)) ; port->has_connection = 0; } local_irq_restore(flags); @@ -162,27 +169,25 @@ void *port_data(int port_num) int fd; down(&ports_sem); - list_for_each(ele, &ports) { + list_for_each(ele, &ports){ port = list_entry(ele, struct port_list, list); - if (port->port == port_num) - goto found; + if(port->port == port_num) goto found; } port = kmalloc(sizeof(struct port_list), GFP_KERNEL); - if (port == NULL) { + if(port == NULL){ printk(KERN_ERR "Allocation of port list failed\n"); goto out; } fd = port_listen_fd(port_num); - if (fd < 0) { + if(fd < 0){ printk(KERN_ERR "binding to port %d failed, errno = %d\n", port_num, -fd); goto out_free; } - - if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, + if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "port", port)) { + "port", port)){ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; } @@ -201,7 +206,7 @@ void *port_data(int port_num) found: dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); - if (dev == NULL) { + if(dev == NULL){ printk(KERN_ERR "Allocation of port device entry failed\n"); goto out; } @@ -211,10 +216,10 @@ void *port_data(int port_num) .telnetd_pid = -1 }); goto out; - out_close: - os_close_file(fd); out_free: kfree(port); + out_close: + os_close_file(fd); out: up(&ports_sem); return dev; @@ -228,9 +233,9 @@ int port_wait(void *data) int fd; atomic_inc(&port->wait_count); - while (1) { + while(1){ fd = -ERESTARTSYS; - if (wait_for_completion_interruptible(&port->done)) + if(wait_for_completion_interruptible(&port->done)) goto out; spin_lock(&port->lock); @@ -253,8 +258,7 @@ int port_wait(void *data) */ free_irq(TELNETD_IRQ, conn); - if (conn->fd >= 0) - break; + if(conn->fd >= 0) break; os_close_file(conn->fd); kfree(conn); } @@ -272,9 +276,9 @@ void port_remove_dev(void *d) { struct port_dev *dev = d; - if (dev->helper_pid != -1) + if(dev->helper_pid != -1) os_kill_process(dev->helper_pid, 0); - if (dev->telnetd_pid != -1) + if(dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid, 1); dev->helper_pid = -1; dev->telnetd_pid = -1; @@ -293,7 +297,7 @@ static void free_port(void) struct list_head *ele; struct port_list *port; - list_for_each(ele, &ports) { + list_for_each(ele, &ports){ port = list_entry(ele, struct port_list, list); free_irq_by_fd(port->fd); os_close_file(port->fd); diff --git a/trunk/arch/um/drivers/port_user.c b/trunk/arch/um/drivers/port_user.c index addd75902656..c799b00012c7 100644 --- a/trunk/arch/um/drivers/port_user.c +++ b/trunk/arch/um/drivers/port_user.c @@ -1,20 +1,24 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #include +#include #include +#include #include -#include #include +#include +#include +#include #include +#include "kern_util.h" +#include "user.h" #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" #include "port.h" +#include "os.h" #include "um_malloc.h" -#include "user.h" struct port_chan { int raw; @@ -30,25 +34,24 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) char *end; int port; - if (*str != ':') { - printk(UM_KERN_ERR "port_init : channel type 'port' must " - "specify a port number\n"); + if(*str != ':'){ + printk("port_init : channel type 'port' must specify a " + "port number\n"); return NULL; } str++; port = strtoul(str, &end, 0); - if ((*end != '\0') || (end == str)) { - printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n", - str); + if((*end != '\0') || (end == str)){ + printk("port_init : couldn't parse port '%s'\n", str); return NULL; } kern_data = port_data(port); - if (kern_data == NULL) + if(kern_data == NULL) return NULL; data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if (data == NULL) + if(data == NULL) goto err; *data = ((struct port_chan) { .raw = opts->raw, @@ -76,13 +79,13 @@ static int port_open(int input, int output, int primary, void *d, int fd, err; fd = port_wait(data->kernel_data); - if ((fd >= 0) && data->raw) { + if((fd >= 0) && data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); - if (err) + if(err) return err; err = raw(fd); - if (err) + if(err) return err; } *dev_out = data->dev; @@ -116,11 +119,11 @@ int port_listen_fd(int port) int fd, err, arg; fd = socket(PF_INET, SOCK_STREAM, 0); - if (fd == -1) + if(fd == -1) return -errno; arg = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) { + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ err = -errno; goto out; } @@ -128,23 +131,23 @@ int port_listen_fd(int port) addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ err = -errno; goto out; } - if (listen(fd, 1) < 0) { + if(listen(fd, 1) < 0){ err = -errno; goto out; } err = os_set_fd_block(fd, 0); - if (err < 0) + if(err < 0) goto out; return fd; out: - close(fd); + os_close_file(fd); return err; } @@ -160,10 +163,10 @@ void port_pre_exec(void *arg) dup2(data->sock_fd, 0); dup2(data->sock_fd, 1); dup2(data->sock_fd, 2); - close(data->sock_fd); + os_close_file(data->sock_fd); dup2(data->pipe_fd, 3); - shutdown(3, SHUT_RD); - close(data->pipe_fd); + os_shutdown_socket(3, 1, 0); + os_close_file(data->pipe_fd); } int port_connection(int fd, int *socket, int *pid_out) @@ -173,12 +176,12 @@ int port_connection(int fd, int *socket, int *pid_out) "/usr/lib/uml/port-helper", NULL }; struct port_pre_exec_data data; - new = accept(fd, NULL, 0); - if (new < 0) - return -errno; + new = os_accept_connection(fd); + if(new < 0) + return new; err = os_pipe(socket, 0, 0); - if (err < 0) + if(err < 0) goto out_close; data = ((struct port_pre_exec_data) @@ -186,18 +189,18 @@ int port_connection(int fd, int *socket, int *pid_out) .pipe_fd = socket[1] }); err = run_helper(port_pre_exec, &data, argv); - if (err < 0) + if(err < 0) goto out_shutdown; *pid_out = err; return new; out_shutdown: - shutdown(socket[0], SHUT_RDWR); - close(socket[0]); - shutdown(socket[1], SHUT_RDWR); - close(socket[1]); + os_shutdown_socket(socket[0], 1, 1); + os_close_file(socket[0]); + os_shutdown_socket(socket[1], 1, 1); + os_close_file(socket[1]); out_close: - close(new); + os_close_file(new); return err; } diff --git a/trunk/arch/um/drivers/pty.c b/trunk/arch/um/drivers/pty.c index 49c79dda6046..1e3fd619a837 100644 --- a/trunk/arch/um/drivers/pty.c +++ b/trunk/arch/um/drivers/pty.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -6,16 +6,16 @@ #include #include #include -#include -#include #include +#include +#include #include #include #include "chan_user.h" -#include "kern_constants.h" #include "os.h" -#include "um_malloc.h" #include "user.h" +#include "kern_constants.h" +#include "um_malloc.h" struct pty_chan { void (*announce)(char *dev_name, int dev); @@ -33,7 +33,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) if (data == NULL) return NULL; - *data = ((struct pty_chan) { .announce = opts->announce, + *data = ((struct pty_chan) { .announce = opts->announce, .dev = device, .raw = opts->raw }); return data; @@ -56,11 +56,11 @@ static int pts_open(int input, int output, int primary, void *d, if (data->raw) { CATCH_EINTR(err = tcgetattr(fd, &data->tt)); if (err) - goto out_close; + return err; err = raw(fd); if (err) - goto out_close; + return err; } dev = ptsname(fd); @@ -71,10 +71,6 @@ static int pts_open(int input, int output, int primary, void *d, (*data->announce)(dev, data->dev); return fd; - -out_close: - close(fd); - return err; } static int getmaster(char *line) @@ -101,7 +97,7 @@ static int getmaster(char *line) *tp = 't'; err = access(line, R_OK | W_OK); *tp = 'p'; - if (!err) + if(!err) return master; close(master); } @@ -123,14 +119,12 @@ static int pty_open(int input, int output, int primary, void *d, if (fd < 0) return fd; - if (data->raw) { + if(data->raw){ err = raw(fd); - if (err) { - close(fd); + if (err) return err; - } } - + if (data->announce) (*data->announce)(dev, data->dev); diff --git a/trunk/arch/um/drivers/slip_kern.c b/trunk/arch/um/drivers/slip_kern.c index ae67e7158e71..125c44f77638 100644 --- a/trunk/arch/um/drivers/slip_kern.c +++ b/trunk/arch/um/drivers/slip_kern.c @@ -1,12 +1,11 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL. - */ - -#include -#include -#include +#include "linux/kernel.h" +#include "linux/stddef.h" +#include "linux/init.h" +#include "linux/netdevice.h" +#include "linux/if_arp.h" #include "net_kern.h" +#include "net_user.h" +#include "kern.h" #include "slip.h" struct slip_init { @@ -44,19 +43,21 @@ void slip_init(struct net_device *dev, void *data) static unsigned short slip_protocol(struct sk_buff *skbuff) { - return htons(ETH_P_IP); + return(htons(ETH_P_IP)); } -static int slip_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int slip_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return slip_user_read(fd, skb_mac_header(skb), skb->dev->mtu, - (struct slip_data *) &lp->user); + return(slip_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, + (struct slip_data *) &lp->user)); } -static int slip_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int slip_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return slip_user_write(fd, skb->data, skb->len, - (struct slip_data *) &lp->user); + return(slip_user_write(fd, (*skb)->data, (*skb)->len, + (struct slip_data *) &lp->user)); } const struct net_kern_info slip_kern_info = { @@ -70,11 +71,12 @@ static int slip_setup(char *str, char **mac_out, void *data) { struct slip_init *init = data; - *init = ((struct slip_init) { .gate_addr = NULL }); + *init = ((struct slip_init) + { .gate_addr = NULL }); - if (str[0] != '\0') + if(str[0] != '\0') init->gate_addr = str; - return 1; + return(1); } static struct transport slip_transport = { diff --git a/trunk/arch/um/drivers/slip_user.c b/trunk/arch/um/drivers/slip_user.c index 5f06204d6871..c0b73c28cff0 100644 --- a/trunk/arch/um/drivers/slip_user.c +++ b/trunk/arch/um/drivers/slip_user.c @@ -1,22 +1,21 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL. - */ - #include #include #include -#include -#include +#include +#include #include +#include #include #include -#include "kern_constants.h" +#include +#include "kern_util.h" +#include "user.h" #include "net_user.h" -#include "os.h" #include "slip.h" +#include "slip_common.h" +#include "os.h" #include "um_malloc.h" -#include "user.h" +#include "kern_constants.h" static int slip_user_init(void *data, void *dev) { @@ -32,9 +31,8 @@ static int set_up_tty(int fd) struct termios tios; if (tcgetattr(fd, &tios) < 0) { - printk(UM_KERN_ERR "could not get initial terminal " - "attributes\n"); - return -1; + printk("could not get initial terminal attributes\n"); + return(-1); } tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; @@ -50,10 +48,10 @@ static int set_up_tty(int fd) cfsetispeed(&tios, B38400); if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { - printk(UM_KERN_ERR "failed to set terminal attributes\n"); - return -1; + printk("failed to set terminal attributes\n"); + return(-1); } - return 0; + return(0); } struct slip_pre_exec_data { @@ -66,11 +64,9 @@ static void slip_pre_exec(void *arg) { struct slip_pre_exec_data *data = arg; - if (data->stdin >= 0) - dup2(data->stdin, 0); + if(data->stdin >= 0) dup2(data->stdin, 0); dup2(data->stdout, 1); - if (data->close_me >= 0) - close(data->close_me); + if(data->close_me >= 0) os_close_file(data->close_me); } static int slip_tramp(char **argv, int fd) @@ -80,9 +76,8 @@ static int slip_tramp(char **argv, int fd) int status, pid, fds[2], err, output_len; err = os_pipe(fds, 1, 0); - if (err < 0) { - printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n", - -err); + if(err < 0){ + printk("slip_tramp : pipe failed, err = %d\n", -err); goto out; } @@ -91,42 +86,41 @@ static int slip_tramp(char **argv, int fd) pe_data.stdout = fds[1]; pe_data.close_me = fds[0]; err = run_helper(slip_pre_exec, &pe_data, argv); - if (err < 0) + if(err < 0) goto out_close; pid = err; output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); - if (output == NULL) { - printk(UM_KERN_ERR "slip_tramp : failed to allocate output " - "buffer\n"); + if(output == NULL){ + printk("slip_tramp : failed to allocate output buffer\n"); os_kill_process(pid, 1); err = -ENOMEM; goto out_free; } - close(fds[1]); + os_close_file(fds[1]); read_output(fds[0], output, output_len); printk("%s", output); CATCH_EINTR(err = waitpid(pid, &status, 0)); - if (err < 0) + if(err < 0) err = errno; - else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { - printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]); + else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ + printk("'%s' didn't exit with status 0\n", argv[0]); err = -EINVAL; } else err = 0; - close(fds[0]); + os_close_file(fds[0]); out_free: kfree(output); return err; out_close: - close(fds[0]); - close(fds[1]); + os_close_file(fds[0]); + os_close_file(fds[1]); out: return err; } @@ -136,64 +130,60 @@ static int slip_open(void *data) struct slip_data *pri = data; char version_buf[sizeof("nnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; - char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, + char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, NULL }; int sfd, mfd, err; err = get_pty(); - if (err < 0) { - printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n", - -err); + if(err < 0){ + printk("slip-open : Failed to open pty, err = %d\n", -err); goto out; } mfd = err; - err = open(ptsname(mfd), O_RDWR, 0); - if (err < 0) { - printk(UM_KERN_ERR "Couldn't open tty for slip line, " - "err = %d\n", -err); + err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); + if(err < 0){ + printk("Couldn't open tty for slip line, err = %d\n", -err); goto out_close; } sfd = err; - if (set_up_tty(sfd)) + if(set_up_tty(sfd)) goto out_close2; pri->slave = sfd; pri->slip.pos = 0; pri->slip.esc = 0; - if (pri->gate_addr != NULL) { + if(pri->gate_addr != NULL){ sprintf(version_buf, "%d", UML_NET_VERSION); strcpy(gate_buf, pri->gate_addr); err = slip_tramp(argv, sfd); - if (err < 0) { - printk(UM_KERN_ERR "slip_tramp failed - err = %d\n", - -err); + if(err < 0){ + printk("slip_tramp failed - err = %d\n", -err); goto out_close2; } err = os_get_ifname(pri->slave, pri->name); - if (err < 0) { - printk(UM_KERN_ERR "get_ifname failed, err = %d\n", - -err); + if(err < 0){ + printk("get_ifname failed, err = %d\n", -err); goto out_close2; } iter_addresses(pri->dev, open_addr, pri->name); } else { err = os_set_slip(sfd); - if (err < 0) { - printk(UM_KERN_ERR "Failed to set slip discipline " - "encapsulation - err = %d\n", -err); + if(err < 0){ + printk("Failed to set slip discipline encapsulation - " + "err = %d\n", -err); goto out_close2; } } - return mfd; + return(mfd); out_close2: - close(sfd); + os_close_file(sfd); out_close: - close(mfd); + os_close_file(mfd); out: return err; } @@ -202,21 +192,21 @@ static void slip_close(int fd, void *data) { struct slip_data *pri = data; char version_buf[sizeof("nnnnn\0")]; - char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, + char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, NULL }; int err; - if (pri->gate_addr != NULL) + if(pri->gate_addr != NULL) iter_addresses(pri->dev, close_addr, pri->name); sprintf(version_buf, "%d", UML_NET_VERSION); err = slip_tramp(argv, pri->slave); - if (err != 0) - printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err); - close(fd); - close(pri->slave); + if(err != 0) + printk("slip_tramp failed - errno = %d\n", -err); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; } @@ -230,13 +220,17 @@ int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) return slip_proto_write(fd, buf, len, &pri->slip); } +static int slip_set_mtu(int mtu, void *data) +{ + return(mtu); +} + static void slip_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct slip_data *pri = data; - if (pri->slave < 0) - return; + if(pri->slave < 0) return; open_addr(addr, netmask, pri->name); } @@ -245,8 +239,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask, { struct slip_data *pri = data; - if (pri->slave < 0) - return; + if(pri->slave < 0) return; close_addr(addr, netmask, pri->name); } @@ -255,8 +248,8 @@ const struct net_user_info slip_user_info = { .open = slip_open, .close = slip_close, .remove = NULL, + .set_mtu = slip_set_mtu, .add_address = slip_add_addr, .delete_address = slip_del_addr, - .mtu = BUF_SIZE, - .max_packet = BUF_SIZE, + .max_packet = BUF_SIZE }; diff --git a/trunk/arch/um/drivers/slirp_kern.c b/trunk/arch/um/drivers/slirp_kern.c index 240ee650865d..0a0324a6d290 100644 --- a/trunk/arch/um/drivers/slirp_kern.c +++ b/trunk/arch/um/drivers/slirp_kern.c @@ -1,14 +1,11 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL. - */ - -#include +#include "linux/kernel.h" +#include "linux/stddef.h" #include "linux/init.h" -#include -#include +#include "linux/netdevice.h" +#include "linux/if_arp.h" #include "net_kern.h" #include "net_user.h" +#include "kern.h" #include "slirp.h" struct slirp_init { @@ -42,26 +39,29 @@ void slirp_init(struct net_device *dev, void *data) dev->tx_queue_len = 256; dev->flags = IFF_NOARP; printk("SLIRP backend - command line:"); - for (i = 0; spri->argw.argv[i] != NULL; i++) + for(i=0;spri->argw.argv[i]!=NULL;i++) { printk(" '%s'",spri->argw.argv[i]); + } printk("\n"); } static unsigned short slirp_protocol(struct sk_buff *skbuff) { - return htons(ETH_P_IP); + return(htons(ETH_P_IP)); } -static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int slirp_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu, - (struct slirp_data *) &lp->user); + return(slirp_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, + (struct slirp_data *) &lp->user)); } -static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int slirp_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return slirp_user_write(fd, skb->data, skb->len, - (struct slirp_data *) &lp->user); + return(slirp_user_write(fd, (*skb)->data, (*skb)->len, + (struct slirp_data *) &lp->user)); } const struct net_kern_info slirp_kern_info = { @@ -76,32 +76,31 @@ static int slirp_setup(char *str, char **mac_out, void *data) struct slirp_init *init = data; int i=0; - *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } }); + *init = ((struct slirp_init) + { .argw = { { "slirp", NULL } } }); str = split_if_spec(str, mac_out, NULL); - if (str == NULL) /* no command line given after MAC addr */ - return 1; + if(str == NULL) { /* no command line given after MAC addr */ + return(1); + } do { - if (i >= SLIRP_MAX_ARGS - 1) { - printk(KERN_WARNING "slirp_setup: truncating slirp " - "arguments\n"); + if(i>=SLIRP_MAX_ARGS-1) { + printk("slirp_setup: truncating slirp arguments\n"); break; } init->argw.argv[i++] = str; while(*str && *str!=',') { - if (*str == '_') - *str=' '; + if(*str=='_') *str=' '; str++; } - if (*str != ',') + if(*str!=',') break; - *str++ = '\0'; - } while (1); - - init->argw.argv[i] = NULL; - return 1; + *str++='\0'; + } while(1); + init->argw.argv[i]=NULL; + return(1); } static struct transport slirp_transport = { diff --git a/trunk/arch/um/drivers/slirp_user.c b/trunk/arch/um/drivers/slirp_user.c index 1865089ff41a..0e462f64f227 100644 --- a/trunk/arch/um/drivers/slirp_user.c +++ b/trunk/arch/um/drivers/slirp_user.c @@ -1,17 +1,18 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL. - */ - +#include +#include #include -#include +#include +#include #include +#include #include -#include "kern_constants.h" +#include +#include "kern_util.h" +#include "user.h" #include "net_user.h" -#include "os.h" #include "slirp.h" -#include "user.h" +#include "slip_common.h" +#include "os.h" static int slirp_user_init(void *data, void *dev) { @@ -30,10 +31,8 @@ static void slirp_pre_exec(void *arg) { struct slirp_pre_exec_data *data = arg; - if (data->stdin != -1) - dup2(data->stdin, 0); - if (data->stdout != -1) - dup2(data->stdout, 1); + if(data->stdin != -1) dup2(data->stdin, 0); + if(data->stdout != -1) dup2(data->stdout, 1); } static int slirp_tramp(char **argv, int fd) @@ -45,7 +44,7 @@ static int slirp_tramp(char **argv, int fd) pe_data.stdout = fd; pid = run_helper(slirp_pre_exec, &pe_data, argv); - return pid; + return(pid); } static int slirp_open(void *data) @@ -54,12 +53,12 @@ static int slirp_open(void *data) int fds[2], pid, err; err = os_pipe(fds, 1, 1); - if (err) - return err; + if(err) + return(err); err = slirp_tramp(pri->argw.argv, fds[1]); - if (err < 0) { - printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err); + if(err < 0){ + printk("slirp_tramp failed - errno = %d\n", -err); goto out; } pid = err; @@ -69,10 +68,10 @@ static int slirp_open(void *data) pri->slip.esc = 0; pri->pid = err; - return fds[0]; + return(fds[0]); out: - close(fds[0]); - close(fds[1]); + os_close_file(fds[0]); + os_close_file(fds[1]); return err; } @@ -81,33 +80,31 @@ static void slirp_close(int fd, void *data) struct slirp_data *pri = data; int status,err; - close(fd); - close(pri->slave); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; - if (pri->pid<1) { - printk(UM_KERN_ERR "slirp_close: no child process to shut " - "down\n"); + if(pri->pid<1) { + printk("slirp_close: no child process to shut down\n"); return; } #if 0 - if (kill(pri->pid, SIGHUP)<0) { - printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " - "(%d)\n", pri->pid, errno); + if(kill(pri->pid, SIGHUP)<0) { + printk("slirp_close: sending hangup to %d failed (%d)\n", + pri->pid, errno); } #endif CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); - if (err < 0) { - printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno); + if(err < 0) { + printk("slirp_close: waitpid returned %d\n", errno); return; } - if (err == 0) { - printk(UM_KERN_ERR "slirp_close: process %d has not exited\n", - pri->pid); + if(err == 0) { + printk("slirp_close: process %d has not exited\n", pri->pid); return; } @@ -124,13 +121,18 @@ int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) return slip_proto_write(fd, buf, len, &pri->slip); } +static int slirp_set_mtu(int mtu, void *data) +{ + return(mtu); +} + const struct net_user_info slirp_user_info = { .init = slirp_user_init, .open = slirp_open, .close = slirp_close, .remove = NULL, + .set_mtu = slirp_set_mtu, .add_address = NULL, .delete_address = NULL, - .mtu = BUF_SIZE, - .max_packet = BUF_SIZE, + .max_packet = BUF_SIZE }; diff --git a/trunk/arch/um/drivers/tty.c b/trunk/arch/um/drivers/tty.c index c930fedc5172..a9f87e19c5bf 100644 --- a/trunk/arch/um/drivers/tty.c +++ b/trunk/arch/um/drivers/tty.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include +#include #include +#include +#include #include "chan_user.h" -#include "kern_constants.h" +#include "user.h" #include "os.h" #include "um_malloc.h" -#include "user.h" struct tty_chan { char *dev; @@ -22,15 +22,15 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) { struct tty_chan *data; - if (*str != ':') { - printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify " + if(*str != ':'){ + printk("tty_init : channel type 'tty' must specify " "a device\n"); return NULL; } str++; data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if (data == NULL) + if(data == NULL) return NULL; *data = ((struct tty_chan) { .dev = str, .raw = opts->raw }); @@ -42,26 +42,19 @@ static int tty_open(int input, int output, int primary, void *d, char **dev_out) { struct tty_chan *data = d; - int fd, err, mode = 0; - - if (input && output) - mode = O_RDWR; - else if (input) - mode = O_RDONLY; - else if (output) - mode = O_WRONLY; + int fd, err; - fd = open(data->dev, mode); - if (fd < 0) - return -errno; + fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); + if(fd < 0) + return fd; - if (data->raw) { + if(data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); - if (err) + if(err) return err; err = raw(fd); - if (err) + if(err) return err; } diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c index 25b248a02507..0eabe73c964d 100644 --- a/trunk/arch/um/drivers/ubd_kern.c +++ b/trunk/arch/um/drivers/ubd_kern.c @@ -615,7 +615,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long)); err = -ENOMEM; - ubd_dev->cow.bitmap = vmalloc(ubd_dev->cow.bitmap_len); + ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); if(ubd_dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; diff --git a/trunk/arch/um/drivers/vde.h b/trunk/arch/um/drivers/vde.h deleted file mode 100644 index fc3a05902ba1..000000000000 --- a/trunk/arch/um/drivers/vde.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). - * Licensed under the GPL. - */ - -#ifndef __UM_VDE_H__ -#define __UM_VDE_H__ - -struct vde_data { - char *vde_switch; - char *descr; - void *args; - void *conn; - void *dev; -}; - -struct vde_init { - char *vde_switch; - char *descr; - int port; - char *group; - int mode; -}; - -extern const struct net_user_info vde_user_info; - -extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init); - -extern int vde_user_read(void *conn, void *buf, int len); -extern int vde_user_write(void *conn, void *buf, int len); - -#endif diff --git a/trunk/arch/um/drivers/vde_kern.c b/trunk/arch/um/drivers/vde_kern.c deleted file mode 100644 index add7e722defb..000000000000 --- a/trunk/arch/um/drivers/vde_kern.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). - * Licensed under the GPL. - * - * Transport usage: - * ethN=vde,,,,,, - * - */ - -#include "linux/init.h" -#include -#include "net_kern.h" -#include "net_user.h" -#include "vde.h" - -static void vde_init(struct net_device *dev, void *data) -{ - struct vde_init *init = data; - struct uml_net_private *pri; - struct vde_data *vpri; - - pri = dev->priv; - vpri = (struct vde_data *) pri->user; - - vpri->vde_switch = init->vde_switch; - vpri->descr = init->descr ? init->descr : "UML vde_transport"; - vpri->args = NULL; - vpri->conn = NULL; - vpri->dev = dev; - - printk("vde backend - %s, ", vpri->vde_switch ? - vpri->vde_switch : "(default socket)"); - - vde_init_libstuff(vpri, init); - - printk("\n"); -} - -static int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - struct vde_data *pri = (struct vde_data *) &lp->user; - - if (pri->conn != NULL) - return vde_user_read(pri->conn, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); - - printk(KERN_ERR "vde_read - we have no VDECONN to read from"); - return -EBADF; -} - -static int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - struct vde_data *pri = (struct vde_data *) &lp->user; - - if (pri->conn != NULL) - return vde_user_write((void *)pri->conn, skb->data, - skb->len); - - printk(KERN_ERR "vde_write - we have no VDECONN to write to"); - return -EBADF; -} - -static const struct net_kern_info vde_kern_info = { - .init = vde_init, - .protocol = eth_protocol, - .read = vde_read, - .write = vde_write, -}; - -static int vde_setup(char *str, char **mac_out, void *data) -{ - struct vde_init *init = data; - char *remain, *port_str = NULL, *mode_str = NULL, *last; - - *init = ((struct vde_init) - { .vde_switch = NULL, - .descr = NULL, - .port = 0, - .group = NULL, - .mode = 0 }); - - remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str, - &init->group, &mode_str, &init->descr, NULL); - - if (remain != NULL) - printk(KERN_WARNING "vde_setup - Ignoring extra data :" - "'%s'\n", remain); - - if (port_str != NULL) { - init->port = simple_strtoul(port_str, &last, 10); - if ((*last != '\0') || (last == port_str)) { - printk(KERN_ERR "vde_setup - Bad port : '%s'\n", - port_str); - return 0; - } - } - - if (mode_str != NULL) { - init->mode = simple_strtoul(mode_str, &last, 8); - if ((*last != '\0') || (last == mode_str)) { - printk(KERN_ERR "vde_setup - Bad mode : '%s'\n", - mode_str); - return 0; - } - } - - printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ? - init->vde_switch : "(default socket)"); - - return 1; -} - -static struct transport vde_transport = { - .list = LIST_HEAD_INIT(vde_transport.list), - .name = "vde", - .setup = vde_setup, - .user = &vde_user_info, - .kern = &vde_kern_info, - .private_size = sizeof(struct vde_data), - .setup_size = sizeof(struct vde_init), -}; - -static int register_vde(void) -{ - register_transport(&vde_transport); - return 0; -} - -late_initcall(register_vde); diff --git a/trunk/arch/um/drivers/vde_user.c b/trunk/arch/um/drivers/vde_user.c deleted file mode 100644 index d9941fe5f931..000000000000 --- a/trunk/arch/um/drivers/vde_user.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). - * Licensed under the GPL. - */ - -#include -#include -#include -#include "kern_constants.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" -#include "vde.h" - -static int vde_user_init(void *data, void *dev) -{ - struct vde_data *pri = data; - VDECONN *conn = NULL; - int err = -EINVAL; - - pri->dev = dev; - - conn = vde_open(pri->vde_switch, pri->descr, pri->args); - - if (conn == NULL) { - err = -errno; - printk(UM_KERN_ERR "vde_user_init: vde_open failed, " - "errno = %d\n", errno); - return err; - } - - printk(UM_KERN_INFO "vde backend - connection opened\n"); - - pri->conn = conn; - - return 0; -} - -static int vde_user_open(void *data) -{ - struct vde_data *pri = data; - - if (pri->conn != NULL) - return vde_datafd(pri->conn); - - printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open"); - return -EINVAL; -} - -static void vde_remove(void *data) -{ - struct vde_data *pri = data; - - if (pri->conn != NULL) { - printk(UM_KERN_INFO "vde backend - closing connection\n"); - vde_close(pri->conn); - pri->conn = NULL; - kfree(pri->args); - pri->args = NULL; - return; - } - - printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove"); -} - -const struct net_user_info vde_user_info = { - .init = vde_user_init, - .open = vde_user_open, - .close = NULL, - .remove = vde_remove, - .add_address = NULL, - .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, -}; - -void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init) -{ - struct vde_open_args *args; - - vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); - if (vpri->args == NULL) { - printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args" - "allocation failed"); - return; - } - - args = vpri->args; - - args->port = init->port; - args->group = init->group; - args->mode = init->mode ? init->mode : 0700; - - args->port ? printk(UM_KERN_INFO "port %d", args->port) : - printk(UM_KERN_INFO "undefined port"); -} - -int vde_user_read(void *conn, void *buf, int len) -{ - VDECONN *vconn = conn; - int rv; - - if (vconn == NULL) - return 0; - - rv = vde_recv(vconn, buf, len, 0); - if (rv < 0) { - if (errno == EAGAIN) - return 0; - return -errno; - } - else if (rv == 0) - return -ENOTCONN; - - return rv; -} - -int vde_user_write(void *conn, void *buf, int len) -{ - VDECONN *vconn = conn; - - if (vconn == NULL) - return 0; - - return vde_send(vconn, buf, len, 0); -} - diff --git a/trunk/arch/um/drivers/xterm.c b/trunk/arch/um/drivers/xterm.c index 8a1c18a9b240..fd817e541543 100644 --- a/trunk/arch/um/drivers/xterm.c +++ b/trunk/arch/um/drivers/xterm.c @@ -1,21 +1,20 @@ -/* +/* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include -#include #include +#include #include -#include #include +#include #include #include "chan_user.h" -#include "kern_constants.h" #include "os.h" -#include "um_malloc.h" +#include "init.h" #include "user.h" #include "xterm.h" +#include "kern_constants.h" struct xterm_chan { int pid; @@ -30,7 +29,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) { struct xterm_chan *data; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = malloc(sizeof(*data)); if (data == NULL) return NULL; *data = ((struct xterm_chan) { .pid = -1, @@ -96,10 +95,8 @@ static int xterm_open(int input, int output, int primary, void *d, if (access(argv[4], X_OK) < 0) argv[4] = "port-helper"; - /* - * Check that DISPLAY is set, this doesn't guarantee the xterm - * will work but w/o it we can be pretty sure it won't. - */ + /* Check that DISPLAY is set, this doesn't guarantee the xterm + * will work but w/o it we can be pretty sure it won't. */ if (getenv("DISPLAY") == NULL) { printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n"); return -ENODEV; @@ -198,7 +195,7 @@ static int xterm_open(int input, int output, int primary, void *d, static void xterm_close(int fd, void *d) { struct xterm_chan *data = d; - + if (data->pid != -1) os_kill_process(data->pid, 1); data->pid = -1; @@ -210,6 +207,11 @@ static void xterm_close(int fd, void *d) os_close_file(fd); } +static void xterm_free(void *d) +{ + free(d); +} + const struct chan_ops xterm_ops = { .type = "xterm", .init = xterm_init, @@ -219,6 +221,6 @@ const struct chan_ops xterm_ops = { .write = generic_write, .console_write = generic_console_write, .window_size = generic_window_size, - .free = generic_free, + .free = xterm_free, .winch = 1, }; diff --git a/trunk/arch/um/include/arch.h b/trunk/arch/um/include/arch.h index 49c601ff2bac..10ad52daa8c5 100644 --- a/trunk/arch/um/include/arch.h +++ b/trunk/arch/um/include/arch.h @@ -9,7 +9,7 @@ #include "sysdep/ptrace.h" extern void arch_check_bugs(void); -extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); -extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); +extern int arch_fixup(unsigned long address, union uml_pt_regs *regs); +extern int arch_handle_signal(int sig, union uml_pt_regs *regs); #endif diff --git a/trunk/arch/um/include/as-layout.h b/trunk/arch/um/include/as-layout.h index a5cdf953e04a..fccf187bf4e1 100644 --- a/trunk/arch/um/include/as-layout.h +++ b/trunk/arch/um/include/as-layout.h @@ -6,28 +6,6 @@ #ifndef __START_H__ #define __START_H__ -#include "uml-config.h" -#include "kern_constants.h" - -/* - * Assembly doesn't want any casting, but C does, so define these - * without casts here, and define new symbols with casts inside the C - * section. - */ -#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE) -#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE) -#define ASM_STUB_START ASM_STUB_CODE - -/* - * This file is included by the assembly stubs, which just want the - * definitions above. - */ -#ifndef __ASSEMBLY__ - -#define STUB_CODE ((unsigned long) ASM_STUB_CODE) -#define STUB_DATA ((unsigned long) ASM_STUB_DATA) -#define STUB_START ((unsigned long) ASM_STUB_START) - #include "sysdep/ptrace.h" struct cpu_task { @@ -50,9 +28,8 @@ extern unsigned long _unprotected_end; extern unsigned long brk_start; extern int linux_main(int argc, char **argv); +extern void set_cmdline(char *cmd); -extern void (*sig_info[])(int, struct uml_pt_regs *); - -#endif +extern void (*sig_info[])(int, union uml_pt_regs *); #endif diff --git a/trunk/arch/um/include/choose-mode.h b/trunk/arch/um/include/choose-mode.h new file mode 100644 index 000000000000..b87b36a87d91 --- /dev/null +++ b/trunk/arch/um/include/choose-mode.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __CHOOSE_MODE_H__ +#define __CHOOSE_MODE_H__ + +#include "uml-config.h" + +#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) +#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) + +extern int mode_tt; +static inline void *__choose_mode(void *tt, void *skas) { + return mode_tt ? tt : skas; +} + +#define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas)))) + +#elif defined(UML_CONFIG_MODE_SKAS) +#define CHOOSE_MODE(tt, skas) (skas) + +#elif defined(UML_CONFIG_MODE_TT) +#define CHOOSE_MODE(tt, skas) (tt) + +#else +#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled +#endif + +#define CHOOSE_MODE_PROC(tt, skas, args...) \ + CHOOSE_MODE(tt(args), skas(args)) + +#ifndef __CHOOSE_MODE +#define __CHOOSE_MODE(tt, skas) CHOOSE_MODE(tt, skas) +#endif + +#endif diff --git a/trunk/arch/um/include/common-offsets.h b/trunk/arch/um/include/common-offsets.h index 0edab695ed4e..6eee343e53eb 100644 --- a/trunk/arch/um/include/common-offsets.h +++ b/trunk/arch/um/include/common-offsets.h @@ -1,13 +1,15 @@ /* for use by sys-$SUBARCH/kernel-offsets.c */ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); +#ifdef CONFIG_MODE_TT +OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); +#endif OFFSET(HOST_TASK_REGS, task_struct, thread.regs); OFFSET(HOST_TASK_PID, task_struct, pid); DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); -DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); @@ -32,9 +34,3 @@ DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC); DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); DEFINE(UM_THREAD_SIZE, THREAD_SIZE); - -DEFINE(UM_HZ, HZ); - -DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC); -DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); -DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC); diff --git a/trunk/arch/um/include/irq_user.h b/trunk/arch/um/include/irq_user.h index 884a9c17eea0..15d311b9be9e 100644 --- a/trunk/arch/um/include/irq_user.h +++ b/trunk/arch/um/include/irq_user.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __IRQ_USER_H__ #define __IRQ_USER_H__ -#include "sysdep/ptrace.h" +#include "uml-config.h" struct irq_fd { struct irq_fd *next; @@ -21,7 +21,7 @@ struct irq_fd { enum { IRQ_READ, IRQ_WRITE }; -extern void sigio_handler(int sig, struct uml_pt_regs *regs); +extern void sigio_handler(int sig, union uml_pt_regs *regs); extern int activate_fd(int irq, int fd, int type, void *dev_id); extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); extern void free_irq_by_fd(int fd); @@ -30,4 +30,8 @@ extern void deactivate_fd(int fd, int irqnum); extern int deactivate_all_fds(void); extern int activate_ipi(int fd, int pid); +#ifdef CONFIG_MODE_TT +extern void forward_interrupts(int pid); +#endif + #endif diff --git a/trunk/arch/um/include/kern_util.h b/trunk/arch/um/include/kern_util.h index 74ce8e5370a6..6c2be26f1d7d 100644 --- a/trunk/arch/um/include/kern_util.h +++ b/trunk/arch/um/include/kern_util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -8,8 +8,9 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +#include "uml-config.h" -typedef void (*kern_hndl)(int, struct uml_pt_regs *); +typedef void (*kern_hndl)(int, union uml_pt_regs *); struct kern_handlers { kern_hndl relay_signal; @@ -33,6 +34,9 @@ extern int nsyscalls; UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); +#ifdef UML_CONFIG_MODE_TT +extern unsigned long stack_sp(unsigned long page); +#endif extern int kernel_thread_proc(void *data); extern void syscall_segv(int sig); extern int current_pid(void); @@ -40,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic); extern int do_signal(void); extern int is_stack_fault(unsigned long sp); extern unsigned long segv(struct faultinfo fi, unsigned long ip, - int is_user, struct uml_pt_regs *regs); + int is_user, union uml_pt_regs *regs); extern int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out); extern void syscall_ready(void); @@ -53,7 +57,7 @@ extern int need_finish_fork(void); extern void free_stack(unsigned long stack, int order); extern void add_input_request(int op, void (*proc)(int), void *arg); extern char *current_cmd(void); -extern void timer_handler(int sig, struct uml_pt_regs *regs); +extern void timer_handler(int sig, union uml_pt_regs *regs); extern int set_signals(int enable); extern int pid_to_processor_id(int pid); extern void deliver_signals(void *t); @@ -63,8 +67,9 @@ extern void finish_fork(void); extern void paging_init(void); extern void init_flush_vm(void); extern void *syscall_sp(void *t); -extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); -extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); +extern void syscall_trace(union uml_pt_regs *regs, int entryexit); +extern int hz(void); +extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); extern void interrupt_end(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int debugger_signal(int status, int pid); @@ -74,9 +79,10 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop); extern int init_parent_proxy(int pid); extern int singlestepping(void *t); extern void check_stack_overflow(void *ptr); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, union uml_pt_regs *regs); extern int user_context(unsigned long sp); -extern void timer_irq(struct uml_pt_regs *regs); +extern void timer_irq(union uml_pt_regs *regs); +extern void unprotect_stack(unsigned long stack); extern void do_uml_exitcalls(void); extern int attach_debugger(int idle_pid, int pid, int stop); extern int config_gdb(char *str); @@ -107,9 +113,11 @@ extern void time_init_kern(void); /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ extern int __cant_sleep(void); -extern void sigio_handler(int sig, struct uml_pt_regs *regs); -extern void copy_sc(struct uml_pt_regs *regs, void *from); +extern void sigio_handler(int sig, union uml_pt_regs *regs); + +extern void copy_sc(union uml_pt_regs *regs, void *from); + extern unsigned long to_irq_stack(unsigned long *mask_out); unsigned long from_irq_stack(int nested); -extern int start_uml(void); + #endif diff --git a/trunk/arch/um/include/mconsole.h b/trunk/arch/um/include/mconsole.h index c139ae1d6826..b282839c1625 100644 --- a/trunk/arch/um/include/mconsole.h +++ b/trunk/arch/um/include/mconsole.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -63,7 +63,7 @@ struct mc_request struct mconsole_request request; struct mconsole_command *cmd; - struct uml_pt_regs regs; + union uml_pt_regs regs; }; extern char mconsole_socket_name[]; @@ -96,3 +96,14 @@ extern void lock_notify(void); extern void unlock_notify(void); #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/mem.h b/trunk/arch/um/include/mem.h index 5cd40e99e8d5..e8ff0d8fa610 100644 --- a/trunk/arch/um/include/mem.h +++ b/trunk/arch/um/include/mem.h @@ -1,12 +1,18 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #ifndef __MEM_H__ #define __MEM_H__ -extern int phys_mapping(unsigned long phys, unsigned long long *offset_out); +#include "linux/types.h" + +extern int phys_mapping(unsigned long phys, __u64 *offset_out); +extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); +extern int is_remapped(void *virt); +extern int physmem_remove_mapping(void *virt); +extern void physmem_forget_descriptor(int fd); extern unsigned long uml_physmem; static inline unsigned long to_phys(void *virt) @@ -20,3 +26,14 @@ static inline void *to_virt(unsigned long phys) } #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/mode.h b/trunk/arch/um/include/mode.h new file mode 100644 index 000000000000..786cf563eb05 --- /dev/null +++ b/trunk/arch/um/include/mode.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_H__ +#define __MODE_H__ + +#include "uml-config.h" + +#ifdef UML_CONFIG_MODE_TT +#include "mode-tt.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS +#include "mode-skas.h" +#endif + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/mode_kern.h b/trunk/arch/um/include/mode_kern.h new file mode 100644 index 000000000000..88e5e77bf517 --- /dev/null +++ b/trunk/arch/um/include/mode_kern.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_KERN_H__ +#define __MODE_KERN_H__ + +#ifdef CONFIG_MODE_TT +#include "mode_kern_tt.h" +#endif + +#ifdef CONFIG_MODE_SKAS +#include "mode_kern_skas.h" +#endif + +#endif diff --git a/trunk/arch/um/include/net_kern.h b/trunk/arch/um/include/net_kern.h index d843c7924a7c..9237056b9103 100644 --- a/trunk/arch/um/include/net_kern.h +++ b/trunk/arch/um/include/net_kern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -30,24 +30,24 @@ struct uml_net_private { struct work_struct work; int fd; unsigned char mac[ETH_ALEN]; - int max_packet; unsigned short (*protocol)(struct sk_buff *); int (*open)(void *); void (*close)(int, void *); void (*remove)(void *); - int (*read)(int, struct sk_buff *skb, struct uml_net_private *); - int (*write)(int, struct sk_buff *skb, struct uml_net_private *); + int (*read)(int, struct sk_buff **skb, struct uml_net_private *); + int (*write)(int, struct sk_buff **skb, struct uml_net_private *); void (*add_address)(unsigned char *, unsigned char *, void *); void (*delete_address)(unsigned char *, unsigned char *, void *); + int (*set_mtu)(int mtu, void *); char user[0]; }; struct net_kern_info { void (*init)(struct net_device *, void *); unsigned short (*protocol)(struct sk_buff *); - int (*read)(int, struct sk_buff *skb, struct uml_net_private *); - int (*write)(int, struct sk_buff *skb, struct uml_net_private *); + int (*read)(int, struct sk_buff **skb, struct uml_net_private *); + int (*write)(int, struct sk_buff **skb, struct uml_net_private *); }; struct transport { @@ -62,6 +62,7 @@ struct transport { extern struct net_device *ether_init(int); extern unsigned short ether_protocol(struct sk_buff *); +extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); extern int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char **gate_addr); extern void register_transport(struct transport *new); diff --git a/trunk/arch/um/include/net_user.h b/trunk/arch/um/include/net_user.h index 63bee158cd8e..cfe7c50634b9 100644 --- a/trunk/arch/um/include/net_user.h +++ b/trunk/arch/um/include/net_user.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -18,10 +18,10 @@ struct net_user_info { int (*open)(void *); void (*close)(int, void *); void (*remove)(void *); + int (*set_mtu)(int mtu, void *); void (*add_address)(unsigned char *, unsigned char *, void *); void (*delete_address)(unsigned char *, unsigned char *, void *); int max_packet; - int mtu; }; extern void ether_user_init(void *data, void *dev); diff --git a/trunk/arch/um/include/os.h b/trunk/arch/um/include/os.h index fbf0a87c6eaa..930b261ea483 100644 --- a/trunk/arch/um/include/os.h +++ b/trunk/arch/um/include/os.h @@ -1,18 +1,20 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __OS_H__ #define __OS_H__ -#include -#include "irq_user.h" +#include "uml-config.h" +#include "asm/types.h" +#include "../os/include/file.h" +#include "sysdep/ptrace.h" #include "kern_util.h" -#include "longjmp.h" -#include "mm_id.h" +#include "skas/mm_id.h" +#include "irq_user.h" #include "sysdep/tls.h" -#include "../os/include/file.h" +#include "sysdep/archsetjmp.h" #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) @@ -128,15 +130,18 @@ static inline struct openflags of_cloexec(struct openflags flags) extern int os_stat_file(const char *file_name, struct uml_stat *buf); extern int os_stat_fd(const int fd, struct uml_stat *buf); extern int os_access(const char *file, int mode); +extern void os_print_error(int error, const char* str); extern int os_get_exec_close(int fd, int *close_on_exec); -extern int os_set_exec_close(int fd); +extern int os_set_exec_close(int fd, int close_on_exec); extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); +extern int os_window_size(int fd, int *rows, int *cols); +extern int os_new_tty_pgrp(int fd, int pid); extern int os_get_ifname(int fd, char *namebuf); extern int os_set_slip(int fd); extern int os_set_owner(int fd, int pid); extern int os_mode_fd(int fd, int mode); -extern int os_seek_file(int fd, unsigned long long offset); +extern int os_seek_file(int fd, __u64 offset); extern int os_open_file(char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); extern int os_write_file(int fd, const void *buf, int count); @@ -174,7 +179,11 @@ extern void check_host_supports_tls(int *supports_tls, int *tls_min); /* Make sure they are clear when running in TT mode. Required by * SEGV_MAYBE_FIXABLE */ +#ifdef UML_CONFIG_MODE_SKAS #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) +#else +#define clear_can_do_skas() do {} while (0) +#endif /* mem.c */ extern int create_mem_file(unsigned long long len); @@ -185,13 +194,20 @@ extern int os_process_parent(int pid); extern void os_stop_process(int pid); extern void os_kill_process(int pid, int reap_child); extern void os_kill_ptraced_process(int pid, int reap_child); +#ifdef UML_CONFIG_MODE_TT +extern void os_usr1_process(int pid); +#endif extern long os_ptrace_ldt(long pid, long addr, long data); extern int os_getpid(void); extern int os_getpgrp(void); +#ifdef UML_CONFIG_MODE_TT +extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); +extern void stop(void); +#endif extern void init_new_thread_signals(void); -extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr); +extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); @@ -202,9 +218,21 @@ extern int os_drop_memory(void *addr, int length); extern int can_drop_memory(void); extern void os_flush_stdout(void); +/* tt.c + * for tt mode only (will be deleted in future...) + */ +extern void forward_ipi(int fd, int pid); +extern void kill_child_dead(int pid); +extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); +extern int protect_memory(unsigned long addr, unsigned long len, + int r, int w, int x, int must_succeed); +extern void forward_pending_sigio(int target); +extern int start_fork_tramp(void *arg, unsigned long temp_stack, + int clone_flags, int (*tramp)(void *)); + /* uaccess.c */ extern unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher, + void **fault_addr, void **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out); @@ -227,7 +255,6 @@ extern int set_umid(char *name); extern char *get_umid(void); /* signal.c */ -extern void timer_init(void); extern void set_sigstack(void *sig_stack, int size); extern void remove_sigstack(void); extern void set_handler(int sig, void (*handler)(int), int flags, ...); @@ -239,6 +266,7 @@ extern int set_signals(int enable); /* trap.c */ extern void os_fill_handlinfo(struct kern_handlers h); +extern void do_longjmp(void *p, int val); /* util.c */ extern void stack_protections(unsigned long address); @@ -249,12 +277,17 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...); extern void os_dump_core(void); /* time.c */ -extern void idle_sleep(unsigned long long nsecs); -extern int set_interval(void); -extern int timer_one_shot(int ticks); -extern long long disable_timer(void); +#define BILLION (1000 * 1000 * 1000) + +extern void switch_timers(int to_real); +extern void idle_sleep(int secs); +extern int set_interval(int is_virtual); +#ifdef CONFIG_MODE_TT +extern void enable_timer(void); +#endif +extern void disable_timer(void); extern void uml_idle_timer(void); -extern long long os_nsecs(void); +extern unsigned long long os_nsecs(void); /* skas/mem.c */ extern long run_syscall_stub(struct mm_id * mm_idp, @@ -275,9 +308,7 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr, extern int is_skas_winch(int pid, int fd, void *data); extern int start_userspace(unsigned long stub_stack); extern int copy_context_skas0(unsigned long stack, int pid); -extern void save_registers(int pid, struct uml_pt_regs *regs); -extern void restore_registers(int pid, struct uml_pt_regs *regs); -extern void userspace(struct uml_pt_regs *regs); +extern void userspace(union uml_pt_regs *regs); extern void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack); extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); diff --git a/trunk/arch/um/include/registers.h b/trunk/arch/um/include/registers.h index 0e27406a43a4..f845b3629a6d 100644 --- a/trunk/arch/um/include/registers.h +++ b/trunk/arch/um/include/registers.h @@ -9,15 +9,13 @@ #include "sysdep/ptrace.h" #include "sysdep/archsetjmp.h" -extern void init_thread_registers(struct uml_pt_regs *to); +extern void init_thread_registers(union uml_pt_regs *to); extern int save_fp_registers(int pid, unsigned long *fp_regs); extern int restore_fp_registers(int pid, unsigned long *fp_regs); -extern int save_fpx_registers(int pid, unsigned long *fp_regs); -extern int restore_fpx_registers(int pid, unsigned long *fp_regs); -extern void save_registers(int pid, struct uml_pt_regs *regs); -extern void restore_registers(int pid, struct uml_pt_regs *regs); +extern void save_registers(int pid, union uml_pt_regs *regs); +extern void restore_registers(int pid, union uml_pt_regs *regs); extern void init_registers(int pid); -extern void get_safe_registers(unsigned long *regs); +extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); #endif diff --git a/trunk/arch/um/include/skas/mmu-skas.h b/trunk/arch/um/include/skas/mmu-skas.h new file mode 100644 index 000000000000..b26986c0c3d2 --- /dev/null +++ b/trunk/arch/um/include/skas/mmu-skas.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_MMU_H +#define __SKAS_MMU_H + +#include "mm_id.h" +#include "asm/ldt.h" + +struct mmu_context_skas { + struct mm_id id; + unsigned long last_page_table; +#ifdef CONFIG_3_LEVEL_PGTABLES + unsigned long last_pmd; +#endif + uml_ldt_t ldt; +}; + +extern void switch_mm_skas(struct mm_id * mm_idp); + +#endif diff --git a/trunk/arch/um/include/skas/mode-skas.h b/trunk/arch/um/include/skas/mode-skas.h index e065feb000df..8bc6916bbbb1 100644 --- a/trunk/arch/um/include/skas/mode-skas.h +++ b/trunk/arch/um/include/skas/mode-skas.h @@ -1,11 +1,18 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __MODE_SKAS_H__ #define __MODE_SKAS_H__ +#include + +extern unsigned long exec_regs[]; +extern unsigned long exec_fp_regs[]; +extern unsigned long exec_fpx_regs[]; +extern int have_fpx_regs; + extern void kill_off_processes_skas(void); #endif diff --git a/trunk/arch/um/include/skas/mode_kern_skas.h b/trunk/arch/um/include/skas/mode_kern_skas.h new file mode 100644 index 000000000000..8ee6285dfacc --- /dev/null +++ b/trunk/arch/um/include/skas/mode_kern_skas.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_MODE_KERN_H__ +#define __SKAS_MODE_KERN_H__ + +#include "linux/sched.h" +#include "asm/page.h" +#include "asm/ptrace.h" + +extern void flush_thread_skas(void); +extern void switch_to_skas(void *prev, void *next); +extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, + unsigned long esp); +extern int copy_thread_skas(int nr, unsigned long clone_flags, + unsigned long sp, unsigned long stack_top, + struct task_struct *p, struct pt_regs *regs); +extern void release_thread_skas(struct task_struct *task); +extern void init_idle_skas(void); +extern void flush_tlb_kernel_range_skas(unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_vm_skas(void); +extern void __flush_tlb_one_skas(unsigned long addr); +extern void flush_tlb_range_skas(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +extern void flush_tlb_mm_skas(struct mm_struct *mm); +extern void force_flush_all_skas(void); +extern long execute_syscall_skas(void *r); +extern void before_mem_skas(unsigned long unused); +extern unsigned long set_task_sizes_skas(unsigned long *task_size_out); +extern int start_uml_skas(void); +extern int external_pid_skas(struct task_struct *task); +extern int thread_pid_skas(struct task_struct *task); +extern void flush_tlb_page_skas(struct vm_area_struct *vma, + unsigned long address); + +#define kmem_end_skas (host_task_size - 1024 * 1024) + +#endif diff --git a/trunk/arch/um/include/skas/skas.h b/trunk/arch/um/include/skas/skas.h index b073f8a86bd3..e88926b16072 100644 --- a/trunk/arch/um/include/skas/skas.h +++ b/trunk/arch/um/include/skas/skas.h @@ -1,11 +1,12 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __SKAS_H #define __SKAS_H +#include "mm_id.h" #include "sysdep/ptrace.h" extern int userspace_pid[]; @@ -14,7 +15,7 @@ extern int skas_needs_stub; extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); -extern void handle_syscall(struct uml_pt_regs *regs); +extern void handle_syscall(union uml_pt_regs *regs); extern int new_mm(unsigned long stack); extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); diff --git a/trunk/arch/um/include/skas/uaccess-skas.h b/trunk/arch/um/include/skas/uaccess-skas.h new file mode 100644 index 000000000000..224a75f4c025 --- /dev/null +++ b/trunk/arch/um/include/skas/uaccess-skas.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_UACCESS_H +#define __SKAS_UACCESS_H + +#include "asm/errno.h" + +/* No SKAS-specific checking. */ +#define access_ok_skas(type, addr, size) 0 + +extern int copy_from_user_skas(void *to, const void __user *from, int n); +extern int copy_to_user_skas(void __user *to, const void *from, int n); +extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); +extern int __clear_user_skas(void __user *mem, int len); +extern int clear_user_skas(void __user *mem, int len); +extern int strnlen_user_skas(const void __user *str, int len); + +#endif diff --git a/trunk/arch/um/include/sysdep-i386/kernel-offsets.h b/trunk/arch/um/include/sysdep-i386/kernel-offsets.h index 5868526b5eef..97ec9d894d75 100644 --- a/trunk/arch/um/include/sysdep-i386/kernel-offsets.h +++ b/trunk/arch/um/include/sysdep-i386/kernel-offsets.h @@ -17,5 +17,6 @@ void foo(void) { + OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs); #include } diff --git a/trunk/arch/um/include/sysdep-i386/ptrace.h b/trunk/arch/um/include/sysdep-i386/ptrace.h index 11c08969d134..52b398bcafcf 100644 --- a/trunk/arch/um/include/sysdep-i386/ptrace.h +++ b/trunk/arch/um/include/sysdep-i386/ptrace.h @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -9,11 +9,17 @@ #include "uml-config.h" #include "user_constants.h" #include "sysdep/faultinfo.h" +#include "choose-mode.h" #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long)) #define MAX_REG_OFFSET (UM_FRAME_SIZE) +#ifdef UML_CONFIG_PT_PROXY +extern void update_debugregs(int seq); +#else static inline void update_debugregs(int seq) {} +#endif + /* syscall emulation path in ptrace */ @@ -25,6 +31,12 @@ void set_using_sysemu(int value); int get_using_sysemu(void); extern int sysemu_supported; +#ifdef UML_CONFIG_MODE_TT +#include "sysdep/sc.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS + #include "skas_ptregs.h" #define REGS_IP(r) ((r)[HOST_IP]) @@ -48,36 +60,70 @@ extern int sysemu_supported; #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) +#endif #ifndef PTRACE_SYSEMU_SINGLESTEP #define PTRACE_SYSEMU_SINGLESTEP 32 #endif -struct uml_pt_regs { - unsigned long gp[MAX_REG_NR]; - struct faultinfo faultinfo; - long syscall; - int is_user; +union uml_pt_regs { +#ifdef UML_CONFIG_MODE_TT + struct tt_regs { + long syscall; + void *sc; + struct faultinfo faultinfo; + } tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { + unsigned long regs[MAX_REG_NR]; + unsigned long fp[HOST_FP_SIZE]; + unsigned long xfp[HOST_XFP_SIZE]; + struct faultinfo faultinfo; + long syscall; + int is_user; + } skas; +#endif }; #define EMPTY_UML_PT_REGS { } -#define UPT_IP(r) REGS_IP((r)->gp) -#define UPT_SP(r) REGS_SP((r)->gp) -#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) -#define UPT_EAX(r) REGS_EAX((r)->gp) -#define UPT_EBX(r) REGS_EBX((r)->gp) -#define UPT_ECX(r) REGS_ECX((r)->gp) -#define UPT_EDX(r) REGS_EDX((r)->gp) -#define UPT_ESI(r) REGS_ESI((r)->gp) -#define UPT_EDI(r) REGS_EDI((r)->gp) -#define UPT_EBP(r) REGS_EBP((r)->gp) -#define UPT_ORIG_EAX(r) ((r)->syscall) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_SS(r) REGS_SS((r)->gp) -#define UPT_DS(r) REGS_DS((r)->gp) -#define UPT_ES(r) REGS_ES((r)->gp) -#define UPT_FS(r) REGS_FS((r)->gp) -#define UPT_GS(r) REGS_GS((r)->gp) +extern int mode_tt; + +#define UPT_SC(r) ((r)->tt.sc) +#define UPT_IP(r) \ + __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) +#define UPT_SP(r) \ + __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) +#define UPT_EFLAGS(r) \ + __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) +#define UPT_EAX(r) \ + __CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) +#define UPT_EBX(r) \ + __CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) +#define UPT_ECX(r) \ + __CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) +#define UPT_EDX(r) \ + __CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) +#define UPT_ESI(r) \ + __CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) +#define UPT_EDI(r) \ + __CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) +#define UPT_EBP(r) \ + __CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) +#define UPT_ORIG_EAX(r) \ + __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) +#define UPT_CS(r) \ + __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_SS(r) \ + __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) +#define UPT_DS(r) \ + __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) +#define UPT_ES(r) \ + __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) +#define UPT_FS(r) \ + __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) +#define UPT_GS(r) \ + __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) #define UPT_SYSCALL_ARG1(r) UPT_EBX(r) #define UPT_SYSCALL_ARG2(r) UPT_ECX(r) @@ -88,19 +134,20 @@ struct uml_pt_regs { extern int user_context(unsigned long sp); -#define UPT_IS_USER(r) ((r)->is_user) +#define UPT_IS_USER(r) \ + CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) struct syscall_args { unsigned long args[6]; }; #define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) #define UPT_REG(regs, reg) \ ({ unsigned long val; \ @@ -128,6 +175,7 @@ struct syscall_args { } \ val; \ }) + #define UPT_SET(regs, reg, val) \ do { \ @@ -156,16 +204,29 @@ struct syscall_args { } while (0) #define UPT_SET_SYSCALL_RETURN(r, res) \ - REGS_SET_SYSCALL_RETURN((r)->regs, (res)) + CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ + REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) -#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) +#define UPT_RESTART_SYSCALL(r) \ + CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ + REGS_RESTART_SYSCALL((r)->skas.regs)) #define UPT_ORIG_SYSCALL(r) UPT_EAX(r) #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) #define UPT_SYSCALL_RET(r) UPT_EAX(r) -#define UPT_FAULTINFO(r) (&(r)->faultinfo) - -extern void arch_init_registers(int pid); +#define UPT_FAULTINFO(r) \ + CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/sysdep-i386/sigcontext.h b/trunk/arch/um/include/sysdep-i386/sigcontext.h index 67e77122aa45..23fd2644d7ed 100644 --- a/trunk/arch/um/include/sysdep-i386/sigcontext.h +++ b/trunk/arch/um/include/sysdep-i386/sigcontext.h @@ -1,15 +1,19 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __SYS_SIGCONTEXT_I386_H #define __SYS_SIGCONTEXT_I386_H -#include "sysdep/sc.h" +#include "uml-config.h" +#include #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) +#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) +#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) + #define GET_FAULTINFO_FROM_SC(fi,sc) \ { \ (fi).cr2 = SC_CR2(sc); \ @@ -17,10 +21,32 @@ (fi).trap_no = SC_TRAPNO(sc); \ } +/* ptrace expects that, at the start of a system call, %eax contains + * -ENOSYS, so this makes it so. + */ +#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) + /* This is Page Fault */ #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) /* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ +#ifdef UML_CONFIG_MODE_SKAS #define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) +#else +#define SEGV_MAYBE_FIXABLE(fi) 0 +#endif + +extern unsigned long *sc_sigmask(void *sc_ptr); +extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/sysdep-i386/stub.h b/trunk/arch/um/include/sysdep-i386/stub.h index 8c097b87fca7..4fffae75ba53 100644 --- a/trunk/arch/um/include/sysdep-i386/stub.h +++ b/trunk/arch/um/include/sysdep-i386/stub.h @@ -9,7 +9,7 @@ #include #include #include -#include "as-layout.h" +#include #include "stub-data.h" #include "kern_constants.h" #include "uml-config.h" @@ -19,7 +19,7 @@ extern void stub_clone_handler(void); #define STUB_SYSCALL_RET EAX #define STUB_MMAP_NR __NR_mmap2 -#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT) +#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) static inline long stub_syscall0(long syscall) { @@ -90,12 +90,12 @@ static inline void remap_stack(int fd, unsigned long offset) { __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" "movl %7, %%ebx ; movl %%eax, (%%ebx)" - : : "g" (STUB_MMAP_NR), "b" (STUB_DATA), - "c" (UM_KERN_PAGE_SIZE), + : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA), + "c" (UM_KERN_PAGE_SIZE), "d" (PROT_READ | PROT_WRITE), - "S" (MAP_FIXED | MAP_SHARED), "D" (fd), - "a" (offset), - "i" (&((struct stub_data *) STUB_DATA)->err) + "S" (MAP_FIXED | MAP_SHARED), "D" (fd), + "a" (offset), + "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) : "memory"); } diff --git a/trunk/arch/um/include/sysdep-i386/thread.h b/trunk/arch/um/include/sysdep-i386/thread.h new file mode 100644 index 000000000000..243fed44d780 --- /dev/null +++ b/trunk/arch/um/include/sysdep-i386/thread.h @@ -0,0 +1,11 @@ +#ifndef __UM_THREAD_H +#define __UM_THREAD_H + +#include + +#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS])) +#ifdef UML_CONFIG_MODE_TT +#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) +#endif + +#endif diff --git a/trunk/arch/um/include/sysdep-x86_64/ptrace.h b/trunk/arch/um/include/sysdep-x86_64/ptrace.h index 9ea44d111f33..62403bd99661 100644 --- a/trunk/arch/um/include/sysdep-x86_64/ptrace.h +++ b/trunk/arch/um/include/sysdep-x86_64/ptrace.h @@ -1,6 +1,5 @@ /* * Copyright 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * Licensed under the GPL */ @@ -15,6 +14,11 @@ #define MAX_REG_OFFSET (UM_FRAME_SIZE) #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) +#ifdef UML_CONFIG_MODE_TT +#include "sysdep/sc.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS #include "skas_ptregs.h" #define REGS_IP(r) ((r)[HOST_IP]) @@ -84,51 +88,78 @@ #define REGS_ERR(r) ((r)->fault_type) -struct uml_pt_regs { - unsigned long gp[MAX_REG_NR]; - struct faultinfo faultinfo; - long syscall; - int is_user; +#endif + +#include "choose-mode.h" + +/* XXX */ +union uml_pt_regs { +#ifdef UML_CONFIG_MODE_TT + struct tt_regs { + long syscall; + unsigned long orig_rax; + void *sc; + struct faultinfo faultinfo; + } tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { + unsigned long regs[MAX_REG_NR]; + unsigned long fp[HOST_FP_SIZE]; + struct faultinfo faultinfo; + long syscall; + int is_user; + } skas; +#endif }; #define EMPTY_UML_PT_REGS { } -#define UPT_RBX(r) REGS_RBX((r)->gp) -#define UPT_RCX(r) REGS_RCX((r)->gp) -#define UPT_RDX(r) REGS_RDX((r)->gp) -#define UPT_RSI(r) REGS_RSI((r)->gp) -#define UPT_RDI(r) REGS_RDI((r)->gp) -#define UPT_RBP(r) REGS_RBP((r)->gp) -#define UPT_RAX(r) REGS_RAX((r)->gp) -#define UPT_R8(r) REGS_R8((r)->gp) -#define UPT_R9(r) REGS_R9((r)->gp) -#define UPT_R10(r) REGS_R10((r)->gp) -#define UPT_R11(r) REGS_R11((r)->gp) -#define UPT_R12(r) REGS_R12((r)->gp) -#define UPT_R13(r) REGS_R13((r)->gp) -#define UPT_R14(r) REGS_R14((r)->gp) -#define UPT_R15(r) REGS_R15((r)->gp) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp) -#define UPT_FS(r) REGS_FS((r)->gp) -#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp) -#define UPT_GS(r) REGS_GS((r)->gp) -#define UPT_DS(r) REGS_DS((r)->gp) -#define UPT_ES(r) REGS_ES((r)->gp) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_SS(r) REGS_SS((r)->gp) -#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp) - -#define UPT_IP(r) REGS_IP((r)->gp) -#define UPT_SP(r) REGS_SP((r)->gp) - -#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) -#define UPT_SYSCALL_NR(r) ((r)->syscall) +/* XXX */ +extern int mode_tt; + +#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs)) +#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs)) +#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs)) +#define UPT_RSI(r) __CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs)) +#define UPT_RDI(r) __CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs)) +#define UPT_RBP(r) __CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs)) +#define UPT_RAX(r) __CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs)) +#define UPT_R8(r) __CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs)) +#define UPT_R9(r) __CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs)) +#define UPT_R10(r) __CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs)) +#define UPT_R11(r) __CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs)) +#define UPT_R12(r) __CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs)) +#define UPT_R13(r) __CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs)) +#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) +#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) +#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_FS_BASE(r) \ + __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs)) +#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) +#define UPT_GS_BASE(r) \ + __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs)) +#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) +#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) +#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) +#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) +#define UPT_ORIG_RAX(r) \ + __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) + +#define UPT_IP(r) __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) +#define UPT_SP(r) __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) + +#define UPT_EFLAGS(r) \ + __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) +#define UPT_SC(r) ((r)->tt.sc) +#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) #define UPT_SYSCALL_RET(r) UPT_RAX(r) extern int user_context(unsigned long sp); -#define UPT_IS_USER(r) ((r)->is_user) +#define UPT_IS_USER(r) \ + CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) #define UPT_SYSCALL_ARG1(r) UPT_RDI(r) #define UPT_SYSCALL_ARG2(r) UPT_RSI(r) @@ -142,99 +173,101 @@ struct syscall_args { }; #define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) #define UPT_REG(regs, reg) \ - ({ unsigned long val; \ - switch(reg){ \ - case R8: val = UPT_R8(regs); break; \ - case R9: val = UPT_R9(regs); break; \ - case R10: val = UPT_R10(regs); break; \ - case R11: val = UPT_R11(regs); break; \ - case R12: val = UPT_R12(regs); break; \ - case R13: val = UPT_R13(regs); break; \ - case R14: val = UPT_R14(regs); break; \ - case R15: val = UPT_R15(regs); break; \ - case RIP: val = UPT_IP(regs); break; \ - case RSP: val = UPT_SP(regs); break; \ - case RAX: val = UPT_RAX(regs); break; \ - case RBX: val = UPT_RBX(regs); break; \ - case RCX: val = UPT_RCX(regs); break; \ - case RDX: val = UPT_RDX(regs); break; \ - case RSI: val = UPT_RSI(regs); break; \ - case RDI: val = UPT_RDI(regs); break; \ - case RBP: val = UPT_RBP(regs); break; \ - case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ - case CS: val = UPT_CS(regs); break; \ - case SS: val = UPT_SS(regs); break; \ - case FS_BASE: val = UPT_FS_BASE(regs); break; \ - case GS_BASE: val = UPT_GS_BASE(regs); break; \ - case DS: val = UPT_DS(regs); break; \ - case ES: val = UPT_ES(regs); break; \ - case FS : val = UPT_FS (regs); break; \ - case GS: val = UPT_GS(regs); break; \ - case EFLAGS: val = UPT_EFLAGS(regs); break; \ - default : \ - panic("Bad register in UPT_REG : %d\n", reg); \ - val = -1; \ - } \ - val; \ - }) + ({ unsigned long val; \ + switch(reg){ \ + case R8: val = UPT_R8(regs); break; \ + case R9: val = UPT_R9(regs); break; \ + case R10: val = UPT_R10(regs); break; \ + case R11: val = UPT_R11(regs); break; \ + case R12: val = UPT_R12(regs); break; \ + case R13: val = UPT_R13(regs); break; \ + case R14: val = UPT_R14(regs); break; \ + case R15: val = UPT_R15(regs); break; \ + case RIP: val = UPT_IP(regs); break; \ + case RSP: val = UPT_SP(regs); break; \ + case RAX: val = UPT_RAX(regs); break; \ + case RBX: val = UPT_RBX(regs); break; \ + case RCX: val = UPT_RCX(regs); break; \ + case RDX: val = UPT_RDX(regs); break; \ + case RSI: val = UPT_RSI(regs); break; \ + case RDI: val = UPT_RDI(regs); break; \ + case RBP: val = UPT_RBP(regs); break; \ + case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ + case CS: val = UPT_CS(regs); break; \ + case SS: val = UPT_SS(regs); break; \ + case FS_BASE: val = UPT_FS_BASE(regs); break; \ + case GS_BASE: val = UPT_GS_BASE(regs); break; \ + case DS: val = UPT_DS(regs); break; \ + case ES: val = UPT_ES(regs); break; \ + case FS : val = UPT_FS (regs); break; \ + case GS: val = UPT_GS(regs); break; \ + case EFLAGS: val = UPT_EFLAGS(regs); break; \ + default : \ + panic("Bad register in UPT_REG : %d\n", reg); \ + val = -1; \ + } \ + val; \ + }) #define UPT_SET(regs, reg, val) \ - ({ unsigned long __upt_val = val; \ - switch(reg){ \ - case R8: UPT_R8(regs) = __upt_val; break; \ - case R9: UPT_R9(regs) = __upt_val; break; \ - case R10: UPT_R10(regs) = __upt_val; break; \ - case R11: UPT_R11(regs) = __upt_val; break; \ - case R12: UPT_R12(regs) = __upt_val; break; \ - case R13: UPT_R13(regs) = __upt_val; break; \ - case R14: UPT_R14(regs) = __upt_val; break; \ - case R15: UPT_R15(regs) = __upt_val; break; \ - case RIP: UPT_IP(regs) = __upt_val; break; \ - case RSP: UPT_SP(regs) = __upt_val; break; \ - case RAX: UPT_RAX(regs) = __upt_val; break; \ - case RBX: UPT_RBX(regs) = __upt_val; break; \ - case RCX: UPT_RCX(regs) = __upt_val; break; \ - case RDX: UPT_RDX(regs) = __upt_val; break; \ - case RSI: UPT_RSI(regs) = __upt_val; break; \ - case RDI: UPT_RDI(regs) = __upt_val; break; \ - case RBP: UPT_RBP(regs) = __upt_val; break; \ - case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ - case CS: UPT_CS(regs) = __upt_val; break; \ - case SS: UPT_SS(regs) = __upt_val; break; \ - case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ - case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ - case DS: UPT_DS(regs) = __upt_val; break; \ - case ES: UPT_ES(regs) = __upt_val; break; \ - case FS: UPT_FS(regs) = __upt_val; break; \ - case GS: UPT_GS(regs) = __upt_val; break; \ - case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ - default : \ - panic("Bad register in UPT_SET : %d\n", reg); \ - break; \ - } \ - __upt_val; \ - }) + ({ unsigned long __upt_val = val; \ + switch(reg){ \ + case R8: UPT_R8(regs) = __upt_val; break; \ + case R9: UPT_R9(regs) = __upt_val; break; \ + case R10: UPT_R10(regs) = __upt_val; break; \ + case R11: UPT_R11(regs) = __upt_val; break; \ + case R12: UPT_R12(regs) = __upt_val; break; \ + case R13: UPT_R13(regs) = __upt_val; break; \ + case R14: UPT_R14(regs) = __upt_val; break; \ + case R15: UPT_R15(regs) = __upt_val; break; \ + case RIP: UPT_IP(regs) = __upt_val; break; \ + case RSP: UPT_SP(regs) = __upt_val; break; \ + case RAX: UPT_RAX(regs) = __upt_val; break; \ + case RBX: UPT_RBX(regs) = __upt_val; break; \ + case RCX: UPT_RCX(regs) = __upt_val; break; \ + case RDX: UPT_RDX(regs) = __upt_val; break; \ + case RSI: UPT_RSI(regs) = __upt_val; break; \ + case RDI: UPT_RDI(regs) = __upt_val; break; \ + case RBP: UPT_RBP(regs) = __upt_val; break; \ + case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ + case CS: UPT_CS(regs) = __upt_val; break; \ + case SS: UPT_SS(regs) = __upt_val; break; \ + case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ + case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ + case DS: UPT_DS(regs) = __upt_val; break; \ + case ES: UPT_ES(regs) = __upt_val; break; \ + case FS: UPT_FS(regs) = __upt_val; break; \ + case GS: UPT_GS(regs) = __upt_val; break; \ + case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ + default : \ + panic("Bad register in UPT_SET : %d\n", reg); \ + break; \ + } \ + __upt_val; \ + }) #define UPT_SET_SYSCALL_RETURN(r, res) \ - REGS_SET_SYSCALL_RETURN((r)->regs, (res)) - -#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) + CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ + REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) -#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas) +#define UPT_RESTART_SYSCALL(r) \ + CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ + REGS_RESTART_SYSCALL((r)->skas.regs)) -#define UPT_FAULTINFO(r) (&(r)->faultinfo) +#define UPT_SEGV_IS_FIXABLE(r) \ + CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ + REGS_SEGV_IS_FIXABLE(&r->skas)) -static inline void arch_init_registers(int pid) -{ -} +#define UPT_FAULTINFO(r) \ + CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) #endif diff --git a/trunk/arch/um/include/sysdep-x86_64/sigcontext.h b/trunk/arch/um/include/sysdep-x86_64/sigcontext.h index 0155133b1458..41073235e7ad 100644 --- a/trunk/arch/um/include/sysdep-x86_64/sigcontext.h +++ b/trunk/arch/um/include/sysdep-x86_64/sigcontext.h @@ -11,17 +11,43 @@ #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -#define GET_FAULTINFO_FROM_SC(fi, sc) \ +#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) +#define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result) + +#define SC_FAULT_ADDR(sc) SC_CR2(sc) +#define SC_FAULT_TYPE(sc) SC_ERR(sc) + +#define GET_FAULTINFO_FROM_SC(fi,sc) \ { \ (fi).cr2 = SC_CR2(sc); \ (fi).error_code = SC_ERR(sc); \ (fi).trap_no = SC_TRAPNO(sc); \ } +/* ptrace expects that, at the start of a system call, %eax contains + * -ENOSYS, so this makes it so. + */ + +#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) + /* This is Page Fault */ #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) /* No broken SKAS API, which doesn't pass trap_no, here. */ #define SEGV_MAYBE_FIXABLE(fi) 0 +extern unsigned long *sc_sigmask(void *sc_ptr); + #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ + diff --git a/trunk/arch/um/include/sysdep-x86_64/stub.h b/trunk/arch/um/include/sysdep-x86_64/stub.h index 655f9c2de3ac..92e989f81761 100644 --- a/trunk/arch/um/include/sysdep-x86_64/stub.h +++ b/trunk/arch/um/include/sysdep-x86_64/stub.h @@ -9,7 +9,6 @@ #include #include #include -#include "as-layout.h" #include "stub-data.h" #include "kern_constants.h" #include "uml-config.h" @@ -95,13 +94,13 @@ static inline void remap_stack(long fd, unsigned long offset) { __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " - "movq %%rax, (%%rbx)": - : "a" (STUB_MMAP_NR), "D" (STUB_DATA), - "S" (UM_KERN_PAGE_SIZE), - "d" (PROT_READ | PROT_WRITE), - "g" (MAP_FIXED | MAP_SHARED), "g" (fd), + "movq %%rax, (%%rbx)": + : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA), + "S" (UM_KERN_PAGE_SIZE), + "d" (PROT_READ | PROT_WRITE), + "g" (MAP_FIXED | MAP_SHARED), "g" (fd), "g" (offset), - "i" (&((struct stub_data *) STUB_DATA)->err) + "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) : __syscall_clobber, "r10", "r8", "r9" ); } diff --git a/trunk/arch/um/include/sysdep-x86_64/thread.h b/trunk/arch/um/include/sysdep-x86_64/thread.h new file mode 100644 index 000000000000..cbef3e1697f4 --- /dev/null +++ b/trunk/arch/um/include/sysdep-x86_64/thread.h @@ -0,0 +1,10 @@ +#ifndef __UM_THREAD_H +#define __UM_THREAD_H + +#include + +#ifdef UML_CONFIG_MODE_TT +#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) +#endif + +#endif diff --git a/trunk/arch/um/include/task.h b/trunk/arch/um/include/task.h index 3fe726b3cf48..6375ba7203c9 100644 --- a/trunk/arch/um/include/task.h +++ b/trunk/arch/um/include/task.h @@ -3,7 +3,7 @@ #include -#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) +#define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) #define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) #endif diff --git a/trunk/arch/um/include/tlb.h b/trunk/arch/um/include/tlb.h index ecd2265b301b..bcd1a4afb842 100644 --- a/trunk/arch/um/include/tlb.h +++ b/trunk/arch/um/include/tlb.h @@ -8,7 +8,34 @@ #include "um_mmu.h" +struct host_vm_op { + enum { NONE, MMAP, MUNMAP, MPROTECT } type; + union { + struct { + unsigned long addr; + unsigned long len; + unsigned int prot; + int fd; + __u64 offset; + } mmap; + struct { + unsigned long addr; + unsigned long len; + } munmap; + struct { + unsigned long addr; + unsigned long len; + unsigned int prot; + } mprotect; + } u; +}; + extern void force_flush_all(void); +extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr, + unsigned long end_addr, int force, + int (*do_ops)(union mm_context *, + struct host_vm_op *, int, int, + void **)); extern int flush_tlb_kernel_range_common(unsigned long start, unsigned long end); diff --git a/trunk/arch/um/include/tt/debug.h b/trunk/arch/um/include/tt/debug.h new file mode 100644 index 000000000000..9778fa838296 --- /dev/null +++ b/trunk/arch/um/include/tt/debug.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and + * Lars Brinkhoff. + * Licensed under the GPL + */ + +#ifndef __UML_TT_DEBUG_H +#define __UML_TT_DEBUG_H + +extern int debugger_proxy(int status, pid_t pid); +extern void child_proxy(pid_t pid, int status); +extern void init_proxy (pid_t pid, int waiting, int status); +extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); +extern void fake_child_exit(void); +extern int gdb_config(char *str); +extern int gdb_remove(int unused); + +#endif diff --git a/trunk/arch/um/include/tt/mmu-tt.h b/trunk/arch/um/include/tt/mmu-tt.h new file mode 100644 index 000000000000..572a78b22587 --- /dev/null +++ b/trunk/arch/um/include/tt/mmu-tt.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_MMU_H +#define __TT_MMU_H + +struct mmu_context_tt { +}; + +#endif diff --git a/trunk/arch/um/include/tt/mode-tt.h b/trunk/arch/um/include/tt/mode-tt.h new file mode 100644 index 000000000000..2823cd56eea2 --- /dev/null +++ b/trunk/arch/um/include/tt/mode-tt.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_TT_H__ +#define __MODE_TT_H__ + +#include "sysdep/ptrace.h" + +enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + +extern int tracing_pid; + +extern int tracer(int (*init_proc)(void *), void *sp); +extern void sig_handler_common_tt(int sig, void *sc); +extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); +extern void reboot_tt(void); +extern void halt_tt(void); +extern int is_tracer_winch(int pid, int fd, void *data); +extern void kill_off_processes_tt(void); + +#endif diff --git a/trunk/arch/um/include/tt/mode_kern_tt.h b/trunk/arch/um/include/tt/mode_kern_tt.h new file mode 100644 index 000000000000..a4fc63057195 --- /dev/null +++ b/trunk/arch/um/include/tt/mode_kern_tt.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_MODE_KERN_H__ +#define __TT_MODE_KERN_H__ + +#include "linux/sched.h" +#include "asm/page.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" + +extern void switch_to_tt(void *prev, void *next); +extern void flush_thread_tt(void); +extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, + unsigned long esp); +extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct *p, + struct pt_regs *regs); +extern void release_thread_tt(struct task_struct *task); +extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); +extern void init_idle_tt(void); +extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); +extern void flush_tlb_kernel_vm_tt(void); +extern void __flush_tlb_one_tt(unsigned long addr); +extern void flush_tlb_range_tt(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +extern void flush_tlb_mm_tt(struct mm_struct *mm); +extern void force_flush_all_tt(void); +extern long execute_syscall_tt(void *r); +extern void before_mem_tt(unsigned long brk_start); +extern unsigned long set_task_sizes_tt(unsigned long *task_size_out); +extern int start_uml_tt(void); +extern int external_pid_tt(struct task_struct *task); +extern int thread_pid_tt(struct task_struct *task); + +#define kmem_end_tt (host_task_size - ABOVE_KMEM) + +#endif diff --git a/trunk/arch/um/include/tt/tt.h b/trunk/arch/um/include/tt/tt.h new file mode 100644 index 000000000000..acb8356e1f98 --- /dev/null +++ b/trunk/arch/um/include/tt/tt.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_H__ +#define __TT_H__ + +#include "sysdep/ptrace.h" + +extern int gdb_pid; +extern int debug; +extern int debug_stop; +extern int debug_trace; + +extern int honeypot; + +extern int fork_tramp(void *sig_stack); +extern int do_proc_op(void *t, int proc_id); +extern int tracer(int (*init_proc)(void *), void *sp); +extern void attach_process(int pid); +extern void tracer_panic(char *format, ...) + __attribute__ ((format (printf, 1, 2))); +extern void set_init_pid(int pid); +extern int set_user_mode(void *task); +extern void set_tracing(void *t, int tracing); +extern int is_tracing(void *task); +extern void syscall_handler(int sig, union uml_pt_regs *regs); +extern void exit_kernel(int pid, void *task); +extern void do_syscall(void *task, int pid, int local_using_sysemu); +extern void do_sigtrap(void *task); +extern int is_valid_pid(int pid); +extern void remap_data(void *segment_start, void *segment_end, int w); +extern long execute_syscall_tt(void *r); + +#endif + diff --git a/trunk/arch/um/include/tt/uaccess-tt.h b/trunk/arch/um/include/tt/uaccess-tt.h new file mode 100644 index 000000000000..13a64f61fcf4 --- /dev/null +++ b/trunk/arch/um/include/tt/uaccess-tt.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#ifndef __TT_UACCESS_H +#define __TT_UACCESS_H + +#include "linux/string.h" +#include "linux/sched.h" +#include "asm/processor.h" +#include "asm/errno.h" +#include "asm/current.h" +#include "asm/a.out.h" +#include "uml_uaccess.h" + +#define ABOVE_KMEM (16 * 1024 * 1024) + +extern unsigned long end_vm; +extern unsigned long uml_physmem; + +#define is_stack(addr, size) \ + (((unsigned long) (addr) < STACK_TOP) && \ + ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ + (((unsigned long) (addr) + (size)) <= STACK_TOP)) + +#define access_ok_tt(type, addr, size) \ + (is_stack(addr, size)) + +extern int __do_copy_from_user(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher); +extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, + void **fault_addr, void **fault_catcher); +extern int __do_clear_user(void *mem, size_t len, void **fault_addr, + void **fault_catcher); +extern int __do_strnlen_user(const char *str, unsigned long n, + void **fault_addr, void **fault_catcher); + +extern int copy_from_user_tt(void *to, const void __user *from, int n); +extern int copy_to_user_tt(void __user *to, const void *from, int n); +extern int strncpy_from_user_tt(char *dst, const char __user *src, int count); +extern int __clear_user_tt(void __user *mem, int len); +extern int clear_user_tt(void __user *mem, int len); +extern int strnlen_user_tt(const void __user *str, int len); + +#endif diff --git a/trunk/arch/um/include/um_mmu.h b/trunk/arch/um/include/um_mmu.h index 8855d8df512f..0fa643238300 100644 --- a/trunk/arch/um/include/um_mmu.h +++ b/trunk/arch/um/include/um_mmu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -7,22 +7,34 @@ #define __ARCH_UM_MMU_H #include "uml-config.h" -#include "mm_id.h" -#include "asm/ldt.h" +#include "choose-mode.h" -typedef struct mm_context { - struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; +#ifdef UML_CONFIG_MODE_TT +#include "mmu-tt.h" #endif - struct uml_ldt ldt; -} mm_context_t; -extern void __switch_mm(struct mm_id * mm_idp); +#ifdef UML_CONFIG_MODE_SKAS +#include "mmu-skas.h" +#endif -/* Avoid tangled inclusion with asm/ldt.h */ -extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); -extern void free_ldt(struct mm_context *mm); +typedef union mm_context { +#ifdef UML_CONFIG_MODE_TT + struct mmu_context_tt tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct mmu_context_skas skas; +#endif +} mm_context_t; #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/um_uaccess.h b/trunk/arch/um/include/um_uaccess.h index fdfc06b85605..5126a99b5961 100644 --- a/trunk/arch/um/include/um_uaccess.h +++ b/trunk/arch/um/include/um_uaccess.h @@ -1,16 +1,26 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #ifndef __ARCH_UM_UACCESS_H #define __ARCH_UM_UACCESS_H +#include "choose-mode.h" + +#ifdef CONFIG_MODE_TT +#include "uaccess-tt.h" +#endif + +#ifdef CONFIG_MODE_SKAS +#include "uaccess-skas.h" +#endif + #include "asm/fixmap.h" #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) + (((unsigned long) (addr) + (size)) < TASK_SIZE)) #define __access_ok_vsyscall(type, addr, size) \ ((type == VERIFY_READ) && \ @@ -25,14 +35,20 @@ (__addr_range_nowrap(addr, size) && \ (__under_task_size(addr, size) || \ __access_ok_vsyscall(type, addr, size) || \ - segment_eq(get_fs(), KERNEL_DS))) + segment_eq(get_fs(), KERNEL_DS) || \ + CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) -extern int copy_from_user(void *to, const void __user *from, int n); -extern int copy_to_user(void __user *to, const void *from, int n); +static inline int copy_from_user(void *to, const void __user *from, int n) +{ + return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, + from, n)); +} -extern int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher); -extern void __do_copy(void *to, const void *from, int n); +static inline int copy_to_user(void __user *to, const void *from, int n) +{ + return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, + from, n)); +} /* * strncpy_from_user: - Copy a NUL terminated string from userspace. @@ -53,7 +69,11 @@ extern void __do_copy(void *to, const void *from, int n); * and returns @count. */ -extern int strncpy_from_user(char *dst, const char __user *src, int count); +static inline int strncpy_from_user(char *dst, const char __user *src, int count) +{ + return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, + dst, src, count)); +} /* * __clear_user: - Zero a block of memory in user space, with less checking. @@ -66,7 +86,10 @@ extern int strncpy_from_user(char *dst, const char __user *src, int count); * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -extern int __clear_user(void __user *mem, int len); +static inline int __clear_user(void *mem, int len) +{ + return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); +} /* * clear_user: - Zero a block of memory in user space. @@ -78,7 +101,10 @@ extern int __clear_user(void __user *mem, int len); * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -extern int clear_user(void __user *mem, int len); +static inline int clear_user(void __user *mem, int len) +{ + return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); +} /* * strlen_user: - Get the size of a string in user space. @@ -91,6 +117,20 @@ extern int clear_user(void __user *mem, int len); * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -extern int strnlen_user(const void __user *str, int len); +static inline int strnlen_user(const void __user *str, long len) +{ + return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); +} #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/uml_uaccess.h b/trunk/arch/um/include/uml_uaccess.h new file mode 100644 index 000000000000..c0df11d06f5e --- /dev/null +++ b/trunk/arch/um/include/uml_uaccess.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __UML_UACCESS_H__ +#define __UML_UACCESS_H__ + +extern int __do_copy_to_user(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher); +void __do_copy(void *to, const void *from, int n); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/user.h b/trunk/arch/um/include/user.h index 99033ff28a78..d380e6d91a90 100644 --- a/trunk/arch/um/include/user.h +++ b/trunk/arch/um/include/user.h @@ -14,12 +14,10 @@ */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -/* This is to get size_t */ -#ifdef __KERNEL__ +/* + * This will provide the size_t definition in both kernel and userspace builds + */ #include -#else -#include -#endif extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/trunk/arch/um/kernel/Makefile b/trunk/arch/um/kernel/Makefile index 499e5e95e609..c5cf4a0827b0 100644 --- a/trunk/arch/um/kernel/Makefile +++ b/trunk/arch/um/kernel/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com) +# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -9,12 +9,15 @@ clean-files := obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ physmem.o process.o ptrace.o reboot.o sigio.o \ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ - um_arch.o umid.o skas/ + um_arch.o umid.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o +obj-$(CONFIG_MODE_TT) += tt/ +obj-$(CONFIG_MODE_SKAS) += skas/ + USER_OBJS := config.o include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/kernel/dyn.lds.S b/trunk/arch/um/kernel/dyn.lds.S index 3866f4960f04..41850906116e 100644 --- a/trunk/arch/um/kernel/dyn.lds.S +++ b/trunk/arch/um/kernel/dyn.lds.S @@ -10,6 +10,8 @@ SECTIONS PROVIDE (__executable_start = START); . = START + SIZEOF_HEADERS; .interp : { *(.interp) } + /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start + * is remapped.*/ __binary_start = .; . = ALIGN(4096); /* Init code and data */ _text = .; diff --git a/trunk/arch/um/kernel/exec.c b/trunk/arch/um/kernel/exec.c index 8196450451cd..ce6828fd396f 100644 --- a/trunk/arch/um/kernel/exec.c +++ b/trunk/arch/um/kernel/exec.c @@ -1,44 +1,35 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/fs.h" +#include "linux/slab.h" #include "linux/smp_lock.h" #include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/current.h" -#include "asm/processor.h" +#include "linux/fs.h" +#include "asm/ptrace.h" +#include "asm/pgtable.h" +#include "asm/tlbflush.h" #include "asm/uaccess.h" +#include "kern_util.h" #include "as-layout.h" #include "mem_user.h" -#include "skas.h" +#include "kern.h" +#include "irq_user.h" +#include "tlb.h" #include "os.h" +#include "choose-mode.h" +#include "mode_kern.h" void flush_thread(void) { - void *data = NULL; - unsigned long end = proc_mm ? task_size : STUB_START; - int ret; - arch_flush_thread(¤t->thread.arch); - - ret = unmap(¤t->mm->context.id, 0, end, 1, &data); - if (ret) { - printk(KERN_ERR "flush_thread - clearing address space failed, " - "err = %d\n", ret); - force_sig(SIGKILL, current); - } - - __switch_mm(¤t->mm->context.id); + CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); } void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - set_fs(USER_DS); - PT_REGS_IP(regs) = eip; - PT_REGS_SP(regs) = esp; + CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); } #ifdef CONFIG_TTY_LOG @@ -48,7 +39,7 @@ extern void log_exec(char **argv, void *tty); static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { - long error; + long error; #ifdef CONFIG_TTY_LOG struct tty_struct *tty; @@ -58,16 +49,17 @@ static long execve1(char *file, char __user * __user *argv, log_exec(argv, tty); mutex_unlock(&tty_mutex); #endif - error = do_execve(file, argv, env, ¤t->thread.regs); - if (error == 0) { + error = do_execve(file, argv, env, ¤t->thread.regs); + if (error == 0){ task_lock(current); - current->ptrace &= ~PT_DTRACE; + current->ptrace &= ~PT_DTRACE; #ifdef SUBARCH_EXECVE1 SUBARCH_EXECVE1(¤t->thread.regs.regs); #endif task_unlock(current); - } - return error; + set_cmdline(current_cmd()); + } + return(error); } long um_execve(char *file, char __user *__user *argv, char __user *__user *env) @@ -75,9 +67,9 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env) long err; err = execve1(file, argv, env); - if (!err) - UML_LONGJMP(current->thread.exec_buf, 1); - return err; + if(!err) + do_longjmp(current->thread.exec_buf, 1); + return(err); } long sys_execve(char __user *file, char __user *__user *argv, @@ -94,5 +86,5 @@ long sys_execve(char __user *file, char __user *__user *argv, putname(filename); out: unlock_kernel(); - return error; + return(error); } diff --git a/trunk/arch/um/kernel/init_task.c b/trunk/arch/um/kernel/init_task.c index dcfceca95052..cba516e6c99a 100644 --- a/trunk/arch/um/kernel/init_task.c +++ b/trunk/arch/um/kernel/init_task.c @@ -3,12 +3,16 @@ * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/init_task.h" +#include "linux/mm.h" #include "linux/fs.h" #include "linux/module.h" +#include "linux/sched.h" +#include "linux/init_task.h" #include "linux/mqueue.h" #include "asm/uaccess.h" +#include "asm/pgtable.h" +#include "mem_user.h" +#include "os.h" static struct fs_struct init_fs = INIT_FS; struct mm_struct init_mm = INIT_MM(init_mm); @@ -42,3 +46,8 @@ union thread_union init_thread_union union thread_union cpu0_irqstack __attribute__((__section__(".data.init_irqstack"))) = { INIT_THREAD_INFO(init_task) }; + +void unprotect_stack(unsigned long stack) +{ + os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0); +} diff --git a/trunk/arch/um/kernel/irq.c b/trunk/arch/um/kernel/irq.c index 277fce17b088..cf0dd9cf8c43 100644 --- a/trunk/arch/um/kernel/irq.c +++ b/trunk/arch/um/kernel/irq.c @@ -1,19 +1,37 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar */ -#include "linux/cpumask.h" -#include "linux/hardirq.h" -#include "linux/interrupt.h" -#include "linux/kernel_stat.h" +#include "linux/kernel.h" #include "linux/module.h" +#include "linux/smp.h" +#include "linux/kernel_stat.h" +#include "linux/interrupt.h" +#include "linux/random.h" +#include "linux/slab.h" +#include "linux/file.h" +#include "linux/proc_fs.h" +#include "linux/init.h" #include "linux/seq_file.h" -#include "as-layout.h" +#include "linux/profile.h" +#include "linux/hardirq.h" +#include "asm/irq.h" +#include "asm/hw_irq.h" +#include "asm/atomic.h" +#include "asm/signal.h" +#include "asm/system.h" +#include "asm/errno.h" +#include "asm/uaccess.h" #include "kern_util.h" +#include "irq_user.h" +#include "irq_kern.h" #include "os.h" +#include "sigio.h" +#include "misc_constants.h" +#include "as-layout.h" /* * Generic, controller-independent functions: @@ -53,8 +71,9 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) + } else if (i == NR_IRQS) { seq_putc(p, '\n'); + } return 0; } @@ -72,7 +91,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; extern void free_irqs(void); -void sigio_handler(int sig, struct uml_pt_regs *regs) +void sigio_handler(int sig, union uml_pt_regs *regs) { struct irq_fd *irq_fd; int n; @@ -83,13 +102,11 @@ void sigio_handler(int sig, struct uml_pt_regs *regs) while (1) { n = os_waiting_for_events(active_fds); if (n <= 0) { - if (n == -EINTR) - continue; + if(n == -EINTR) continue; else break; } - for (irq_fd = active_fds; irq_fd != NULL; - irq_fd = irq_fd->next) { + for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { if (irq_fd->current_events != 0) { irq_fd->current_events = 0; do_IRQ(irq_fd->irq, regs); @@ -121,7 +138,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI; - else events = UM_POLLOUT; + else + events = UM_POLLOUT; *new_fd = ((struct irq_fd) { .next = NULL, .id = dev_id, .fd = fd, @@ -135,10 +153,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id) spin_lock_irqsave(&irq_lock, flags); for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { if ((irq_fd->fd == fd) && (irq_fd->type == type)) { - printk(KERN_ERR "Registering fd %d twice\n", fd); - printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq); - printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id, - dev_id); + printk("Registering fd %d twice\n", fd); + printk("Irqs : %d, %d\n", irq_fd->irq, irq); + printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id); goto out_unlock; } } @@ -154,8 +171,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (n == 0) break; - /* - * n > 0 + /* n > 0 * It means we couldn't put new pollfd to current pollfds * and tmp_fds is NULL or too small for new pollfds array. * Needed size is equal to n as minimum. @@ -181,8 +197,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) spin_unlock_irqrestore(&irq_lock, flags); - /* - * This calls activate_fd, so it has to be outside the critical + /* This calls activate_fd, so it has to be outside the critical * section. */ maybe_sigio_broken(fd, (type == IRQ_READ)); @@ -249,14 +264,13 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) i++; } if (irq == NULL) { - printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n", - fd); + printk("find_irq_by_fd doesn't have descriptor %d\n", fd); goto out; } fdi = os_get_pollfd(i); if ((fdi != -1) && (fdi != fd)) { - printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds " - "and pollfds, fd %d vs %d, need %d\n", irq->fd, + printk("find_irq_by_fd - mismatch between active_fds and " + "pollfds, fd %d vs %d, need %d\n", irq->fd, fdi, fd); irq = NULL; goto out; @@ -292,7 +306,7 @@ void deactivate_fd(int fd, int irqnum) spin_lock_irqsave(&irq_lock, flags); irq = find_irq_by_fd(fd, irqnum, &i); - if (irq == NULL) { + if(irq == NULL){ spin_unlock_irqrestore(&irq_lock, flags); return; } @@ -325,12 +339,36 @@ int deactivate_all_fds(void) return 0; } +#ifdef CONFIG_MODE_TT +void forward_interrupts(int pid) +{ + struct irq_fd *irq; + unsigned long flags; + int err; + + spin_lock_irqsave(&irq_lock, flags); + for (irq = active_fds; irq != NULL; irq = irq->next) { + err = os_set_owner(irq->fd, pid); + if (err < 0) { + /* XXX Just remove the irq rather than + * print out an infinite stream of these + */ + printk("Failed to forward %d to pid %d, err = %d\n", + irq->fd, pid, -err); + } + + irq->pid = pid; + } + spin_unlock_irqrestore(&irq_lock, flags); +} +#endif + /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ -unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) +unsigned int do_IRQ(int irq, union uml_pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); irq_enter(); @@ -358,10 +396,8 @@ int um_request_irq(unsigned int irq, int fd, int type, EXPORT_SYMBOL(um_request_irq); EXPORT_SYMBOL(reactivate_fd); -/* - * hw_interrupt_type must define (startup || enable) && - * (shutdown || disable) && end - */ +/* hw_interrupt_type must define (startup || enable) && + * (shutdown || disable) && end */ static void dummy(unsigned int irq) { } @@ -410,8 +446,7 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) err = os_pipe(fds, 1, 1); if (err) { - printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n", - -err); + printk("init_aio_irq - os_pipe failed, err = %d\n", -err); goto out; } @@ -419,8 +454,7 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, (void *) (long) fds[0]); if (err) { - printk(KERN_ERR "init_aio_irq - : um_request_irq failed, " - "err = %d\n", + printk("init_aio_irq - : um_request_irq failed, err = %d\n", err); goto out_close; } @@ -491,9 +525,8 @@ unsigned long to_irq_stack(unsigned long *mask_out) int nested; mask = xchg(&pending_mask, *mask_out); - if (mask != 0) { - /* - * If any interrupts come in at this point, we want to + if(mask != 0){ + /* If any interrupts come in at this point, we want to * make sure that their bits aren't lost by our * putting our bit in. So, this loop accumulates bits * until xchg returns the same value that we put in. @@ -505,13 +538,13 @@ unsigned long to_irq_stack(unsigned long *mask_out) do { old |= mask; mask = xchg(&pending_mask, old); - } while (mask != old); + } while(mask != old); return 1; } ti = current_thread_info(); nested = (ti->real_thread != NULL); - if (!nested) { + if(!nested){ struct task_struct *task; struct thread_info *tti; diff --git a/trunk/arch/um/kernel/ksyms.c b/trunk/arch/um/kernel/ksyms.c index 1b388b41d95d..7b3e53fb8070 100644 --- a/trunk/arch/um/kernel/ksyms.c +++ b/trunk/arch/um/kernel/ksyms.c @@ -1,15 +1,22 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/module.h" -#include "linux/syscalls.h" -#include "asm/a.out.h" +#include "linux/string.h" +#include "linux/smp_lock.h" +#include "linux/spinlock.h" +#include "linux/highmem.h" +#include "asm/current.h" +#include "asm/processor.h" +#include "asm/unistd.h" +#include "asm/pgalloc.h" +#include "asm/pgtable.h" +#include "asm/page.h" #include "asm/tlbflush.h" -#include "asm/uaccess.h" -#include "as-layout.h" #include "kern_util.h" +#include "as-layout.h" #include "mem_user.h" #include "os.h" @@ -27,19 +34,30 @@ EXPORT_SYMBOL(get_kmem_end); EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(um_virt_to_phys); +EXPORT_SYMBOL(mode_tt); EXPORT_SYMBOL(handle_page_fault); EXPORT_SYMBOL(find_iomem); -EXPORT_SYMBOL(strnlen_user); -EXPORT_SYMBOL(strncpy_from_user); -EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(clear_user); +#ifdef CONFIG_MODE_TT +EXPORT_SYMBOL(stop); +EXPORT_SYMBOL(strncpy_from_user_tt); +EXPORT_SYMBOL(copy_from_user_tt); +EXPORT_SYMBOL(copy_to_user_tt); +#endif + +#ifdef CONFIG_MODE_SKAS +EXPORT_SYMBOL(strnlen_user_skas); +EXPORT_SYMBOL(strncpy_from_user_skas); +EXPORT_SYMBOL(copy_to_user_skas); +EXPORT_SYMBOL(copy_from_user_skas); +EXPORT_SYMBOL(clear_user_skas); +#endif EXPORT_SYMBOL(uml_strdup); EXPORT_SYMBOL(os_stat_fd); EXPORT_SYMBOL(os_stat_file); EXPORT_SYMBOL(os_access); +EXPORT_SYMBOL(os_print_error); EXPORT_SYMBOL(os_get_exec_close); EXPORT_SYMBOL(os_set_exec_close); EXPORT_SYMBOL(os_getpid); @@ -67,6 +85,9 @@ EXPORT_SYMBOL(run_helper); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(do_gettimeofday); +EXPORT_SYMBOL(do_settimeofday); + #ifdef CONFIG_SMP /* required for SMP */ diff --git a/trunk/arch/um/kernel/mem.c b/trunk/arch/um/kernel/mem.c index 8456397f5f4d..d2b11f242698 100644 --- a/trunk/arch/um/kernel/mem.c +++ b/trunk/arch/um/kernel/mem.c @@ -17,7 +17,7 @@ #include "as-layout.h" #include "kern.h" #include "mem_user.h" -#include "um_uaccess.h" +#include "uml_uaccess.h" #include "os.h" #include "linux/types.h" #include "linux/string.h" diff --git a/trunk/arch/um/kernel/physmem.c b/trunk/arch/um/kernel/physmem.c index e66432f42485..5ee7e851bbc1 100644 --- a/trunk/arch/um/kernel/physmem.c +++ b/trunk/arch/um/kernel/physmem.c @@ -1,17 +1,25 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include "linux/bootmem.h" #include "linux/mm.h" +#include "linux/rbtree.h" +#include "linux/slab.h" +#include "linux/vmalloc.h" +#include "linux/bootmem.h" +#include "linux/module.h" #include "linux/pfn.h" -#include "asm/page.h" +#include "asm/types.h" +#include "asm/pgtable.h" +#include "kern_util.h" #include "as-layout.h" -#include "init.h" -#include "kern.h" +#include "mode_kern.h" +#include "mem.h" #include "mem_user.h" #include "os.h" +#include "kern.h" +#include "init.h" static int physmem_fd = -1; @@ -41,10 +49,10 @@ int __init init_maps(unsigned long physmem, unsigned long iomem, total_len = phys_len + iomem_len + highmem_len; map = alloc_bootmem_low_pages(total_len); - if (map == NULL) + if(map == NULL) return -ENOMEM; - for (i = 0; i < total_pages; i++) { + for(i = 0; i < total_pages; i++){ p = &map[i]; memset(p, 0, sizeof(struct page)); SetPageReserved(p); @@ -60,8 +68,8 @@ static unsigned long kmem_top = 0; unsigned long get_kmem_end(void) { - if (kmem_top == 0) - kmem_top = host_task_size - 1024 * 1024; + if(kmem_top == 0) + kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); return kmem_top; } @@ -73,9 +81,9 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, fd = phys_mapping(phys, &offset); err = os_map_memory((void *) virt, fd, offset, len, r, w, x); - if (err) { - if (err == -ENOMEM) - printk(KERN_ERR "try increasing the host's " + if(err) { + if(err == -ENOMEM) + printk("try increasing the host's " "/proc/sys/vm/max_map_count to /4096\n"); panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " @@ -97,16 +105,13 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, offset = uml_reserved - uml_physmem; err = os_map_memory((void *) uml_reserved, physmem_fd, offset, - len - offset, 1, 1, 1); - if (err < 0) { - printf("setup_physmem - mapping %ld bytes of memory at 0x%p " - "failed - errno = %d\n", len - offset, - (void *) uml_reserved, err); + len - offset, 1, 1, 0); + if(err < 0){ + os_print_error(err, "Mapping memory"); exit(1); } - /* - * Special kludge - This page will be mapped in to userspace processes + /* Special kludge - This page will be mapped in to userspace processes * from physmem_fd, so it needs to be written out there. */ os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); @@ -117,20 +122,20 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, len - bootmap_size - reserve); } -int phys_mapping(unsigned long phys, unsigned long long *offset_out) +int phys_mapping(unsigned long phys, __u64 *offset_out) { int fd = -1; - if (phys < physmem_size) { + if(phys < physmem_size){ fd = physmem_fd; *offset_out = phys; } - else if (phys < __pa(end_iomem)) { + else if(phys < __pa(end_iomem)){ struct iomem_region *region = iomem_regions; - while (region != NULL) { - if ((phys >= region->phys) && - (phys < region->phys + region->size)) { + while(region != NULL){ + if((phys >= region->phys) && + (phys < region->phys + region->size)){ fd = region->fd; *offset_out = phys - region->phys; break; @@ -138,7 +143,7 @@ int phys_mapping(unsigned long phys, unsigned long long *offset_out) region = region->next; } } - else if (phys < __pa(end_iomem) + highmem) { + else if(phys < __pa(end_iomem) + highmem){ fd = physmem_fd; *offset_out = phys - iomem_size; } @@ -183,8 +188,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) { struct iomem_region *region = iomem_regions; - while (region != NULL) { - if (!strcmp(region->driver, driver)) { + while(region != NULL){ + if(!strcmp(region->driver, driver)){ *len_out = region->size; return region->virt; } @@ -201,12 +206,12 @@ int setup_iomem(void) unsigned long iomem_start = high_physmem + PAGE_SIZE; int err; - while (region != NULL) { + while(region != NULL){ err = os_map_memory((void *) iomem_start, region->fd, 0, region->size, 1, 1, 0); - if (err) - printk(KERN_ERR "Mapping iomem region for driver '%s' " - "failed, errno = %d\n", region->driver, -err); + if(err) + printk("Mapping iomem region for driver '%s' failed, " + "errno = %d\n", region->driver, -err); else { region->virt = iomem_start; region->phys = __pa(region->virt); diff --git a/trunk/arch/um/kernel/process.c b/trunk/arch/um/kernel/process.c index 0eae00b3e588..bfa52f206bb6 100644 --- a/trunk/arch/um/kernel/process.c +++ b/trunk/arch/um/kernel/process.c @@ -1,30 +1,53 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/err.h" -#include "linux/hardirq.h" +#include "linux/kernel.h" +#include "linux/sched.h" +#include "linux/interrupt.h" +#include "linux/string.h" #include "linux/mm.h" -#include "linux/personality.h" +#include "linux/slab.h" +#include "linux/utsname.h" +#include "linux/fs.h" +#include "linux/utime.h" +#include "linux/smp_lock.h" +#include "linux/module.h" +#include "linux/init.h" +#include "linux/capability.h" +#include "linux/vmalloc.h" +#include "linux/spinlock.h" #include "linux/proc_fs.h" #include "linux/ptrace.h" #include "linux/random.h" -#include "linux/sched.h" -#include "linux/tick.h" -#include "linux/threads.h" +#include "linux/personality.h" +#include "asm/unistd.h" +#include "asm/mman.h" +#include "asm/segment.h" +#include "asm/stat.h" #include "asm/pgtable.h" +#include "asm/processor.h" +#include "asm/tlbflush.h" #include "asm/uaccess.h" -#include "as-layout.h" +#include "asm/user.h" #include "kern_util.h" -#include "os.h" -#include "skas.h" +#include "as-layout.h" +#include "kern.h" +#include "signal_kern.h" +#include "init.h" +#include "irq_user.h" +#include "mem_user.h" #include "tlb.h" +#include "frame_kern.h" +#include "sigcontext.h" +#include "os.h" +#include "mode.h" +#include "mode_kern.h" +#include "choose-mode.h" -/* - * This is a per-cpu array. A processor only modifies its entry and it only +/* This is a per-cpu array. A processor only modifies its entry and it only * cares about its entry, so it's OK if another processor is modifying its * entry. */ @@ -32,16 +55,15 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; static inline int external_pid(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ - return userspace_pid[0]; + return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task); } int pid_to_processor_id(int pid) { int i; - for(i = 0; i < ncpus; i++) { - if (cpu_tasks[i].pid == pid) + for(i = 0; i < ncpus; i++){ + if(cpu_tasks[i].pid == pid) return i; } return -1; @@ -60,9 +82,9 @@ unsigned long alloc_stack(int order, int atomic) if (atomic) flags = GFP_ATOMIC; page = __get_free_pages(flags, order); - if (page == 0) + if(page == 0) return 0; - + stack_protections(page); return page; } @@ -83,8 +105,6 @@ static inline void set_current(struct task_struct *task) { external_pid(task), task }); } -extern void arch_switch_to(struct task_struct *from, struct task_struct *to); - void *_switch_to(void *prev, void *next, void *last) { struct task_struct *from = prev; @@ -94,14 +114,9 @@ void *_switch_to(void *prev, void *next, void *last) set_current(to); do { - current->thread.saved_task = NULL; - - switch_threads(&from->thread.switch_buf, - &to->thread.switch_buf); - - arch_switch_to(current->thread.prev_sched, current); - - if (current->thread.saved_task) + current->thread.saved_task = NULL ; + CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + if(current->thread.saved_task) show_regs(&(current->thread.regs)); next= current->thread.saved_task; prev= current; @@ -113,114 +128,49 @@ void *_switch_to(void *prev, void *next, void *last) void interrupt_end(void) { - if (need_resched()) + if(need_resched()) schedule(); - if (test_tsk_thread_flag(current, TIF_SIGPENDING)) + if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); } -void exit_thread(void) +void release_thread(struct task_struct *task) { + CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); } -void *get_current(void) +void exit_thread(void) { - return current; + unprotect_stack((unsigned long) current_thread); } -extern void schedule_tail(struct task_struct *prev); - -/* - * This is called magically, by its address being stuffed in a jmp_buf - * and being longjmp-d to. - */ -void new_thread_handler(void) -{ - int (*fn)(void *), n; - void *arg; - - if (current->thread.prev_sched != NULL) - schedule_tail(current->thread.prev_sched); - current->thread.prev_sched = NULL; - - fn = current->thread.request.u.thread.proc; - arg = current->thread.request.u.thread.arg; - - /* - * The return value is 1 if the kernel thread execs a process, - * 0 if it just exits - */ - n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if (n == 1) { - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); - } - else do_exit(0); -} - -/* Called magically, see new_thread_handler above */ -void fork_handler(void) +void *get_current(void) { - force_flush_all(); - if (current->thread.prev_sched == NULL) - panic("blech"); - - schedule_tail(current->thread.prev_sched); - - /* - * XXX: if interrupt_end() calls schedule, this call to - * arch_switch_to isn't needed. We could want to apply this to - * improve performance. -bb - */ - arch_switch_to(current->thread.prev_sched, current); - - current->thread.prev_sched = NULL; - - /* Handle any immediate reschedules or signals */ - interrupt_end(); - - userspace(¤t->thread.regs.regs); + return current; } int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { - void (*handler)(void); - int ret = 0; + int ret; p->thread = (struct thread_struct) INIT_THREAD; + ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, + clone_flags, sp, stack_top, p, regs); - if (current->thread.forking) { - memcpy(&p->thread.regs.regs, ®s->regs, - sizeof(p->thread.regs.regs)); - REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0); - if (sp != 0) - REGS_SP(p->thread.regs.regs.gp) = sp; + if (ret || !current->thread.forking) + goto out; - handler = fork_handler; - - arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } - else { - init_thread_registers(&p->thread.regs.regs); - p->thread.request.u.thread = current->thread.request.u.thread; - handler = new_thread_handler; - } + clear_flushed_tls(p); - new_thread(task_stack_page(p), &p->thread.switch_buf, handler); - - if (current->thread.forking) { - clear_flushed_tls(p); - - /* - * Set a new TLS for the child thread? - */ - if (clone_flags & CLONE_SETTLS) - ret = arch_copy_tls(p); - } + /* + * Set a new TLS for the child thread? + */ + if (clone_flags & CLONE_SETTLS) + ret = arch_copy_tls(p); +out: return ret; } @@ -229,35 +179,39 @@ void initial_thread_cb(void (*proc)(void *), void *arg) int save_kmalloc_ok = kmalloc_ok; kmalloc_ok = 0; - initial_thread_cb_skas(proc, arg); + CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, + arg); kmalloc_ok = save_kmalloc_ok; } +#ifdef CONFIG_MODE_TT +unsigned long stack_sp(unsigned long page) +{ + return page + PAGE_SIZE - sizeof(void *); +} +#endif + void default_idle(void) { - unsigned long long nsecs; + CHOOSE_MODE(uml_idle_timer(), (void) 0); - while(1) { + while(1){ /* endless idle loop with no priority at all */ /* * although we are an idle CPU, we do not want to * get into the scheduler unnecessarily. */ - if (need_resched()) + if(need_resched()) schedule(); - tick_nohz_stop_sched_tick(); - nsecs = disable_timer(); - idle_sleep(nsecs); - tick_nohz_restart_sched_tick(); + idle_sleep(10); } } void cpu_idle(void) { - cpu_tasks[current_thread->cpu].pid = os_getpid(); - default_idle(); + CHOOSE_MODE(init_idle_tt(), init_idle_skas()); } void *um_virt_to_phys(struct task_struct *task, unsigned long addr, @@ -269,26 +223,26 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte; pte_t ptent; - if (task->mm == NULL) + if(task->mm == NULL) return ERR_PTR(-EINVAL); pgd = pgd_offset(task->mm, addr); - if (!pgd_present(*pgd)) + if(!pgd_present(*pgd)) return ERR_PTR(-EINVAL); pud = pud_offset(pgd, addr); - if (!pud_present(*pud)) + if(!pud_present(*pud)) return ERR_PTR(-EINVAL); pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) + if(!pmd_present(*pmd)) return ERR_PTR(-EINVAL); pte = pte_offset_kernel(pmd, addr); ptent = *pte; - if (!pte_present(ptent)) + if(!pte_present(ptent)) return ERR_PTR(-EINVAL); - if (pte_out != NULL) + if(pte_out != NULL) *pte_out = ptent; return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK); } @@ -361,7 +315,7 @@ int smp_sigio_handler(void) #ifdef CONFIG_SMP int cpu = current_thread->cpu; IPI_handler(cpu); - if (cpu != 0) + if(cpu != 0) return 1; #endif return 0; @@ -389,8 +343,7 @@ int get_using_sysemu(void) static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) { - if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) - /* No overflow */ + if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ *eof = 1; return strlen(buf); @@ -405,8 +358,7 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned if (tmp[0] >= '0' && tmp[0] <= '2') set_using_sysemu(tmp[0] - '0'); - /* We use the first char, but pretend to write everything */ - return count; + return count; /*We use the first char, but pretend to write everything*/ } int __init make_proc_sysemu(void) @@ -436,10 +388,10 @@ int singlestepping(void * t) struct task_struct *task = t ? t : current; if ( ! (task->ptrace & PT_DTRACE) ) - return 0; + return(0); if (task->thread.singlestep_syscall) - return 1; + return(1); return 2; } diff --git a/trunk/arch/um/kernel/ptrace.c b/trunk/arch/um/kernel/ptrace.c index a0eba0833068..6916c8888dba 100644 --- a/trunk/arch/um/kernel/ptrace.c +++ b/trunk/arch/um/kernel/ptrace.c @@ -1,27 +1,35 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/audit.h" -#include "linux/ptrace.h" #include "linux/sched.h" -#include "asm/uaccess.h" +#include "linux/mm.h" +#include "linux/errno.h" +#include "linux/smp_lock.h" +#include "linux/security.h" +#include "linux/ptrace.h" +#include "linux/audit.h" #ifdef CONFIG_PROC_MM -#include "proc_mm.h" +#include "linux/proc_mm.h" #endif +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "kern_util.h" #include "skas_ptrace.h" +#include "sysdep/ptrace.h" +#include "os.h" static inline void set_singlestepping(struct task_struct *child, int on) { - if (on) - child->ptrace |= PT_DTRACE; - else - child->ptrace &= ~PT_DTRACE; - child->thread.singlestep_syscall = 0; + if (on) + child->ptrace |= PT_DTRACE; + else + child->ptrace &= ~PT_DTRACE; + child->thread.singlestep_syscall = 0; #ifdef SUBARCH_SET_SINGLESTEPPING - SUBARCH_SET_SINGLESTEPPING(child, on); + SUBARCH_SET_SINGLESTEPPING(child, on); #endif } @@ -29,8 +37,8 @@ static inline void set_singlestepping(struct task_struct *child, int on) * Called by kernel/ptrace.c when detaching.. */ void ptrace_disable(struct task_struct *child) -{ - set_singlestepping(child,0); +{ + set_singlestepping(child,0); } extern int peek_user(struct task_struct * child, long addr, long data); @@ -42,40 +50,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) unsigned long __user *p = (void __user *)(unsigned long)data; switch (request) { - /* read word at location addr. */ - case PTRACE_PEEKTEXT: + /* when I and D space are separate, these will need to be fixed. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: ret = generic_ptrace_peekdata(child, addr, data); break; /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: - ret = peek_user(child, addr, data); - break; + case PTRACE_PEEKUSR: + ret = peek_user(child, addr, data); + break; - /* write the word at location addr. */ - case PTRACE_POKETEXT: + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: ret = generic_ptrace_pokedata(child, addr, data); break; - /* write the word at location addr in the USER area */ - case PTRACE_POKEUSR: - ret = poke_user(child, addr, data); - break; + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = poke_user(child, addr, data); + break; - /* continue and stop at next (return from) syscall */ - case PTRACE_SYSCALL: - /* restart after signal. */ - case PTRACE_CONT: { + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; if (!valid_signal(data)) break; - set_singlestepping(child, 0); - if (request == PTRACE_SYSCALL) + set_singlestepping(child, 0); + if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } child->exit_code = data; wake_up_process(child); ret = 0; @@ -83,8 +91,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { @@ -92,7 +100,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; - set_singlestepping(child, 0); + set_singlestepping(child, 0); child->exit_code = SIGKILL; wake_up_process(child); break; @@ -103,7 +111,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - set_singlestepping(child, 1); + set_singlestepping(child, 1); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -111,6 +119,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } + case PTRACE_DETACH: + /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + #ifdef PTRACE_GETREGS case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { @@ -143,14 +156,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif #ifdef PTRACE_GETFPREGS case PTRACE_GETFPREGS: /* Get the child FPU state. */ - ret = get_fpregs((struct user_i387_struct __user *) data, - child); + ret = get_fpregs(data, child); break; #endif #ifdef PTRACE_SETFPREGS case PTRACE_SETFPREGS: /* Set the child FPU state. */ - ret = set_fpregs((struct user_i387_struct __user *) data, - child); + ret = set_fpregs(data, child); + break; +#endif +#ifdef PTRACE_GETFPXREGS + case PTRACE_GETFPXREGS: /* Get the child FPU state. */ + ret = get_fpxregs(data, child); + break; +#endif +#ifdef PTRACE_SETFPXREGS + case PTRACE_SETFPXREGS: /* Set the child FPU state. */ + ret = set_fpxregs(data, child); break; #endif case PTRACE_GET_THREAD_AREA: @@ -164,13 +185,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_FAULTINFO: { - /* - * Take the info from thread->arch->faultinfo, + /* Take the info from thread->arch->faultinfo, * but transfer max. sizeof(struct ptrace_faultinfo). * On i386, ptrace_faultinfo is smaller! */ ret = copy_to_user(p, &child->thread.arch.faultinfo, sizeof(struct ptrace_faultinfo)); + if(ret) + break; break; } @@ -178,13 +200,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_LDT: { struct ptrace_ldt ldt; - if (copy_from_user(&ldt, p, sizeof(ldt))) { + if(copy_from_user(&ldt, p, sizeof(ldt))){ ret = -EIO; break; } - /* - * This one is confusing, so just punt and return -EIO for + /* This one is confusing, so just punt and return -EIO for * now */ ret = -EIO; @@ -196,7 +217,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct mm_struct *old = child->mm; struct mm_struct *new = proc_mm_get_mm(data); - if (IS_ERR(new)) { + if(IS_ERR(new)){ ret = PTR_ERR(new); break; } @@ -210,22 +231,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } #endif #ifdef PTRACE_ARCH_PRCTL - case PTRACE_ARCH_PRCTL: - /* XXX Calls ptrace on the host - needs some SMP thinking */ - ret = arch_prctl(child, data, (void *) addr); - break; + case PTRACE_ARCH_PRCTL: + /* XXX Calls ptrace on the host - needs some SMP thinking */ + ret = arch_prctl_skas(child, data, (void *) addr); + break; #endif default: ret = ptrace_request(child, request, addr, data); - if (ret == -EIO) - ret = subarch_ptrace(child, request, addr, data); break; } return ret; } -void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, +void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, int error_code) { struct siginfo info; @@ -241,11 +260,10 @@ void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, force_sig_info(SIGTRAP, &info, tsk); } -/* - * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and +/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check */ -void syscall_trace(struct uml_pt_regs *regs, int entryexit) +void syscall_trace(union uml_pt_regs *regs, int entryexit) { int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; int tracesysgood; @@ -259,7 +277,7 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit) UPT_SYSCALL_ARG3(regs), UPT_SYSCALL_ARG4(regs)); else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), - UPT_SYSCALL_RET(regs)); + UPT_SYSCALL_RET(regs)); } /* Fake a debug trap */ @@ -272,18 +290,15 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit) if (!(current->ptrace & PT_PTRACED)) return; - /* - * the 0x80 provides a way for the tracing parent to distinguish - * between a syscall stop and SIGTRAP delivery - */ + /* the 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ tracesysgood = (current->ptrace & PT_TRACESYSGOOD); ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); if (entryexit) /* force do_signal() --> is_syscall() */ set_thread_flag(TIF_SIGPENDING); - /* - * this isn't the same as continuing with a signal, but it will do + /* 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 */ diff --git a/trunk/arch/um/kernel/reboot.c b/trunk/arch/um/kernel/reboot.c index 04cebcf0679f..7e4305a1fd3c 100644 --- a/trunk/arch/um/kernel/reboot.c +++ b/trunk/arch/um/kernel/reboot.c @@ -1,53 +1,60 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include "linux/module.h" #include "linux/sched.h" +#include "asm/smp.h" +#include "kern_util.h" +#include "kern.h" #include "os.h" -#include "skas.h" +#include "mode.h" +#include "choose-mode.h" void (*pm_power_off)(void); -static void kill_off_processes(void) +#ifdef CONFIG_SMP +static void kill_idlers(int me) { - if(proc_mm) - /* - * FIXME: need to loop over userspace_pids - */ - os_kill_ptraced_process(userspace_pid[0], 1); - else { - struct task_struct *p; - int pid, me; - - me = os_getpid(); - for_each_process(p){ - if(p->mm == NULL) - continue; - - pid = p->mm->context.id.u.pid; - os_kill_ptraced_process(pid, 1); - } +#ifdef CONFIG_MODE_TT + struct task_struct *p; + int i; + + for(i = 0; i < ARRAY_SIZE(idle_threads); i++){ + p = idle_threads[i]; + if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) + os_kill_process(p->thread.mode.tt.extern_pid, 0); } +#endif +} +#endif + +static void kill_off_processes(void) +{ + CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); +#ifdef CONFIG_SMP + kill_idlers(os_getpid()); +#endif } void uml_cleanup(void) { - kmalloc_ok = 0; + kmalloc_ok = 0; do_uml_exitcalls(); kill_off_processes(); } void machine_restart(char * __unused) { - uml_cleanup(); - reboot_skas(); + uml_cleanup(); + CHOOSE_MODE(reboot_tt(), reboot_skas()); } void machine_power_off(void) { - uml_cleanup(); - halt_skas(); + uml_cleanup(); + CHOOSE_MODE(halt_tt(), halt_skas()); } void machine_halt(void) diff --git a/trunk/arch/um/kernel/signal.c b/trunk/arch/um/kernel/signal.c index 19cb97733937..c4020c3d7857 100644 --- a/trunk/arch/um/kernel/signal.c +++ b/trunk/arch/um/kernel/signal.c @@ -1,17 +1,29 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include "linux/stddef.h" +#include "linux/sys.h" +#include "linux/sched.h" +#include "linux/wait.h" +#include "linux/kernel.h" +#include "linux/smp_lock.h" #include "linux/module.h" +#include "linux/slab.h" +#include "linux/tty.h" +#include "linux/binfmts.h" #include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/siginfo.h" #include "asm/signal.h" +#include "asm/uaccess.h" #include "asm/unistd.h" -#include "frame_kern.h" +#include "asm/ucontext.h" #include "kern_util.h" +#include "signal_kern.h" +#include "kern.h" +#include "frame_kern.h" #include "sigcontext.h" +#include "mode.h" EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); @@ -34,9 +46,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, current_thread_info()->restart_block.fn = do_no_restart_syscall; /* Did we come from a system call? */ - if (PT_REGS_SYSCALL_NR(regs) >= 0) { + if(PT_REGS_SYSCALL_NR(regs) >= 0){ /* If so, check system call restarting.. */ - switch(PT_REGS_SYSCALL_RET(regs)) { + switch(PT_REGS_SYSCALL_RET(regs)){ case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: PT_REGS_SYSCALL_RET(regs) = -EINTR; @@ -56,17 +68,17 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, } sp = PT_REGS_SP(regs); - if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) + if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; #ifdef CONFIG_ARCH_HAS_SC_SIGNALS - if (!(ka->sa.sa_flags & SA_SIGINFO)) + if(!(ka->sa.sa_flags & SA_SIGINFO)) err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); else #endif err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); - if (err) { + if(err){ spin_lock_irq(¤t->sighand->siglock); current->blocked = *oldset; recalc_sigpending(); @@ -76,7 +88,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) + if(!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); @@ -97,16 +109,14 @@ static int kern_do_signal(struct pt_regs *regs) else oldset = ¤t->blocked; - while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ handled_sig = 1; /* Whee! Actually deliver the signal. */ - if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { - /* - * a signal was successfully delivered; the saved + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ + /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag - */ + * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); break; @@ -114,9 +124,9 @@ static int kern_do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { + if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ /* Restart the system call - no handlers present */ - switch(PT_REGS_SYSCALL_RET(regs)) { + switch(PT_REGS_SYSCALL_RET(regs)){ case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: @@ -127,25 +137,22 @@ static int kern_do_signal(struct pt_regs *regs) PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); break; - } + } } - /* - * This closes a way to execute a system call on the host. If + /* This closes a way to execute a system call on the host. If * you set a breakpoint on a system call instruction and singlestep * from it, the tracing thread used to PTRACE_SINGLESTEP the process * rather than PTRACE_SYSCALL it, allowing the system call to execute * on the host. The tracing thread will check this flag and * PTRACE_SYSCALL if necessary. */ - if (current->ptrace & PT_DTRACE) + if(current->ptrace & PT_DTRACE) current->thread.singlestep_syscall = is_syscall(PT_REGS_IP(¤t->thread.regs)); - /* - * if there's no signal to deliver, we just put the saved sigmask - * back - */ + /* if there's no signal to deliver, we just put the saved sigmask + * back */ if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); diff --git a/trunk/arch/um/kernel/skas/Makefile b/trunk/arch/um/kernel/skas/Makefile index 0b76d8869c94..3e3fa7e7e3cf 100644 --- a/trunk/arch/um/kernel/skas/Makefile +++ b/trunk/arch/um/kernel/skas/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # -obj-y := clone.o mmu.o process.o syscall.o uaccess.o +obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o # clone.o is in the stub, so it can't be built with profiling # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> diff --git a/trunk/arch/um/kernel/skas/clone.c b/trunk/arch/um/kernel/skas/clone.c index d119f4f7d897..47b812b3bca8 100644 --- a/trunk/arch/um/kernel/skas/clone.c +++ b/trunk/arch/um/kernel/skas/clone.c @@ -4,7 +4,6 @@ #include #include #include -#include "as-layout.h" #include "ptrace_user.h" #include "skas.h" #include "stub-data.h" @@ -22,11 +21,12 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { - struct stub_data *data = (struct stub_data *) STUB_DATA; + struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA; long err; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); + UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - + sizeof(void *)); if(err != 0) goto out; diff --git a/trunk/arch/um/kernel/skas/exec.c b/trunk/arch/um/kernel/skas/exec.c new file mode 100644 index 000000000000..580eb6468949 --- /dev/null +++ b/trunk/arch/um/kernel/skas/exec.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "asm/current.h" +#include "asm/page.h" +#include "asm/signal.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "asm/mmu_context.h" +#include "tlb.h" +#include "skas.h" +#include "um_mmu.h" +#include "os.h" + +void flush_thread_skas(void) +{ + void *data = NULL; + unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; + int ret; + + ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data); + if(ret){ + printk("flush_thread_skas - clearing address space failed, " + "err = %d\n", ret); + force_sig(SIGKILL, current); + } + + switch_mm_skas(¤t->mm->context.skas.id); +} + +void start_thread_skas(struct pt_regs *regs, unsigned long eip, + unsigned long esp) +{ + set_fs(USER_DS); + PT_REGS_IP(regs) = eip; + PT_REGS_SP(regs) = esp; +} diff --git a/trunk/arch/um/kernel/skas/mem.c b/trunk/arch/um/kernel/skas/mem.c new file mode 100644 index 000000000000..7c18dfcd7d8e --- /dev/null +++ b/trunk/arch/um/kernel/skas/mem.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/mm.h" +#include "asm/pgtable.h" +#include "mem_user.h" +#include "skas.h" + +unsigned long set_task_sizes_skas(unsigned long *task_size_out) +{ + /* Round up to the nearest 4M */ + unsigned long host_task_size = ROUND_4M((unsigned long) + &host_task_size); + + if (!skas_needs_stub) + *task_size_out = host_task_size; + else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; + + return host_task_size; +} diff --git a/trunk/arch/um/kernel/skas/mmu.c b/trunk/arch/um/kernel/skas/mmu.c index f859ec306cd5..2c6d090a2e87 100644 --- a/trunk/arch/um/kernel/skas/mmu.c +++ b/trunk/arch/um/kernel/skas/mmu.c @@ -1,13 +1,20 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/mm.h" #include "linux/sched.h" +#include "linux/list.h" +#include "linux/spinlock.h" +#include "linux/slab.h" +#include "linux/errno.h" +#include "linux/mm.h" +#include "asm/current.h" +#include "asm/segment.h" +#include "asm/mmu.h" #include "asm/pgalloc.h" #include "asm/pgtable.h" -#include "as-layout.h" +#include "asm/ldt.h" #include "os.h" #include "skas.h" @@ -34,11 +41,10 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, if (!pte) goto out_pte; - /* - * There's an interaction between the skas0 stub pages, stack + /* There's an interaction between the skas0 stub pages, stack * randomization, and the BUG at the end of exit_mmap. exit_mmap - * checks that the number of page tables freed is the same as had - * been allocated. If the stack is on the last page table page, + * checks that the number of page tables freed is the same as had + * been allocated. If the stack is on the last page table page, * then the stack pte page will be freed, and if not, it won't. To * avoid having to know where the stack is, or if the process mapped * something at the top of its address space for some other reason, @@ -48,77 +54,76 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, * destroy_context_skas. */ - mm->context.last_page_table = pmd_page_vaddr(*pmd); + mm->context.skas.last_page_table = pmd_page_vaddr(*pmd); #ifdef CONFIG_3_LEVEL_PGTABLES - mm->context.last_pmd = (unsigned long) __va(pud_val(*pud)); + mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); #endif *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); *pte = pte_mkread(*pte); - return 0; + return(0); out_pmd: pud_free(pud); out_pte: pmd_free(pmd); out: - return -ENOMEM; + return(-ENOMEM); } -int init_new_context(struct task_struct *task, struct mm_struct *mm) +int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) { - struct mm_context *from_mm = NULL; - struct mm_context *to_mm = &mm->context; + struct mmu_context_skas *from_mm = NULL; + struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; int ret = -ENOMEM; - if (skas_needs_stub) { + if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); - if (stack == 0) + if(stack == 0) goto out; - /* - * This zeros the entry that pgd_alloc didn't, needed since + /* This zeros the entry that pgd_alloc didn't, needed since * we are about to reinitialize it, and want mm.nr_ptes to * be accurate. */ mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); - ret = init_stub_pte(mm, STUB_CODE, + ret = init_stub_pte(mm, CONFIG_STUB_CODE, (unsigned long) &__syscall_stub_start); - if (ret) + if(ret) goto out_free; - ret = init_stub_pte(mm, STUB_DATA, stack); - if (ret) + ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack); + if(ret) goto out_free; mm->nr_ptes--; } to_mm->id.stack = stack; - if (current->mm != NULL && current->mm != &init_mm) - from_mm = ¤t->mm->context; + if(current->mm != NULL && current->mm != &init_mm) + from_mm = ¤t->mm->context.skas; - if (proc_mm) { + if(proc_mm){ ret = new_mm(stack); - if (ret < 0) { - printk(KERN_ERR "init_new_context_skas - " - "new_mm failed, errno = %d\n", ret); + if(ret < 0){ + printk("init_new_context_skas - new_mm failed, " + "errno = %d\n", ret); goto out_free; } to_mm->id.u.mm_fd = ret; } else { - if (from_mm) + if(from_mm) to_mm->id.u.pid = copy_context_skas0(stack, from_mm->id.u.pid); else to_mm->id.u.pid = start_userspace(stack); } ret = init_new_ldt(to_mm, from_mm); - if (ret < 0) { - printk(KERN_ERR "init_new_context_skas - init_ldt" + if(ret < 0){ + printk("init_new_context_skas - init_ldt" " failed, errno = %d\n", ret); goto out_free; } @@ -126,22 +131,22 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) return 0; out_free: - if (to_mm->id.stack != 0) + if(to_mm->id.stack != 0) free_page(to_mm->id.stack); out: return ret; } -void destroy_context(struct mm_struct *mm) +void destroy_context_skas(struct mm_struct *mm) { - struct mm_context *mmu = &mm->context; + struct mmu_context_skas *mmu = &mm->context.skas; - if (proc_mm) + if(proc_mm) os_close_file(mmu->id.u.mm_fd); else os_kill_ptraced_process(mmu->id.u.pid, 1); - if (!proc_mm || !ptrace_faultinfo) { + if(!proc_mm || !ptrace_faultinfo){ free_page(mmu->id.stack); pte_lock_deinit(virt_to_page(mmu->last_page_table)); pte_free_kernel((pte_t *) mmu->last_page_table); @@ -150,6 +155,4 @@ void destroy_context(struct mm_struct *mm) pmd_free((pmd_t *) mmu->last_pmd); #endif } - - free_ldt(mmu); } diff --git a/trunk/arch/um/kernel/skas/process.c b/trunk/arch/um/kernel/skas/process.c index fce389c2342f..48051a98525f 100644 --- a/trunk/arch/um/kernel/skas/process.c +++ b/trunk/arch/um/kernel/skas/process.c @@ -1,26 +1,146 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/init.h" #include "linux/sched.h" +#include "linux/slab.h" +#include "linux/ptrace.h" +#include "linux/proc_fs.h" +#include "linux/file.h" +#include "linux/errno.h" +#include "linux/init.h" +#include "asm/uaccess.h" +#include "asm/atomic.h" +#include "kern_util.h" #include "as-layout.h" -#include "os.h" #include "skas.h" +#include "os.h" +#include "tlb.h" +#include "kern.h" +#include "mode.h" +#include "registers.h" + +void switch_to_skas(void *prev, void *next) +{ + struct task_struct *from, *to; + + from = prev; + to = next; + + /* XXX need to check runqueues[cpu].idle */ + if(current->pid == 0) + switch_timers(0); + + switch_threads(&from->thread.mode.skas.switch_buf, + &to->thread.mode.skas.switch_buf); + + arch_switch_to_skas(current->thread.prev_sched, current); + + if(current->pid == 0) + switch_timers(1); +} + +extern void schedule_tail(struct task_struct *prev); + +/* This is called magically, by its address being stuffed in a jmp_buf + * and being longjmp-d to. + */ +void new_thread_handler(void) +{ + int (*fn)(void *), n; + void *arg; + + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + + fn = current->thread.request.u.thread.proc; + arg = current->thread.request.u.thread.arg; + + /* The return value is 1 if the kernel thread execs a process, + * 0 if it just exits + */ + n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); + if(n == 1){ + /* Handle any immediate reschedules or signals */ + interrupt_end(); + userspace(¤t->thread.regs.regs); + } + else do_exit(0); +} + +void release_thread_skas(struct task_struct *task) +{ +} + +/* Called magically, see new_thread_handler above */ +void fork_handler(void) +{ + force_flush_all(); + if(current->thread.prev_sched == NULL) + panic("blech"); + + schedule_tail(current->thread.prev_sched); + + /* XXX: if interrupt_end() calls schedule, this call to + * arch_switch_to_skas isn't needed. We could want to apply this to + * improve performance. -bb */ + arch_switch_to_skas(current->thread.prev_sched, current); + + current->thread.prev_sched = NULL; + +/* Handle any immediate reschedules or signals */ + interrupt_end(); + + userspace(¤t->thread.regs.regs); +} + +int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct * p, + struct pt_regs *regs) +{ + void (*handler)(void); + + if(current->thread.forking){ + memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, + sizeof(p->thread.regs.regs.skas)); + REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); + if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; + + handler = fork_handler; + + arch_copy_thread(¤t->thread.arch, &p->thread.arch); + } + else { + init_thread_registers(&p->thread.regs.regs); + p->thread.request.u.thread = current->thread.request.u.thread; + handler = new_thread_handler; + } + + new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, + handler); + return(0); +} int new_mm(unsigned long stack) { int fd; fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); - if (fd < 0) - return fd; + if(fd < 0) + return(fd); - if (skas_needs_stub) - map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); + if(skas_needs_stub) + map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); - return fd; + return(fd); +} + +void init_idle_skas(void) +{ + cpu_tasks[current_thread->cpu].pid = os_getpid(); + default_idle(); } extern void start_kernel(void); @@ -38,32 +158,67 @@ static int __init start_kernel_proc(void *unused) cpu_online_map = cpumask_of_cpu(0); #endif start_kernel(); - return 0; + return(0); } extern int userspace_pid[]; extern char cpu0_irqstack[]; -int __init start_uml(void) +int __init start_uml_skas(void) { stack_protections((unsigned long) &cpu0_irqstack); set_sigstack(cpu0_irqstack, THREAD_SIZE); - if (proc_mm) + if(proc_mm) userspace_pid[0] = start_userspace(0); init_new_thread_signals(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return start_idle_thread(task_stack_page(&init_task), - &init_task.thread.switch_buf); + return(start_idle_thread(task_stack_page(&init_task), + &init_task.thread.mode.skas.switch_buf)); +} + +int external_pid_skas(struct task_struct *task) +{ + /* FIXME: Need to look up userspace_pid by cpu */ + return(userspace_pid[0]); +} + +int thread_pid_skas(struct task_struct *task) +{ + /* FIXME: Need to look up userspace_pid by cpu */ + return(userspace_pid[0]); +} + +void kill_off_processes_skas(void) +{ + if(proc_mm) + /* + * FIXME: need to loop over userspace_pids in + * kill_off_processes_skas + */ + os_kill_ptraced_process(userspace_pid[0], 1); + else { + struct task_struct *p; + int pid, me; + + me = os_getpid(); + for_each_process(p){ + if(p->mm == NULL) + continue; + + pid = p->mm->context.skas.id.u.pid; + os_kill_ptraced_process(pid, 1); + } + } } unsigned long current_stub_stack(void) { - if (current->mm == NULL) - return 0; + if(current->mm == NULL) + return(0); - return current->mm->context.id.stack; + return(current->mm->context.skas.id.stack); } diff --git a/trunk/arch/um/kernel/skas/syscall.c b/trunk/arch/um/kernel/skas/syscall.c index 50b476f2b38d..0ae4eea21be4 100644 --- a/trunk/arch/um/kernel/skas/syscall.c +++ b/trunk/arch/um/kernel/skas/syscall.c @@ -1,15 +1,19 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/kernel.h" +#include "linux/sys.h" #include "linux/ptrace.h" -#include "kern_util.h" -#include "sysdep/ptrace.h" +#include "asm/errno.h" +#include "asm/unistd.h" +#include "asm/ptrace.h" +#include "asm/current.h" #include "sysdep/syscalls.h" +#include "kern_util.h" +#include "syscall.h" -void handle_syscall(struct uml_pt_regs *r) +void handle_syscall(union uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); long result; @@ -20,8 +24,7 @@ void handle_syscall(struct uml_pt_regs *r) current->thread.nsyscalls++; nsyscalls++; - /* - * This should go in the declaration of syscall, but when I do that, + /* This should go in the declaration of syscall, but when I do that, * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing * children at all, sometimes hanging when bash doesn't see the first * ls exit. @@ -30,11 +33,11 @@ void handle_syscall(struct uml_pt_regs *r) * in case it's a compiler bug. */ syscall = UPT_SYSCALL_NR(r); - if ((syscall >= NR_syscalls) || (syscall < 0)) + if((syscall >= NR_syscalls) || (syscall < 0)) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); - REGS_SET_SYSCALL_RETURN(r->gp, result); + REGS_SET_SYSCALL_RETURN(r->skas.regs, result); syscall_trace(r, 1); } diff --git a/trunk/arch/um/kernel/skas/tlb.c b/trunk/arch/um/kernel/skas/tlb.c new file mode 100644 index 000000000000..c0f0693743ba --- /dev/null +++ b/trunk/arch/um/kernel/skas/tlb.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/sched.h" +#include "linux/mm.h" +#include "asm/page.h" +#include "asm/pgtable.h" +#include "asm/mmu.h" +#include "mem_user.h" +#include "mem.h" +#include "skas.h" +#include "os.h" +#include "tlb.h" + +static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, + int finished, void **flush) +{ + struct host_vm_op *op; + int i, ret = 0; + + for(i = 0; i <= last && !ret; i++){ + op = &ops[i]; + switch(op->type){ + case MMAP: + ret = map(&mmu->skas.id, op->u.mmap.addr, + op->u.mmap.len, op->u.mmap.prot, + op->u.mmap.fd, op->u.mmap.offset, finished, + flush); + break; + case MUNMAP: + ret = unmap(&mmu->skas.id, op->u.munmap.addr, + op->u.munmap.len, finished, flush); + break; + case MPROTECT: + ret = protect(&mmu->skas.id, op->u.mprotect.addr, + op->u.mprotect.len, op->u.mprotect.prot, + finished, flush); + break; + default: + printk("Unknown op type %d in do_ops\n", op->type); + break; + } + } + + return ret; +} + +extern int proc_mm; + +static void fix_range(struct mm_struct *mm, unsigned long start_addr, + unsigned long end_addr, int force) +{ + if(!proc_mm && (end_addr > CONFIG_STUB_START)) + end_addr = CONFIG_STUB_START; + + fix_range_common(mm, start_addr, end_addr, force, do_ops); +} + +void __flush_tlb_one_skas(unsigned long addr) +{ + flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); +} + +void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + if(vma->vm_mm == NULL) + flush_tlb_kernel_range_common(start, end); + else fix_range(vma->vm_mm, start, end, 0); +} + +void flush_tlb_mm_skas(struct mm_struct *mm) +{ + unsigned long end; + + /* Don't bother flushing if this address space is about to be + * destroyed. + */ + if(atomic_read(&mm->mm_users) == 0) + return; + + end = proc_mm ? task_size : CONFIG_STUB_START; + fix_range(mm, 0, end, 0); +} + +void force_flush_all_skas(void) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma = mm->mmap; + + while(vma != NULL) { + fix_range(mm, vma->vm_start, vma->vm_end, 1); + vma = vma->vm_next; + } +} + +void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + struct mm_struct *mm = vma->vm_mm; + void *flush = NULL; + int r, w, x, prot, err = 0; + struct mm_id *mm_id; + + pgd = pgd_offset(mm, address); + if(!pgd_present(*pgd)) + goto kill; + + pud = pud_offset(pgd, address); + if(!pud_present(*pud)) + goto kill; + + pmd = pmd_offset(pud, address); + if(!pmd_present(*pmd)) + goto kill; + + pte = pte_offset_kernel(pmd, address); + + r = pte_read(*pte); + w = pte_write(*pte); + x = pte_exec(*pte); + if (!pte_young(*pte)) { + r = 0; + w = 0; + } else if (!pte_dirty(*pte)) { + w = 0; + } + + mm_id = &mm->context.skas.id; + prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | + (x ? UM_PROT_EXEC : 0)); + if(pte_newpage(*pte)){ + if(pte_present(*pte)){ + unsigned long long offset; + int fd; + + fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); + err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, + 1, &flush); + } + else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); + } + else if(pte_newprot(*pte)) + err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); + + if(err) + goto kill; + + *pte = pte_mkuptodate(*pte); + + return; + +kill: + printk("Failed to flush page for address 0x%lx\n", address); + force_sig(SIGKILL, current); +} + diff --git a/trunk/arch/um/kernel/skas/uaccess.c b/trunk/arch/um/kernel/skas/uaccess.c index 1d8b119f2d0e..8912cec0fe43 100644 --- a/trunk/arch/um/kernel/skas/uaccess.c +++ b/trunk/arch/um/kernel/skas/uaccess.c @@ -1,14 +1,18 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include "linux/err.h" +#include "linux/compiler.h" +#include "linux/stddef.h" +#include "linux/kernel.h" +#include "linux/string.h" +#include "linux/fs.h" +#include "linux/hardirq.h" #include "linux/highmem.h" -#include "linux/mm.h" -#include "asm/current.h" #include "asm/page.h" #include "asm/pgtable.h" +#include "asm/uaccess.h" #include "kern_util.h" #include "os.h" @@ -23,16 +27,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write) void *phys = um_virt_to_phys(current, virt, &pte); int dummy_code; - if (IS_ERR(phys) || (is_write && !pte_write(pte))) { + if(IS_ERR(phys) || (is_write && !pte_write(pte))){ err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); - if (err) - return -1UL; + if(err) + return(-1UL); phys = um_virt_to_phys(current, virt, NULL); } - if (IS_ERR(phys)) - phys = (void *) -1; + if(IS_ERR(phys)) + phys = (void *) -1; - return (unsigned long) phys; + return((unsigned long) phys); } static int do_op_one_page(unsigned long addr, int len, int is_write, @@ -42,18 +46,17 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, int n; addr = maybe_map(addr, is_write); - if (addr == -1UL) - return -1; + if(addr == -1UL) + return(-1); page = phys_to_page(addr); - addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + - (addr & ~PAGE_MASK); + addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); n = (*op)(addr, len, arg); kunmap_atomic(page, KM_UML_USERCOPY); - return n; + return(n); } static void do_buffer_op(void *jmpbuf, void *arg_ptr) @@ -78,21 +81,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) current->thread.fault_catcher = jmpbuf; n = do_op_one_page(addr, size, is_write, op, arg); - if (n != 0) { + if(n != 0){ *res = (n < 0 ? remain : 0); goto out; } addr += size; remain -= size; - if (remain == 0) { + if(remain == 0){ *res = 0; goto out; } - while(addr < ((addr + remain) & PAGE_MASK)) { + while(addr < ((addr + remain) & PAGE_MASK)){ n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); - if (n != 0) { + if(n != 0){ *res = (n < 0 ? remain : 0); goto out; } @@ -100,13 +103,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) addr += PAGE_SIZE; remain -= PAGE_SIZE; } - if (remain == 0) { + if(remain == 0){ *res = 0; goto out; } n = do_op_one_page(addr, remain, is_write, op, arg); - if (n != 0) + if(n != 0) *res = (n < 0 ? remain : 0); else *res = 0; out: @@ -121,10 +124,10 @@ static int buffer_op(unsigned long addr, int len, int is_write, faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, &res); - if (!faulted) - return res; + if(!faulted) + return(res); - return addr + len - (unsigned long) current->thread.fault_addr; + return(addr + len - (unsigned long) current->thread.fault_addr); } static int copy_chunk_from_user(unsigned long from, int len, void *arg) @@ -133,19 +136,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) memcpy((void *) to, (void *) from, len); *to_ptr += len; - return 0; + return(0); } -int copy_from_user(void *to, const void __user *from, int n) +int copy_from_user_skas(void *to, const void __user *from, int n) { - if (segment_eq(get_fs(), KERNEL_DS)) { + if(segment_eq(get_fs(), KERNEL_DS)){ memcpy(to, (__force void*)from, n); - return 0; + return(0); } - return access_ok(VERIFY_READ, from, n) ? + return(access_ok(VERIFY_READ, from, n) ? buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): - n; + n); } static int copy_chunk_to_user(unsigned long to, int len, void *arg) @@ -154,19 +157,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) memcpy((void *) to, (void *) from, len); *from_ptr += len; - return 0; + return(0); } -int copy_to_user(void __user *to, const void *from, int n) +int copy_to_user_skas(void __user *to, const void *from, int n) { - if (segment_eq(get_fs(), KERNEL_DS)) { - memcpy((__force void *) to, from, n); - return 0; + if(segment_eq(get_fs(), KERNEL_DS)){ + memcpy((__force void*)to, from, n); + return(0); } - return access_ok(VERIFY_WRITE, to, n) ? + return(access_ok(VERIFY_WRITE, to, n) ? buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : - n; + n); } static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) @@ -178,51 +181,51 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) n = strnlen(to, len); *to_ptr += n; - if (n < len) - return 1; - return 0; + if(n < len) + return(1); + return(0); } -int strncpy_from_user(char *dst, const char __user *src, int count) +int strncpy_from_user_skas(char *dst, const char __user *src, int count) { int n; char *ptr = dst; - if (segment_eq(get_fs(), KERNEL_DS)) { - strncpy(dst, (__force void *) src, count); - return strnlen(dst, count); + if(segment_eq(get_fs(), KERNEL_DS)){ + strncpy(dst, (__force void*)src, count); + return(strnlen(dst, count)); } - if (!access_ok(VERIFY_READ, src, 1)) - return -EFAULT; + if(!access_ok(VERIFY_READ, src, 1)) + return(-EFAULT); n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, &ptr); - if (n != 0) - return -EFAULT; - return strnlen(dst, count); + if(n != 0) + return(-EFAULT); + return(strnlen(dst, count)); } static int clear_chunk(unsigned long addr, int len, void *unused) { memset((void *) addr, 0, len); - return 0; + return(0); } -int __clear_user(void __user *mem, int len) +int __clear_user_skas(void __user *mem, int len) { - return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); + return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); } -int clear_user(void __user *mem, int len) +int clear_user_skas(void __user *mem, int len) { - if (segment_eq(get_fs(), KERNEL_DS)) { + if(segment_eq(get_fs(), KERNEL_DS)){ memset((__force void*)mem, 0, len); - return 0; + return(0); } - return access_ok(VERIFY_WRITE, mem, len) ? - buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; + return(access_ok(VERIFY_WRITE, mem, len) ? + buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); } static int strnlen_chunk(unsigned long str, int len, void *arg) @@ -232,20 +235,31 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) n = strnlen((void *) str, len); *len_ptr += n; - if (n < len) - return 1; - return 0; + if(n < len) + return(1); + return(0); } -int strnlen_user(const void __user *str, int len) +int strnlen_user_skas(const void __user *str, int len) { int count = 0, n; - if (segment_eq(get_fs(), KERNEL_DS)) - return strnlen((__force char*)str, len) + 1; + if(segment_eq(get_fs(), KERNEL_DS)) + return(strnlen((__force char*)str, len) + 1); n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); - if (n == 0) - return count + 1; - return -EFAULT; + if(n == 0) + return(count + 1); + return(-EFAULT); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/smp.c b/trunk/arch/um/kernel/smp.c index 36d89cf8d20b..e6a7778006ad 100644 --- a/trunk/arch/um/kernel/smp.c +++ b/trunk/arch/um/kernel/smp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -56,12 +56,12 @@ void smp_send_stop(void) int i; printk(KERN_INFO "Stopping all CPUs..."); - for (i = 0; i < num_online_cpus(); i++) { - if (i == current_thread->cpu) + for(i = 0; i < num_online_cpus(); i++){ + if(i == current_thread->cpu) continue; os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); } - printk(KERN_INFO "done\n"); + printk("done\n"); } static cpumask_t smp_commenced_mask = CPU_MASK_NONE; @@ -72,7 +72,7 @@ static int idle_proc(void *cpup) int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); - if (err < 0) + if(err < 0) panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); os_set_fd_async(cpu_data[cpu].ipi_pipe[0], @@ -80,7 +80,7 @@ static int idle_proc(void *cpup) wmb(); if (cpu_test_and_set(cpu, cpu_callin_map)) { - printk(KERN_ERR "huh, CPU#%d already present??\n", cpu); + printk("huh, CPU#%d already present??\n", cpu); BUG(); } @@ -95,11 +95,12 @@ static int idle_proc(void *cpup) static struct task_struct *idle_thread(int cpu) { struct task_struct *new_task; + unsigned char c; current->thread.request.u.thread.proc = idle_proc; current->thread.request.u.thread.arg = (void *) cpu; new_task = fork_idle(cpu); - if (IS_ERR(new_task)) + if(IS_ERR(new_task)) panic("copy_process failed in idle_thread, error = %ld", PTR_ERR(new_task)); @@ -107,7 +108,9 @@ static struct task_struct *idle_thread(int cpu) { .pid = new_task->thread.mode.tt.extern_pid, .task = new_task } ); idle_threads[cpu] = new_task; - panic("skas mode doesn't support SMP"); + CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, + sizeof(c)), + ({ panic("skas mode doesn't support SMP"); })); return new_task; } @@ -126,14 +129,14 @@ void smp_prepare_cpus(unsigned int maxcpus) cpu_set(me, cpu_callin_map); err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); - if (err < 0) + if(err < 0) panic("CPU#0 failed to create IPI pipe, errno = %d", -err); os_set_fd_async(cpu_data[me].ipi_pipe[0], current->thread.mode.tt.extern_pid); - for (cpu = 1; cpu < ncpus; cpu++) { - printk(KERN_INFO "Booting processor %d...\n", cpu); + for(cpu = 1; cpu < ncpus; cpu++){ + printk("Booting processor %d...\n", cpu); idle = idle_thread(cpu); @@ -144,8 +147,8 @@ void smp_prepare_cpus(unsigned int maxcpus) cpu_relax(); if (cpu_isset(cpu, cpu_callin_map)) - printk(KERN_INFO "done\n"); - else printk(KERN_INFO "failed\n"); + printk("done\n"); + else printk("failed\n"); } } @@ -187,14 +190,13 @@ void IPI_handler(int cpu) break; case 'S': - printk(KERN_INFO "CPU#%d stopping\n", cpu); - while (1) + printk("CPU#%d stopping\n", cpu); + while(1) pause(); break; default: - printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n", - cpu, c); + printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); break; } } diff --git a/trunk/arch/um/kernel/syscall.c b/trunk/arch/um/kernel/syscall.c index b9d92b2089ae..7b3b67333ff3 100644 --- a/trunk/arch/um/kernel/syscall.c +++ b/trunk/arch/um/kernel/syscall.c @@ -1,17 +1,27 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ +#include "linux/sched.h" #include "linux/file.h" -#include "linux/fs.h" +#include "linux/smp_lock.h" #include "linux/mm.h" -#include "linux/sched.h" +#include "linux/fs.h" #include "linux/utsname.h" -#include "asm/current.h" +#include "linux/msg.h" +#include "linux/shm.h" +#include "linux/sys.h" +#include "linux/syscalls.h" +#include "linux/unistd.h" +#include "linux/slab.h" +#include "linux/utime.h" #include "asm/mman.h" #include "asm/uaccess.h" -#include "asm/unistd.h" +#include "kern_util.h" +#include "sysdep/syscalls.h" +#include "mode_kern.h" +#include "choose-mode.h" /* Unlocked, I don't care if this is a bit off */ int nsyscalls = 0; @@ -24,7 +34,7 @@ long sys_fork(void) ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); current->thread.forking = 0; - return ret; + return(ret); } long sys_vfork(void) @@ -36,7 +46,7 @@ long sys_vfork(void) UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); current->thread.forking = 0; - return ret; + return(ret); } /* common code for old and new mmaps */ @@ -82,15 +92,15 @@ long old_mmap(unsigned long addr, unsigned long len, */ long sys_pipe(unsigned long __user * fildes) { - int fd[2]; - long error; + int fd[2]; + long error; - error = do_pipe(fd); - if (!error) { + error = do_pipe(fd); + if (!error) { if (copy_to_user(fildes, fd, sizeof(fd))) - error = -EFAULT; - } - return error; + error = -EFAULT; + } + return error; } @@ -114,7 +124,7 @@ long sys_olduname(struct oldold_utsname __user * name) if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; - down_read(&uts_sem); + down_read(&uts_sem); error = __copy_to_user(&name->sysname, &utsname()->sysname, __OLD_UTS_LEN); diff --git a/trunk/arch/um/kernel/time.c b/trunk/arch/um/kernel/time.c index 1ac746a9eae1..259c49da7ff5 100644 --- a/trunk/arch/um/kernel/time.c +++ b/trunk/arch/um/kernel/time.c @@ -1,126 +1,189 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/clockchips.h" +#include "linux/kernel.h" +#include "linux/module.h" +#include "linux/unistd.h" +#include "linux/stddef.h" +#include "linux/spinlock.h" +#include "linux/time.h" +#include "linux/sched.h" #include "linux/interrupt.h" -#include "linux/jiffies.h" -#include "linux/threads.h" +#include "linux/init.h" +#include "linux/delay.h" +#include "linux/hrtimer.h" #include "asm/irq.h" #include "asm/param.h" +#include "asm/current.h" #include "kern_util.h" +#include "mode.h" #include "os.h" +int hz(void) +{ + return(HZ); +} + /* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) { - return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ); + return (unsigned long long)jiffies_64 * (1000000000 / HZ); } -void timer_handler(int sig, struct uml_pt_regs *regs) -{ - unsigned long flags; - - local_irq_save(flags); - do_IRQ(TIMER_IRQ, regs); - local_irq_restore(flags); -} +#ifdef CONFIG_UML_REAL_TIME_CLOCK +static unsigned long long prev_nsecs[NR_CPUS]; +static long long delta[NR_CPUS]; /* Deviation per interval */ +#endif -static void itimer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +void timer_irq(union uml_pt_regs *regs) { - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - set_interval(); - break; - - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_ONESHOT: - disable_timer(); - break; - - case CLOCK_EVT_MODE_RESUME: - break; + unsigned long long ticks = 0; +#ifdef CONFIG_UML_REAL_TIME_CLOCK + int c = cpu(); + if(prev_nsecs[c]){ + /* We've had 1 tick */ + unsigned long long nsecs = os_nsecs(); + + delta[c] += nsecs - prev_nsecs[c]; + prev_nsecs[c] = nsecs; + + /* Protect against the host clock being set backwards */ + if(delta[c] < 0) + delta[c] = 0; + + ticks += (delta[c] * HZ) / BILLION; + delta[c] -= (ticks * BILLION) / HZ; + } + else prev_nsecs[c] = os_nsecs(); +#else + ticks = 1; +#endif + while(ticks > 0){ + do_IRQ(TIMER_IRQ, regs); + ticks--; } } -static int itimer_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - return timer_one_shot(delta + 1); -} +/* Protects local_offset */ +static DEFINE_SPINLOCK(timer_spinlock); +static unsigned long long local_offset = 0; -static struct clock_event_device itimer_clockevent = { - .name = "itimer", - .rating = 250, - .cpumask = CPU_MASK_ALL, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = itimer_set_mode, - .set_next_event = itimer_next_event, - .shift = 32, - .irq = 0, -}; - -static irqreturn_t um_timer(int irq, void *dev) +static inline unsigned long long get_time(void) { - (*itimer_clockevent.event_handler)(&itimer_clockevent); + unsigned long long nsecs; + unsigned long flags; - return IRQ_HANDLED; + spin_lock_irqsave(&timer_spinlock, flags); + nsecs = os_nsecs(); + nsecs += local_offset; + spin_unlock_irqrestore(&timer_spinlock, flags); + + return nsecs; } -static cycle_t itimer_read(void) +irqreturn_t um_timer(int irq, void *dev) { - return os_nsecs(); + unsigned long long nsecs; + unsigned long flags; + + write_seqlock_irqsave(&xtime_lock, flags); + + do_timer(1); + +#ifdef CONFIG_UML_REAL_TIME_CLOCK + nsecs = get_time(); +#else + nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec + + BILLION / HZ; +#endif + xtime.tv_sec = nsecs / NSEC_PER_SEC; + xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; + + write_sequnlock_irqrestore(&xtime_lock, flags); + + return IRQ_HANDLED; } -static struct clocksource itimer_clocksource = { - .name = "itimer", - .rating = 300, - .read = itimer_read, - .mask = CLOCKSOURCE_MASK(64), - .mult = 1, - .shift = 0, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void __init setup_itimer(void) +static void register_timer(void) { int err; err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); - if (err != 0) + if(err != 0) printk(KERN_ERR "register_timer : request_irq failed - " "errno = %d\n", -err); - itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32); - itimer_clockevent.max_delta_ns = - clockevent_delta2ns(60 * HZ, &itimer_clockevent); - itimer_clockevent.min_delta_ns = - clockevent_delta2ns(1, &itimer_clockevent); - err = clocksource_register(&itimer_clocksource); - if (err) { - printk(KERN_ERR "clocksource_register returned %d\n", err); - return; - } - clockevents_register_device(&itimer_clockevent); + err = set_interval(1); + if(err != 0) + printk(KERN_ERR "register_timer : set_interval failed - " + "errno = %d\n", -err); } extern void (*late_time_init)(void); -void __init time_init(void) +void time_init(void) { long long nsecs; - timer_init(); - nsecs = os_nsecs(); - set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC, - -nsecs % NSEC_PER_SEC); - set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC, - nsecs % NSEC_PER_SEC); - late_time_init = setup_itimer; + set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, + -nsecs % BILLION); + set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION); + late_time_init = register_timer; +} + +void do_gettimeofday(struct timeval *tv) +{ +#ifdef CONFIG_UML_REAL_TIME_CLOCK + unsigned long long nsecs = get_time(); +#else + unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION + + xtime.tv_nsec; +#endif + tv->tv_sec = nsecs / NSEC_PER_SEC; + /* Careful about calculations here - this was originally done as + * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC + * which gave bogus (> 1000000) values. Dunno why, suspect gcc + * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion + * problem that I missed. + */ + nsecs -= tv->tv_sec * NSEC_PER_SEC; + tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; +} + +static inline void set_time(unsigned long long nsecs) +{ + unsigned long long now; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + now = os_nsecs(); + local_offset = nsecs - now; + spin_unlock_irqrestore(&timer_spinlock, flags); + + clock_was_set(); +} + +int do_settimeofday(struct timespec *tv) +{ + set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); + + return 0; +} + +void timer_handler(int sig, union uml_pt_regs *regs) +{ + if(current_thread->cpu == 0) + timer_irq(regs); + local_irq_disable(); + irq_enter(); + update_process_times(CHOOSE_MODE( + (UPT_SC(regs) && user_context(UPT_SP(regs))), + (regs)->skas.is_user)); + irq_exit(); + local_irq_enable(); } diff --git a/trunk/arch/um/kernel/tlb.c b/trunk/arch/um/kernel/tlb.c index f4a0e407eee4..8a8d52851443 100644 --- a/trunk/arch/um/kernel/tlb.c +++ b/trunk/arch/um/kernel/tlb.c @@ -1,182 +1,130 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #include "linux/mm.h" +#include "asm/page.h" +#include "asm/pgalloc.h" #include "asm/pgtable.h" #include "asm/tlbflush.h" +#include "choose-mode.h" +#include "mode_kern.h" #include "as-layout.h" +#include "tlb.h" +#include "mem.h" #include "mem_user.h" #include "os.h" -#include "skas.h" -#include "tlb.h" - -struct host_vm_change { - struct host_vm_op { - enum { NONE, MMAP, MUNMAP, MPROTECT } type; - union { - struct { - unsigned long addr; - unsigned long len; - unsigned int prot; - int fd; - __u64 offset; - } mmap; - struct { - unsigned long addr; - unsigned long len; - } munmap; - struct { - unsigned long addr; - unsigned long len; - unsigned int prot; - } mprotect; - } u; - } ops[1]; - int index; - struct mm_id *id; - void *data; - int force; -}; - -#define INIT_HVC(mm, force) \ - ((struct host_vm_change) \ - { .ops = { { .type = NONE } }, \ - .id = &mm->context.id, \ - .data = NULL, \ - .index = 0, \ - .force = force }) - -static int do_ops(struct host_vm_change *hvc, int end, - int finished) -{ - struct host_vm_op *op; - int i, ret = 0; - - for (i = 0; i < end && !ret; i++) { - op = &hvc->ops[i]; - switch(op->type) { - case MMAP: - ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, - op->u.mmap.prot, op->u.mmap.fd, - op->u.mmap.offset, finished, &hvc->data); - break; - case MUNMAP: - ret = unmap(hvc->id, op->u.munmap.addr, - op->u.munmap.len, finished, &hvc->data); - break; - case MPROTECT: - ret = protect(hvc->id, op->u.mprotect.addr, - op->u.mprotect.len, op->u.mprotect.prot, - finished, &hvc->data); - break; - default: - printk(KERN_ERR "Unknown op type %d in do_ops\n", - op->type); - break; - } - } - - return ret; -} static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, - unsigned int prot, struct host_vm_change *hvc) + unsigned int prot, struct host_vm_op *ops, int *index, + int last_filled, union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, struct host_vm_op *, + int, int, void **)) { __u64 offset; struct host_vm_op *last; int fd, ret = 0; fd = phys_mapping(phys, &offset); - if (hvc->index != 0) { - last = &hvc->ops[hvc->index - 1]; - if ((last->type == MMAP) && + if(*index != -1){ + last = &ops[*index]; + if((last->type == MMAP) && (last->u.mmap.addr + last->u.mmap.len == virt) && (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) && - (last->u.mmap.offset + last->u.mmap.len == offset)) { + (last->u.mmap.offset + last->u.mmap.len == offset)){ last->u.mmap.len += len; return 0; } } - if (hvc->index == ARRAY_SIZE(hvc->ops)) { - ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); - hvc->index = 0; + if(*index == last_filled){ + ret = (*do_ops)(mmu, ops, last_filled, 0, flush); + *index = -1; } - hvc->ops[hvc->index++] = ((struct host_vm_op) - { .type = MMAP, - .u = { .mmap = { .addr = virt, - .len = len, - .prot = prot, - .fd = fd, - .offset = offset } + ops[++*index] = ((struct host_vm_op) { .type = MMAP, + .u = { .mmap = { + .addr = virt, + .len = len, + .prot = prot, + .fd = fd, + .offset = offset } } }); return ret; } static int add_munmap(unsigned long addr, unsigned long len, - struct host_vm_change *hvc) + struct host_vm_op *ops, int *index, int last_filled, + union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, struct host_vm_op *, + int, int, void **)) { struct host_vm_op *last; int ret = 0; - if (hvc->index != 0) { - last = &hvc->ops[hvc->index - 1]; - if ((last->type == MUNMAP) && - (last->u.munmap.addr + last->u.mmap.len == addr)) { + if(*index != -1){ + last = &ops[*index]; + if((last->type == MUNMAP) && + (last->u.munmap.addr + last->u.mmap.len == addr)){ last->u.munmap.len += len; return 0; } } - if (hvc->index == ARRAY_SIZE(hvc->ops)) { - ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); - hvc->index = 0; + if(*index == last_filled){ + ret = (*do_ops)(mmu, ops, last_filled, 0, flush); + *index = -1; } - hvc->ops[hvc->index++] = ((struct host_vm_op) - { .type = MUNMAP, - .u = { .munmap = { .addr = addr, - .len = len } } }); + ops[++*index] = ((struct host_vm_op) { .type = MUNMAP, + .u = { .munmap = { + .addr = addr, + .len = len } } }); return ret; } static int add_mprotect(unsigned long addr, unsigned long len, - unsigned int prot, struct host_vm_change *hvc) + unsigned int prot, struct host_vm_op *ops, int *index, + int last_filled, union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, struct host_vm_op *, + int, int, void **)) { struct host_vm_op *last; int ret = 0; - if (hvc->index != 0) { - last = &hvc->ops[hvc->index - 1]; - if ((last->type == MPROTECT) && + if(*index != -1){ + last = &ops[*index]; + if((last->type == MPROTECT) && (last->u.mprotect.addr + last->u.mprotect.len == addr) && - (last->u.mprotect.prot == prot)) { + (last->u.mprotect.prot == prot)){ last->u.mprotect.len += len; return 0; } } - if (hvc->index == ARRAY_SIZE(hvc->ops)) { - ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); - hvc->index = 0; + if(*index == last_filled){ + ret = (*do_ops)(mmu, ops, last_filled, 0, flush); + *index = -1; } - hvc->ops[hvc->index++] = ((struct host_vm_op) - { .type = MPROTECT, - .u = { .mprotect = { .addr = addr, - .len = len, - .prot = prot } } }); + ops[++*index] = ((struct host_vm_op) { .type = MPROTECT, + .u = { .mprotect = { + .addr = addr, + .len = len, + .prot = prot } } }); return ret; } #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) static inline int update_pte_range(pmd_t *pmd, unsigned long addr, - unsigned long end, - struct host_vm_change *hvc) + unsigned long end, struct host_vm_op *ops, + int last_op, int *op_index, int force, + union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, + struct host_vm_op *, int, int, + void **)) { pte_t *pte; int r, w, x, prot, ret = 0; @@ -194,22 +142,29 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, } prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | (x ? UM_PROT_EXEC : 0)); - if (hvc->force || pte_newpage(*pte)) { - if (pte_present(*pte)) + if(force || pte_newpage(*pte)){ + if(pte_present(*pte)) ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, prot, hvc); - else ret = add_munmap(addr, PAGE_SIZE, hvc); + PAGE_SIZE, prot, ops, op_index, + last_op, mmu, flush, do_ops); + else ret = add_munmap(addr, PAGE_SIZE, ops, op_index, + last_op, mmu, flush, do_ops); } - else if (pte_newprot(*pte)) - ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); + else if(pte_newprot(*pte)) + ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index, + last_op, mmu, flush, do_ops); *pte = pte_mkuptodate(*pte); } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); return ret; } static inline int update_pmd_range(pud_t *pud, unsigned long addr, - unsigned long end, - struct host_vm_change *hvc) + unsigned long end, struct host_vm_op *ops, + int last_op, int *op_index, int force, + union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, + struct host_vm_op *, int, int, + void **)) { pmd_t *pmd; unsigned long next; @@ -218,20 +173,28 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr, pmd = pmd_offset(pud, addr); do { next = pmd_addr_end(addr, end); - if (!pmd_present(*pmd)) { - if (hvc->force || pmd_newpage(*pmd)) { - ret = add_munmap(addr, next - addr, hvc); + if(!pmd_present(*pmd)){ + if(force || pmd_newpage(*pmd)){ + ret = add_munmap(addr, next - addr, ops, + op_index, last_op, mmu, + flush, do_ops); pmd_mkuptodate(*pmd); } } - else ret = update_pte_range(pmd, addr, next, hvc); + else ret = update_pte_range(pmd, addr, next, ops, last_op, + op_index, force, mmu, flush, + do_ops); } while (pmd++, addr = next, ((addr != end) && !ret)); return ret; } static inline int update_pud_range(pgd_t *pgd, unsigned long addr, - unsigned long end, - struct host_vm_change *hvc) + unsigned long end, struct host_vm_op *ops, + int last_op, int *op_index, int force, + union mm_context *mmu, void **flush, + int (*do_ops)(union mm_context *, + struct host_vm_op *, int, int, + void **)) { pud_t *pud; unsigned long next; @@ -240,45 +203,56 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr, pud = pud_offset(pgd, addr); do { next = pud_addr_end(addr, end); - if (!pud_present(*pud)) { - if (hvc->force || pud_newpage(*pud)) { - ret = add_munmap(addr, next - addr, hvc); + if(!pud_present(*pud)){ + if(force || pud_newpage(*pud)){ + ret = add_munmap(addr, next - addr, ops, + op_index, last_op, mmu, + flush, do_ops); pud_mkuptodate(*pud); } } - else ret = update_pmd_range(pud, addr, next, hvc); + else ret = update_pmd_range(pud, addr, next, ops, last_op, + op_index, force, mmu, flush, + do_ops); } while (pud++, addr = next, ((addr != end) && !ret)); return ret; } void fix_range_common(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force) + unsigned long end_addr, int force, + int (*do_ops)(union mm_context *, struct host_vm_op *, + int, int, void **)) { pgd_t *pgd; - struct host_vm_change hvc; + union mm_context *mmu = &mm->context; + struct host_vm_op ops[1]; unsigned long addr = start_addr, next; - int ret = 0; + int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1; + void *flush = NULL; - hvc = INIT_HVC(mm, force); + ops[0].type = NONE; pgd = pgd_offset(mm, addr); do { next = pgd_addr_end(addr, end_addr); - if (!pgd_present(*pgd)) { - if (force || pgd_newpage(*pgd)) { - ret = add_munmap(addr, next - addr, &hvc); + if(!pgd_present(*pgd)){ + if (force || pgd_newpage(*pgd)){ + ret = add_munmap(addr, next - addr, ops, + &op_index, last_op, mmu, + &flush, do_ops); pgd_mkuptodate(*pgd); } } - else ret = update_pud_range(pgd, addr, next, &hvc); + else ret = update_pud_range(pgd, addr, next, ops, last_op, + &op_index, force, mmu, &flush, + do_ops); } while (pgd++, addr = next, ((addr != end_addr) && !ret)); - if (!ret) - ret = do_ops(&hvc, hvc.index, 1); + if(!ret) + ret = (*do_ops)(mmu, ops, op_index, 1, &flush); /* This is not an else because ret is modified above */ - if (ret) { - printk(KERN_ERR "fix_range_common: failed, killing current " - "process\n"); + if(ret) { + printk("fix_range_common: failed, killing current process\n"); force_sig(SIGKILL, current); } } @@ -294,17 +268,17 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) int updated = 0, err; mm = &init_mm; - for (addr = start; addr < end;) { + for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - if (!pgd_present(*pgd)) { + if(!pgd_present(*pgd)){ last = ADD_ROUND(addr, PGDIR_SIZE); - if (last > end) + if(last > end) last = end; - if (pgd_newpage(*pgd)) { + if(pgd_newpage(*pgd)){ updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if (err < 0) + if(err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -313,15 +287,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pud = pud_offset(pgd, addr); - if (!pud_present(*pud)) { + if(!pud_present(*pud)){ last = ADD_ROUND(addr, PUD_SIZE); - if (last > end) + if(last > end) last = end; - if (pud_newpage(*pud)) { + if(pud_newpage(*pud)){ updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if (err < 0) + if(err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -330,15 +304,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) { + if(!pmd_present(*pmd)){ last = ADD_ROUND(addr, PMD_SIZE); - if (last > end) + if(last > end) last = end; - if (pmd_newpage(*pmd)) { + if(pmd_newpage(*pmd)){ updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if (err < 0) + if(err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -347,110 +321,45 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pte = pte_offset_kernel(pmd, addr); - if (!pte_present(*pte) || pte_newpage(*pte)) { + if(!pte_present(*pte) || pte_newpage(*pte)){ updated = 1; err = os_unmap_memory((void *) addr, PAGE_SIZE); - if (err < 0) + if(err < 0) panic("munmap failed, errno = %d\n", -err); - if (pte_present(*pte)) + if(pte_present(*pte)) map_memory(addr, pte_val(*pte) & PAGE_MASK, PAGE_SIZE, 1, 1, 1); } - else if (pte_newprot(*pte)) { + else if(pte_newprot(*pte)){ updated = 1; os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); } addr += PAGE_SIZE; } - return updated; -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - struct mm_struct *mm = vma->vm_mm; - void *flush = NULL; - int r, w, x, prot, err = 0; - struct mm_id *mm_id; - - address &= PAGE_MASK; - pgd = pgd_offset(mm, address); - if (!pgd_present(*pgd)) - goto kill; - - pud = pud_offset(pgd, address); - if (!pud_present(*pud)) - goto kill; - - pmd = pmd_offset(pud, address); - if (!pmd_present(*pmd)) - goto kill; - - pte = pte_offset_kernel(pmd, address); - - r = pte_read(*pte); - w = pte_write(*pte); - x = pte_exec(*pte); - if (!pte_young(*pte)) { - r = 0; - w = 0; - } else if (!pte_dirty(*pte)) { - w = 0; - } - - mm_id = &mm->context.id; - prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | - (x ? UM_PROT_EXEC : 0)); - if (pte_newpage(*pte)) { - if (pte_present(*pte)) { - unsigned long long offset; - int fd; - - fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); - err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, - 1, &flush); - } - else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); - } - else if (pte_newprot(*pte)) - err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); - - if (err) - goto kill; - - *pte = pte_mkuptodate(*pte); - - return; - -kill: - printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address); - force_sig(SIGKILL, current); + return(updated); } pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) { - return pgd_offset(mm, address); + return(pgd_offset(mm, address)); } pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) { - return pud_offset(pgd, address); + return(pud_offset(pgd, address)); } pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) { - return pmd_offset(pud, address); + return(pmd_offset(pud, address)); } pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) { - return pte_offset_kernel(pmd, address); + return(pte_offset_kernel(pmd, address)); } pte_t *addr_pte(struct task_struct *task, unsigned long addr) @@ -459,7 +368,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) pud_t *pud = pud_offset(pgd, addr); pmd_t *pmd = pmd_offset(pud, addr); - return pte_offset_map(pmd, addr); + return(pte_offset_map(pmd, addr)); } void flush_tlb_all(void) @@ -469,58 +378,35 @@ void flush_tlb_all(void) void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - flush_tlb_kernel_range_common(start, end); + CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, + flush_tlb_kernel_range_common, start, end); } void flush_tlb_kernel_vm(void) { - flush_tlb_kernel_range_common(start_vm, end_vm); + CHOOSE_MODE(flush_tlb_kernel_vm_tt(), + flush_tlb_kernel_range_common(start_vm, end_vm)); } void __flush_tlb_one(unsigned long addr) { - flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); -} - -static void fix_range(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force) -{ - if (!proc_mm && (end_addr > STUB_START)) - end_addr = STUB_START; - - fix_range_common(mm, start_addr, end_addr, force); + CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); } void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (vma->vm_mm == NULL) - flush_tlb_kernel_range_common(start, end); - else fix_range(vma->vm_mm, start, end, 0); + CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, + end); } void flush_tlb_mm(struct mm_struct *mm) { - unsigned long end; - - /* - * Don't bother flushing if this address space is about to be - * destroyed. - */ - if (atomic_read(&mm->mm_users) == 0) - return; - - end = proc_mm ? task_size : STUB_START; - fix_range(mm, 0, end, 0); + CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); } void force_flush_all(void) { - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma = mm->mmap; - - while (vma != NULL) { - fix_range(mm, vma->vm_start, vma->vm_end, 1); - vma = vma->vm_next; - } + CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); } + diff --git a/trunk/arch/um/kernel/trap.c b/trunk/arch/um/kernel/trap.c index bd060551e619..3850d53f79fd 100644 --- a/trunk/arch/um/kernel/trap.c +++ b/trunk/arch/um/kernel/trap.c @@ -1,24 +1,40 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include -#include -#include -#include -#include -#include "arch.h" -#include "as-layout.h" +#include "linux/kernel.h" +#include "asm/errno.h" +#include "linux/sched.h" +#include "linux/mm.h" +#include "linux/spinlock.h" +#include "linux/init.h" +#include "linux/ptrace.h" +#include "asm/semaphore.h" +#include "asm/pgtable.h" +#include "asm/pgalloc.h" +#include "asm/tlbflush.h" +#include "asm/a.out.h" +#include "asm/current.h" +#include "asm/irq.h" +#include "sysdep/sigcontext.h" #include "kern_util.h" -#include "os.h" +#include "as-layout.h" +#include "arch.h" +#include "kern.h" +#include "chan_kern.h" +#include "mconsole_kern.h" +#include "mem.h" +#include "mem_kern.h" #include "sysdep/sigcontext.h" +#include "sysdep/ptrace.h" +#include "os.h" +#ifdef CONFIG_MODE_SKAS +#include "skas.h" +#endif +#include "os.h" -/* - * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by - * segv(). - */ +/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out) { @@ -32,33 +48,31 @@ int handle_page_fault(unsigned long address, unsigned long ip, *code_out = SEGV_MAPERR; - /* - * If the fault was during atomic operation, don't take the fault, just - * fail. - */ + /* If the fault was during atomic operation, don't take the fault, just + * fail. */ if (in_atomic()) goto out_nosemaphore; down_read(&mm->mmap_sem); vma = find_vma(mm, address); - if (!vma) + if(!vma) goto out; - else if (vma->vm_start <= address) + else if(vma->vm_start <= address) goto good_area; - else if (!(vma->vm_flags & VM_GROWSDOWN)) + else if(!(vma->vm_flags & VM_GROWSDOWN)) goto out; - else if (is_user && !ARCH_IS_STACKGROW(address)) + else if(is_user && !ARCH_IS_STACKGROW(address)) goto out; - else if (expand_stack(vma, address)) + else if(expand_stack(vma, address)) goto out; good_area: *code_out = SEGV_ACCERR; - if (is_write && !(vma->vm_flags & VM_WRITE)) + if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; /* Don't require VM_READ|VM_EXEC for write faults! */ - if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) + if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) goto out; do { @@ -84,10 +98,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, pud = pud_offset(pgd, address); pmd = pmd_offset(pud, address); pte = pte_offset_kernel(pmd, address); - } while (!pte_present(*pte)); + } while(!pte_present(*pte)); err = 0; - /* - * The below warning was added in place of + /* The below warning was added in place of * pte_mkyoung(); if (is_write) pte_mkdirty(); * If it's triggered, we'd see normally a hang here (a clean pte is * marked read-only to emulate the dirty bit). @@ -101,7 +114,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, out: up_read(&mm->mmap_sem); out_nosemaphore: - return err; + return(err); /* * We ran out of memory, or some other thing happened to us that made @@ -128,11 +141,11 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) force_sig_info(SIGSEGV, &si, current); } -static void segv_handler(int sig, struct uml_pt_regs *regs) +static void segv_handler(int sig, union uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); - if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { + if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ bad_segv(*fi, UPT_IP(regs)); return; } @@ -146,49 +159,45 @@ static void segv_handler(int sig, struct uml_pt_regs *regs) * give us bad data! */ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, - struct uml_pt_regs *regs) + union uml_pt_regs *regs) { struct siginfo si; - jmp_buf *catcher; + void *catcher; int err; int is_write = FAULT_WRITE(fi); unsigned long address = FAULT_ADDRESS(fi); - if (!is_user && (address >= start_vm) && (address < end_vm)) { + if(!is_user && (address >= start_vm) && (address < end_vm)){ flush_tlb_kernel_vm(); return 0; } - else if (current->mm == NULL) { + else if(current->mm == NULL) { show_regs(container_of(regs, struct pt_regs, regs)); - panic("Segfault with no mm"); + panic("Segfault with no mm"); } if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) - err = handle_page_fault(address, ip, is_write, is_user, - &si.si_code); + err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); else { err = -EFAULT; - /* - * A thread accessed NULL, we get a fault, but CR2 is invalid. - * This code is used in __do_copy_from_user() of TT mode. - * XXX tt mode is gone, so maybe this isn't needed any more - */ + /* A thread accessed NULL, we get a fault, but CR2 is invalid. + * This code is used in __do_copy_from_user() of TT mode. */ address = 0; } catcher = current->thread.fault_catcher; - if (!err) + if(!err) return 0; - else if (catcher != NULL) { + else if(catcher != NULL){ current->thread.fault_addr = (void *) address; - UML_LONGJMP(catcher, 1); + do_longjmp(catcher, 1); } - else if (current->thread.fault_addr != NULL) + else if(current->thread.fault_addr != NULL) panic("fault_addr set but no fault catcher"); - else if (!is_user && arch_fixup(ip, regs)) + else if(!is_user && arch_fixup(ip, regs)) return 0; - if (!is_user) { + if(!is_user) { show_regs(container_of(regs, struct pt_regs, regs)); panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", address, ip); @@ -202,7 +211,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, current->thread.arch.faultinfo = fi; force_sig_info(SIGBUS, &si, current); } else if (err == -ENOMEM) { - printk(KERN_INFO "VM: killing process %s\n", current->comm); + printk("VM: killing process %s\n", current->comm); do_exit(SIGKILL); } else { BUG_ON(err != -EFAULT); @@ -214,15 +223,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, union uml_pt_regs *regs) { - if (arch_handle_signal(sig, regs)) + if(arch_handle_signal(sig, regs)) return; - if (!UPT_IS_USER(regs)) { - if (sig == SIGBUS) - printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " - "mount likely just ran out of space\n"); + if(!UPT_IS_USER(regs)){ + if(sig == SIGBUS) + printk("Bus error - the host /dev/shm or /tmp mount " + "likely just ran out of space\n"); panic("Kernel mode signal %d", sig); } @@ -230,14 +239,14 @@ void relay_signal(int sig, struct uml_pt_regs *regs) force_sig(sig, current); } -static void bus_handler(int sig, struct uml_pt_regs *regs) +static void bus_handler(int sig, union uml_pt_regs *regs) { - if (current->thread.fault_catcher != NULL) - UML_LONGJMP(current->thread.fault_catcher, 1); + if(current->thread.fault_catcher != NULL) + do_longjmp(current->thread.fault_catcher, 1); else relay_signal(sig, regs); } -static void winch(int sig, struct uml_pt_regs *regs) +static void winch(int sig, union uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } diff --git a/trunk/arch/um/kernel/tt/Makefile b/trunk/arch/um/kernel/tt/Makefile new file mode 100644 index 000000000000..6939e5af8472 --- /dev/null +++ b/trunk/arch/um/kernel/tt/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) +# Licensed under the GPL +# + +obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ + syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \ + uaccess.o uaccess_user.o + +obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ + +USER_OBJS := gdb.o tracer.o + +include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/kernel/tt/exec_kern.c b/trunk/arch/um/kernel/tt/exec_kern.c new file mode 100644 index 000000000000..40126cb51801 --- /dev/null +++ b/trunk/arch/um/kernel/tt/exec_kern.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/mm.h" +#include "asm/signal.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "asm/pgalloc.h" +#include "asm/tlbflush.h" +#include "kern_util.h" +#include "irq_user.h" +#include "mem_user.h" +#include "os.h" +#include "tlb.h" +#include "mode.h" + +static int exec_tramp(void *sig_stack) +{ + init_new_thread_stack(sig_stack, NULL); + init_new_thread_signals(); + os_stop_process(os_getpid()); + return(0); +} + +void flush_thread_tt(void) +{ + unsigned long stack; + int new_pid; + + stack = alloc_stack(0, 0); + if(stack == 0){ + printk(KERN_ERR + "flush_thread : failed to allocate temporary stack\n"); + do_exit(SIGKILL); + } + + new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); + if(new_pid < 0){ + printk(KERN_ERR + "flush_thread : new thread failed, errno = %d\n", + -new_pid); + do_exit(SIGKILL); + } + + if(current_thread->cpu == 0) + forward_interrupts(new_pid); + current->thread.request.op = OP_EXEC; + current->thread.request.u.exec.pid = new_pid; + unprotect_stack((unsigned long) current_thread); + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); + enable_timer(); + free_page(stack); + protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); + stack_protections((unsigned long) current_thread); + force_flush_all(); + unblock_signals(); +} + +void start_thread_tt(struct pt_regs *regs, unsigned long eip, + unsigned long esp) +{ + set_fs(USER_DS); + flush_tlb_mm(current->mm); + PT_REGS_IP(regs) = eip; + PT_REGS_SP(regs) = esp; + PT_FIX_EXEC_STACK(esp); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/exec_user.c b/trunk/arch/um/kernel/tt/exec_user.c new file mode 100644 index 000000000000..7b5f2181cf51 --- /dev/null +++ b/trunk/arch/um/kernel/tt/exec_user.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include "kern_util.h" +#include "user.h" +#include "ptrace_user.h" +#include "os.h" + +void do_exec(int old_pid, int new_pid) +{ + unsigned long regs[FRAME_SIZE]; + int err; + + if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || + (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) + tracer_panic("do_exec failed to attach proc - errno = %d", + errno); + + CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); + if (err < 0) + tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", + errno); + + if(ptrace_getregs(old_pid, regs) < 0) + tracer_panic("do_exec failed to get registers - errno = %d", + errno); + + os_kill_ptraced_process(old_pid, 0); + + if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) + tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno); + + if(ptrace_setregs(new_pid, regs) < 0) + tracer_panic("do_exec failed to start new proc - errno = %d", + errno); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/gdb.c b/trunk/arch/um/kernel/tt/gdb.c new file mode 100644 index 000000000000..030e4658f36b --- /dev/null +++ b/trunk/arch/um/kernel/tt/gdb.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include "ptrace_user.h" +#include "uml-config.h" +#include "kern_constants.h" +#include "chan_user.h" +#include "init.h" +#include "user.h" +#include "debug.h" +#include "kern_util.h" +#include "tt.h" +#include "sysdep/thread.h" +#include "os.h" + +extern int debugger_pid; +extern int debugger_fd; +extern int debugger_parent; + +int detach(int pid, int sig) +{ + return(ptrace(PTRACE_DETACH, pid, 0, sig)); +} + +int attach(int pid) +{ + int err; + + err = ptrace(PTRACE_ATTACH, pid, 0, 0); + if(err < 0) return(-errno); + else return(err); +} + +int cont(int pid) +{ + return(ptrace(PTRACE_CONT, pid, 0, 0)); +} + +#ifdef UML_CONFIG_PT_PROXY + +int debugger_signal(int status, pid_t pid) +{ + return(debugger_proxy(status, pid)); +} + +void child_signal(pid_t pid, int status) +{ + child_proxy(pid, status); +} + +static void gdb_announce(char *dev_name, int dev) +{ + printf("gdb assigned device '%s'\n", dev_name); +} + +static struct chan_opts opts = { + .announce = gdb_announce, + .xterm_title = "UML kernel debugger", + .raw = 0, + .tramp_stack = 0, + .in_kernel = 0, +}; + +/* Accessed by the tracing thread, which automatically serializes access */ +static void *xterm_data; +static int xterm_fd; + +extern void *xterm_init(char *, int, struct chan_opts *); +extern int xterm_open(int, int, int, void *, char **); +extern void xterm_close(int, void *); + +int open_gdb_chan(void) +{ + char stack[UM_KERN_PAGE_SIZE], *dummy; + + opts.tramp_stack = (unsigned long) stack; + xterm_data = xterm_init("", 0, &opts); + xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); + return(xterm_fd); +} + +static void exit_debugger_cb(void *unused) +{ + if(debugger_pid != -1){ + if(gdb_pid != -1){ + fake_child_exit(); + gdb_pid = -1; + } + else kill_child_dead(debugger_pid); + debugger_pid = -1; + if(debugger_parent != -1) + detach(debugger_parent, SIGINT); + } + if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); +} + +static void exit_debugger(void) +{ + initial_thread_cb(exit_debugger_cb, NULL); +} + +__uml_exitcall(exit_debugger); + +struct gdb_data { + char *str; + int err; +}; + +extern char *linux_prog; + +static void config_gdb_cb(void *arg) +{ + struct gdb_data *data = arg; + void *task; + int pid; + + data->err = -1; + if(debugger_pid != -1) exit_debugger_cb(NULL); + if(!strncmp(data->str, "pid,", strlen("pid,"))){ + data->str += strlen("pid,"); + pid = strtoul(data->str, NULL, 0); + task = cpu_tasks[0].task; + debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); + if(debugger_pid != -1){ + data->err = 0; + gdb_pid = pid; + } + return; + } + data->err = 0; + debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); + init_proxy(debugger_pid, 0, 0); +} + +int gdb_config(char *str, char **error_out) +{ + struct gdb_data data; + + if(*str++ != '=') return(-1); + data.str = str; + initial_thread_cb(config_gdb_cb, &data); + return(data.err); +} + +void remove_gdb_cb(void *unused) +{ + exit_debugger_cb(NULL); +} + +int gdb_remove(int unused, char **error_out) +{ + initial_thread_cb(remove_gdb_cb, NULL); + return 0; +} + +void signal_usr1(int sig) +{ + if(debugger_pid != -1){ + printf("The debugger is already running\n"); + return; + } + debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); + init_proxy(debugger_pid, 0, 0); +} + +int init_ptrace_proxy(int idle_pid, int startup, int stop) +{ + int pid, status; + + pid = start_debugger(linux_prog, startup, stop, &debugger_fd); + status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); + if(pid < 0){ + cont(idle_pid); + return(-1); + } + init_proxy(pid, 1, status); + return(pid); +} + +int attach_debugger(int idle_pid, int pid, int stop) +{ + int status = 0, err; + + err = attach(pid); + if(err < 0){ + printf("Failed to attach pid %d, errno = %d\n", pid, -err); + return(-1); + } + if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); + init_proxy(pid, 1, status); + return(pid); +} + +#ifdef notdef /* Put this back in when it does something useful */ +static int __init uml_gdb_init_setup(char *line, int *add) +{ + gdb_init = uml_strdup(line); + return 0; +} + +__uml_setup("gdb=", uml_gdb_init_setup, +"gdb=\n\n" +); +#endif + +static int __init uml_gdb_pid_setup(char *line, int *add) +{ + gdb_pid = strtoul(line, NULL, 0); + *add = 0; + return 0; +} + +__uml_setup("gdb-pid=", uml_gdb_pid_setup, +"gdb-pid=\n" +" gdb-pid is used to attach an external debugger to UML. This may be\n" +" an already-running gdb or a debugger-like process like strace.\n\n" +); + +#else + +int debugger_signal(int status, pid_t pid){ return(0); } +void child_signal(pid_t pid, int status){ } +int init_ptrace_proxy(int idle_pid, int startup, int stop) +{ + printf("debug requested when CONFIG_PT_PROXY is off\n"); + kill_child_dead(idle_pid); + exit(1); +} + +void signal_usr1(int sig) +{ + printf("debug requested when CONFIG_PT_PROXY is off\n"); +} + +int attach_debugger(int idle_pid, int pid, int stop) +{ + printf("attach_debugger called when CONFIG_PT_PROXY " + "is off\n"); + return(-1); +} + +int config_gdb(char *str) +{ + return(-1); +} + +int remove_gdb(void) +{ + return(-1); +} + +int init_parent_proxy(int pid) +{ + return(-1); +} + +void debugger_parent_signal(int status, int pid) +{ +} + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/gdb_kern.c b/trunk/arch/um/kernel/tt/gdb_kern.c new file mode 100644 index 000000000000..03b06bc00771 --- /dev/null +++ b/trunk/arch/um/kernel/tt/gdb_kern.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/init.h" +#include "mconsole_kern.h" + +#ifdef CONFIG_MCONSOLE + +extern int gdb_config(char *str, char **error_out); +extern int gdb_remove(int n, char **error_out); + +static struct mc_device gdb_mc = { + .list = INIT_LIST_HEAD(gdb_mc.list), + .name = "gdb", + .config = gdb_config, + .remove = gdb_remove, +}; + +int gdb_mc_init(void) +{ + mconsole_register_dev(&gdb_mc); + return(0); +} + +__initcall(gdb_mc_init); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/include/mode-tt.h b/trunk/arch/um/kernel/tt/include/mode-tt.h new file mode 100644 index 000000000000..e171e15fead5 --- /dev/null +++ b/trunk/arch/um/kernel/tt/include/mode-tt.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_TT_H__ +#define __MODE_TT_H__ + +#include "sysdep/ptrace.h" + +enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + +extern int tracing_pid; + +extern int tracer(int (*init_proc)(void *), void *sp); +extern void sig_handler_common_tt(int sig, void *sc); +extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); +extern void reboot_tt(void); +extern void halt_tt(void); +extern int is_tracer_winch(int pid, int fd, void *data); +extern void kill_off_processes_tt(void); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ksyms.c b/trunk/arch/um/kernel/tt/ksyms.c new file mode 100644 index 000000000000..84a9385a8fef --- /dev/null +++ b/trunk/arch/um/kernel/tt/ksyms.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/module.h" +#include "asm/uaccess.h" +#include "mode.h" + +EXPORT_SYMBOL(__do_copy_from_user); +EXPORT_SYMBOL(__do_copy_to_user); +EXPORT_SYMBOL(__do_strncpy_from_user); +EXPORT_SYMBOL(__do_strnlen_user); +EXPORT_SYMBOL(__do_clear_user); +EXPORT_SYMBOL(clear_user_tt); + +EXPORT_SYMBOL(tracing_pid); +EXPORT_SYMBOL(honeypot); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/mem.c b/trunk/arch/um/kernel/tt/mem.c new file mode 100644 index 000000000000..d0c3c4975f28 --- /dev/null +++ b/trunk/arch/um/kernel/tt/mem.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/mm.h" +#include "asm/uaccess.h" +#include "mem_user.h" +#include "kern_util.h" +#include "kern.h" +#include "tt.h" + +void before_mem_tt(unsigned long brk_start) +{ + if(debug) + remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); + remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); + remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); +} + +#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) +#define START (CONFIG_TOP_ADDR - SIZE) + +unsigned long set_task_sizes_tt(unsigned long *task_size_out) +{ + unsigned long host_task_size; + + /* Round up to the nearest 4M */ + host_task_size = ROUND_4M((unsigned long) &host_task_size); + *task_size_out = START; + + return host_task_size; +} diff --git a/trunk/arch/um/kernel/tt/mem_user.c b/trunk/arch/um/kernel/tt/mem_user.c new file mode 100644 index 000000000000..9774f6360c32 --- /dev/null +++ b/trunk/arch/um/kernel/tt/mem_user.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include "tt.h" +#include "mem_user.h" +#include "os.h" + +void remap_data(void *segment_start, void *segment_end, int w) +{ + void *addr; + unsigned long size; + int data, prot; + + if(w) prot = PROT_WRITE; + else prot = 0; + prot |= PROT_READ | PROT_EXEC; + size = (unsigned long) segment_end - + (unsigned long) segment_start; + data = create_mem_file(size); + addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); + if(addr == MAP_FAILED){ + perror("mapping new data segment"); + exit(1); + } + memcpy(addr, segment_start, size); + if(switcheroo(data, prot, addr, segment_start, size) < 0){ + printf("switcheroo failed\n"); + exit(1); + } +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/process_kern.c b/trunk/arch/um/kernel/tt/process_kern.c new file mode 100644 index 000000000000..74347adf81bf --- /dev/null +++ b/trunk/arch/um/kernel/tt/process_kern.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "linux/signal.h" +#include "linux/kernel.h" +#include "linux/interrupt.h" +#include "linux/ptrace.h" +#include "asm/system.h" +#include "asm/pgalloc.h" +#include "asm/ptrace.h" +#include "asm/tlbflush.h" +#include "irq_user.h" +#include "kern_util.h" +#include "os.h" +#include "kern.h" +#include "sigcontext.h" +#include "mem_user.h" +#include "tlb.h" +#include "mode.h" +#include "mode_kern.h" +#include "init.h" +#include "tt.h" + +void switch_to_tt(void *prev, void *next) +{ + struct task_struct *from, *to, *prev_sched; + unsigned long flags; + int err, vtalrm, alrm, prof, cpu; + char c; + + from = prev; + to = next; + + cpu = task_thread_info(from)->cpu; + if(cpu == 0) + forward_interrupts(to->thread.mode.tt.extern_pid); +#ifdef CONFIG_SMP + forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); +#endif + local_irq_save(flags); + + vtalrm = change_sig(SIGVTALRM, 0); + alrm = change_sig(SIGALRM, 0); + prof = change_sig(SIGPROF, 0); + + forward_pending_sigio(to->thread.mode.tt.extern_pid); + + c = 0; + + /* Notice that here we "up" the semaphore on which "to" is waiting, and + * below (the read) we wait on this semaphore (which is implemented by + * switch_pipe) and go sleeping. Thus, after that, we have resumed in + * "to", and can't use any more the value of "from" (which is outdated), + * nor the value in "to" (since it was the task which stole us the CPU, + * which we don't care about). */ + + err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); + if(err != sizeof(c)) + panic("write of switch_pipe failed, err = %d", -err); + + if(from->thread.mode.tt.switch_pipe[0] == -1) + os_kill_process(os_getpid(), 0); + + err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, + sizeof(c)); + if(err != sizeof(c)) + panic("read of switch_pipe failed, errno = %d", -err); + + /* If the process that we have just scheduled away from has exited, + * then it needs to be killed here. The reason is that, even though + * it will kill itself when it next runs, that may be too late. Its + * stack will be freed, possibly before then, and if that happens, + * we have a use-after-free situation. So, it gets killed here + * in case it has not already killed itself. + */ + prev_sched = current->thread.prev_sched; + if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) + os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); + + change_sig(SIGVTALRM, vtalrm); + change_sig(SIGALRM, alrm); + change_sig(SIGPROF, prof); + + arch_switch_to_tt(prev_sched, current); + + flush_tlb_all(); + local_irq_restore(flags); +} + +void release_thread_tt(struct task_struct *task) +{ + int pid = task->thread.mode.tt.extern_pid; + + /* + * We first have to kill the other process, before + * closing its switch_pipe. Else it might wake up + * and receive "EOF" before we could kill it. + */ + if(os_getpid() != pid) + os_kill_process(pid, 0); + + os_close_file(task->thread.mode.tt.switch_pipe[0]); + os_close_file(task->thread.mode.tt.switch_pipe[1]); + /* use switch_pipe as flag: thread is released */ + task->thread.mode.tt.switch_pipe[0] = -1; +} + +void suspend_new_thread(int fd) +{ + int err; + char c; + + os_stop_process(os_getpid()); + err = os_read_file(fd, &c, sizeof(c)); + if(err != sizeof(c)) + panic("read failed in suspend_new_thread, err = %d", -err); +} + +void schedule_tail(struct task_struct *prev); + +static void new_thread_handler(int sig) +{ + unsigned long disable; + int (*fn)(void *); + void *arg; + + fn = current->thread.request.u.thread.proc; + arg = current->thread.request.u.thread.arg; + + UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); + disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | + (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); + SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; + + suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); + + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + + init_new_thread_signals(); + enable_timer(); + free_page(current->thread.temp_stack); + set_cmdline("(kernel thread)"); + + change_sig(SIGUSR1, 1); + change_sig(SIGPROF, 1); + local_irq_enable(); + if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) + do_exit(0); + + /* XXX No set_user_mode here because a newly execed process will + * immediately segfault on its non-existent IP, coming straight back + * to the signal handler, which will call set_user_mode on its way + * out. This should probably change since it's confusing. + */ +} + +static int new_thread_proc(void *stack) +{ + /* local_irq_disable is needed to block out signals until this thread is + * properly scheduled. Otherwise, the tracing thread will get mighty + * upset about any signals that arrive before that. + * This has the complication that it sets the saved signal mask in + * the sigcontext to block signals. This gets restored when this + * thread (or a descendant, since they get a copy of this sigcontext) + * returns to userspace. + * So, this is compensated for elsewhere. + * XXX There is still a small window until local_irq_disable() actually + * finishes where signals are possible - shouldn't be a problem in + * practice since SIGIO hasn't been forwarded here yet, and the + * local_irq_disable should finish before a SIGVTALRM has time to be + * delivered. + */ + + local_irq_disable(); + init_new_thread_stack(stack, new_thread_handler); + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + return(0); +} + +/* Signal masking - signals are blocked at the start of fork_tramp. They + * are re-enabled when finish_fork_handler is entered by fork_tramp hitting + * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, + * so it is blocked before it's called. They are re-enabled on sigreturn + * despite the fact that they were blocked when the SIGUSR1 was issued because + * copy_thread copies the parent's sigcontext, including the signal mask + * onto the signal frame. + */ + +void finish_fork_handler(int sig) +{ + UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); + suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); + + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + + enable_timer(); + change_sig(SIGVTALRM, 1); + local_irq_enable(); + if(current->mm != current->parent->mm) + protect_memory(uml_reserved, high_physmem - uml_reserved, 1, + 1, 0, 1); + stack_protections((unsigned long) current_thread); + + free_page(current->thread.temp_stack); + local_irq_disable(); + change_sig(SIGUSR1, 0); + set_user_mode(current); +} + +int fork_tramp(void *stack) +{ + local_irq_disable(); + arch_init_thread(); + init_new_thread_stack(stack, finish_fork_handler); + + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + return(0); +} + +int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct * p, + struct pt_regs *regs) +{ + int (*tramp)(void *); + int new_pid, err; + unsigned long stack; + + if(current->thread.forking) + tramp = fork_tramp; + else { + tramp = new_thread_proc; + p->thread.request.u.thread = current->thread.request.u.thread; + } + + err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); + if(err < 0){ + printk("copy_thread : pipe failed, err = %d\n", -err); + return(err); + } + + stack = alloc_stack(0, 0); + if(stack == 0){ + printk(KERN_ERR "copy_thread : failed to allocate " + "temporary stack\n"); + return(-ENOMEM); + } + + clone_flags &= CLONE_VM; + p->thread.temp_stack = stack; + new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); + if(new_pid < 0){ + printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", + -new_pid); + return(new_pid); + } + + if(current->thread.forking){ + sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); + SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); + if(sp != 0) + SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; + } + p->thread.mode.tt.extern_pid = new_pid; + + current->thread.request.op = OP_FORK; + current->thread.request.u.fork.pid = new_pid; + os_usr1_process(os_getpid()); + + /* Enable the signal and then disable it to ensure that it is handled + * here, and nowhere else. + */ + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); + err = 0; + return(err); +} + +void reboot_tt(void) +{ + current->thread.request.op = OP_REBOOT; + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); +} + +void halt_tt(void) +{ + current->thread.request.op = OP_HALT; + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); +} + +void kill_off_processes_tt(void) +{ + struct task_struct *p; + int me; + + me = os_getpid(); + for_each_process(p){ + if(p->thread.mode.tt.extern_pid != me) + os_kill_process(p->thread.mode.tt.extern_pid, 0); + } + if(init_task.thread.mode.tt.extern_pid != me) + os_kill_process(init_task.thread.mode.tt.extern_pid, 0); +} + +void initial_thread_cb_tt(void (*proc)(void *), void *arg) +{ + if(os_getpid() == tracing_pid){ + (*proc)(arg); + } + else { + current->thread.request.op = OP_CB; + current->thread.request.u.cb.proc = proc; + current->thread.request.u.cb.arg = arg; + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); + } +} + +int do_proc_op(void *t, int proc_id) +{ + struct task_struct *task; + struct thread_struct *thread; + int op, pid; + + task = t; + thread = &task->thread; + op = thread->request.op; + switch(op){ + case OP_NONE: + case OP_TRACE_ON: + break; + case OP_EXEC: + pid = thread->request.u.exec.pid; + do_exec(thread->mode.tt.extern_pid, pid); + thread->mode.tt.extern_pid = pid; + cpu_tasks[task_thread_info(task)->cpu].pid = pid; + break; + case OP_FORK: + attach_process(thread->request.u.fork.pid); + break; + case OP_CB: + (*thread->request.u.cb.proc)(thread->request.u.cb.arg); + break; + case OP_REBOOT: + case OP_HALT: + break; + default: + tracer_panic("Bad op in do_proc_op"); + break; + } + thread->request.op = OP_NONE; + return(op); +} + +void init_idle_tt(void) +{ + default_idle(); +} + +extern void start_kernel(void); + +static int start_kernel_proc(void *unused) +{ + int pid; + + block_signals(); + pid = os_getpid(); + + cpu_tasks[0].pid = pid; + cpu_tasks[0].task = current; +#ifdef CONFIG_SMP + cpu_online_map = cpumask_of_cpu(0); +#endif + if(debug) os_stop_process(pid); + start_kernel(); + return(0); +} + +void set_tracing(void *task, int tracing) +{ + ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; +} + +int is_tracing(void *t) +{ + return (((struct task_struct *) t)->thread.mode.tt.tracing); +} + +int set_user_mode(void *t) +{ + struct task_struct *task; + + task = t ? t : current; + if(task->thread.mode.tt.tracing) + return(1); + task->thread.request.op = OP_TRACE_ON; + os_usr1_process(os_getpid()); + return(0); +} + +void set_init_pid(int pid) +{ + int err; + + init_task.thread.mode.tt.extern_pid = pid; + err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); + if(err) + panic("Can't create switch pipe for init_task, errno = %d", + -err); +} + +int start_uml_tt(void) +{ + void *sp; + int pages; + + pages = (1 << CONFIG_KERNEL_STACK_ORDER); + sp = task_stack_page(&init_task) + + pages * PAGE_SIZE - sizeof(unsigned long); + return(tracer(start_kernel_proc, sp)); +} + +int external_pid_tt(struct task_struct *task) +{ + return(task->thread.mode.tt.extern_pid); +} + +int thread_pid_tt(struct task_struct *task) +{ + return(task->thread.mode.tt.extern_pid); +} + +int is_valid_pid(int pid) +{ + struct task_struct *task; + + read_lock(&tasklist_lock); + for_each_process(task){ + if(task->thread.mode.tt.extern_pid == pid){ + read_unlock(&tasklist_lock); + return(1); + } + } + read_unlock(&tasklist_lock); + return(0); +} diff --git a/trunk/arch/um/kernel/tt/ptproxy/Makefile b/trunk/arch/um/kernel/tt/ptproxy/Makefile new file mode 100644 index 000000000000..3ad5b774de59 --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +obj-y = proxy.o ptrace.o sysdep.o wait.o + +USER_OBJS := $(obj-y) + +include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/kernel/tt/ptproxy/proxy.c b/trunk/arch/um/kernel/tt/ptproxy/proxy.c new file mode 100644 index 000000000000..420c23f311f3 --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/proxy.c @@ -0,0 +1,377 @@ +/********************************************************************** +proxy.c + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. + +Jeff Dike (jdike@karaya.com) : Modified for integration into uml +**********************************************************************/ + +/* XXX This file shouldn't refer to CONFIG_* */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ptrace_user.h" + +#include "ptproxy.h" +#include "sysdep.h" +#include "wait.h" + +#include "user.h" +#include "os.h" +#include "tempfile.h" + +static int debugger_wait(debugger_state *debugger, int *status, int options, + int (*syscall)(debugger_state *debugger, pid_t child), + int (*normal_return)(debugger_state *debugger, + pid_t unused), + int (*wait_return)(debugger_state *debugger, + pid_t unused)) +{ + if(debugger->real_wait){ + debugger->handle_trace = normal_return; + syscall_continue(debugger->pid); + debugger->real_wait = 0; + return(1); + } + debugger->wait_status_ptr = status; + debugger->wait_options = options; + if((debugger->debugee != NULL) && debugger->debugee->event){ + syscall_continue(debugger->pid); + wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, + NULL); + (*wait_return)(debugger, -1); + return(0); + } + else if(debugger->wait_options & WNOHANG){ + syscall_cancel(debugger->pid, 0); + debugger->handle_trace = syscall; + return(0); + } + else { + syscall_pause(debugger->pid); + debugger->handle_trace = wait_return; + debugger->waiting = 1; + } + return(1); +} + +/* + * Handle debugger trap, i.e. syscall. + */ + +int debugger_syscall(debugger_state *debugger, pid_t child) +{ + long arg1, arg2, arg3, arg4, arg5, result; + int syscall, ret = 0; + + syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, + &arg5); + + switch(syscall){ + case __NR_execve: + /* execve never returns */ + debugger->handle_trace = debugger_syscall; + break; + + case __NR_ptrace: + if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; + if(!debugger->debugee->in_context) + child = debugger->debugee->pid; + result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, + &ret); + syscall_cancel(debugger->pid, result); + debugger->handle_trace = debugger_syscall; + return(ret); + +#ifdef __NR_waitpid + case __NR_waitpid: +#endif + case __NR_wait4: + if(!debugger_wait(debugger, (int *) arg2, arg3, + debugger_syscall, debugger_normal_return, + proxy_wait_return)) + return(0); + break; + + case __NR_kill: + if(!debugger->debugee->in_context) + child = debugger->debugee->pid; + if(arg1 == debugger->debugee->pid){ + result = kill(child, arg2); + syscall_cancel(debugger->pid, result); + debugger->handle_trace = debugger_syscall; + return(0); + } + else debugger->handle_trace = debugger_normal_return; + break; + + default: + debugger->handle_trace = debugger_normal_return; + } + + syscall_continue(debugger->pid); + return(0); +} + +/* Used by the tracing thread */ +static debugger_state parent; +static int parent_syscall(debugger_state *debugger, int pid); + +int init_parent_proxy(int pid) +{ + parent = ((debugger_state) { .pid = pid, + .wait_options = 0, + .wait_status_ptr = NULL, + .waiting = 0, + .real_wait = 0, + .expecting_child = 0, + .handle_trace = parent_syscall, + .debugee = NULL } ); + return(0); +} + +int parent_normal_return(debugger_state *debugger, pid_t unused) +{ + debugger->handle_trace = parent_syscall; + syscall_continue(debugger->pid); + return(0); +} + +static int parent_syscall(debugger_state *debugger, int pid) +{ + long arg1, arg2, arg3, arg4, arg5; + int syscall; + + syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); + + if((syscall == __NR_wait4) +#ifdef __NR_waitpid + || (syscall == __NR_waitpid) +#endif + ){ + debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, + parent_normal_return, parent_wait_return); + } + else ptrace(PTRACE_SYSCALL, pid, 0, 0); + return(0); +} + +int debugger_normal_return(debugger_state *debugger, pid_t unused) +{ + debugger->handle_trace = debugger_syscall; + syscall_continue(debugger->pid); + return(0); +} + +void debugger_cancelled_return(debugger_state *debugger, int result) +{ + debugger->handle_trace = debugger_syscall; + syscall_set_result(debugger->pid, result); + syscall_continue(debugger->pid); +} + +/* Used by the tracing thread */ +static debugger_state debugger; +static debugee_state debugee; + +void init_proxy (pid_t debugger_pid, int stopped, int status) +{ + debugger.pid = debugger_pid; + debugger.handle_trace = debugger_syscall; + debugger.debugee = &debugee; + debugger.waiting = 0; + debugger.real_wait = 0; + debugger.expecting_child = 0; + + debugee.pid = 0; + debugee.traced = 0; + debugee.stopped = stopped; + debugee.event = 0; + debugee.zombie = 0; + debugee.died = 0; + debugee.wait_status = status; + debugee.in_context = 1; +} + +int debugger_proxy(int status, int pid) +{ + int ret = 0, sig; + + if(WIFSTOPPED(status)){ + sig = WSTOPSIG(status); + if (sig == SIGTRAP) + ret = (*debugger.handle_trace)(&debugger, pid); + + else if(sig == SIGCHLD){ + if(debugger.expecting_child){ + ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); + debugger.expecting_child = 0; + } + else if(debugger.waiting) + real_wait_return(&debugger); + else { + ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); + debugger.real_wait = 1; + } + } + else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); + } + else if(WIFEXITED(status)){ + tracer_panic("debugger (pid %d) exited with status %d", + debugger.pid, WEXITSTATUS(status)); + } + else if(WIFSIGNALED(status)){ + tracer_panic("debugger (pid %d) exited with signal %d", + debugger.pid, WTERMSIG(status)); + } + else { + tracer_panic("proxy got unknown status (0x%x) on debugger " + "(pid %d)", status, debugger.pid); + } + return(ret); +} + +void child_proxy(pid_t pid, int status) +{ + debugee.event = 1; + debugee.wait_status = status; + + if(WIFSTOPPED(status)){ + debugee.stopped = 1; + debugger.expecting_child = 1; + kill(debugger.pid, SIGCHLD); + } + else if(WIFEXITED(status) || WIFSIGNALED(status)){ + debugee.zombie = 1; + debugger.expecting_child = 1; + kill(debugger.pid, SIGCHLD); + } + else panic("proxy got unknown status (0x%x) on child (pid %d)", + status, pid); +} + +void debugger_parent_signal(int status, int pid) +{ + int sig; + + if(WIFSTOPPED(status)){ + sig = WSTOPSIG(status); + if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); + else ptrace(PTRACE_SYSCALL, pid, 0, sig); + } +} + +void fake_child_exit(void) +{ + int status, pid; + + child_proxy(1, W_EXITCODE(0, 0)); + while(debugger.waiting == 1){ + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); + if(pid != debugger.pid){ + printk("fake_child_exit - waitpid failed, " + "errno = %d\n", errno); + return; + } + debugger_proxy(status, debugger.pid); + } + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); + if(pid != debugger.pid){ + printk("fake_child_exit - waitpid failed, " + "errno = %d\n", errno); + return; + } + if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) + printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", + errno); +} + +char gdb_init_string[] = +"att 1 \n\ +b panic \n\ +b stop \n\ +handle SIGWINCH nostop noprint pass \n\ +"; + +int start_debugger(char *prog, int startup, int stop, int *fd_out) +{ + int slave, child; + + slave = open_gdb_chan(); + child = fork(); + if(child == 0){ + char *tempname = NULL; + int fd; + + if(setsid() < 0) perror("setsid"); + if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || + (dup2(slave, 2) < 0)){ + printk("start_debugger : dup2 failed, errno = %d\n", + errno); + exit(1); + } + if(ioctl(0, TIOCSCTTY, 0) < 0){ + printk("start_debugger : TIOCSCTTY failed, " + "errno = %d\n", errno); + exit(1); + } + if(tcsetpgrp (1, os_getpid()) < 0){ + printk("start_debugger : tcsetpgrp failed, " + "errno = %d\n", errno); +#ifdef notdef + exit(1); +#endif + } + fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); + if(fd < 0){ + printk("start_debugger : make_tempfile failed," + "err = %d\n", -fd); + exit(1); + } + os_write_file(fd, gdb_init_string, + sizeof(gdb_init_string) - 1); + if(startup){ + if(stop){ + os_write_file(fd, "b start_kernel\n", + strlen("b start_kernel\n")); + } + os_write_file(fd, "c\n", strlen("c\n")); + } + if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ + printk("start_debugger : PTRACE_TRACEME failed, " + "errno = %d\n", errno); + exit(1); + } + execlp("gdb", "gdb", "--command", tempname, prog, NULL); + printk("start_debugger : exec of gdb failed, errno = %d\n", + errno); + } + if(child < 0){ + printk("start_debugger : fork for gdb failed, errno = %d\n", + errno); + return(-1); + } + *fd_out = slave; + return(child); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/ptproxy.h b/trunk/arch/um/kernel/tt/ptproxy/ptproxy.h new file mode 100644 index 000000000000..5eb0285b1968 --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/ptproxy.h @@ -0,0 +1,61 @@ +/********************************************************************** +ptproxy.h + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. +**********************************************************************/ + +#ifndef __PTPROXY_H +#define __PTPROXY_H + +#include + +typedef struct debugger debugger_state; +typedef struct debugee debugee_state; + +struct debugger +{ + pid_t pid; + int wait_options; + int *wait_status_ptr; + unsigned int waiting : 1; + unsigned int real_wait : 1; + unsigned int expecting_child : 1; + int (*handle_trace) (debugger_state *, pid_t); + + debugee_state *debugee; +}; + +struct debugee +{ + pid_t pid; + int wait_status; + unsigned int died : 1; + unsigned int event : 1; + unsigned int stopped : 1; + unsigned int trace_singlestep : 1; + unsigned int trace_syscall : 1; + unsigned int traced : 1; + unsigned int zombie : 1; + unsigned int in_context : 1; +}; + +extern int debugger_syscall(debugger_state *debugger, pid_t pid); +extern int debugger_normal_return (debugger_state *debugger, pid_t unused); + +extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, + int *strace_out); +extern void debugger_cancelled_return(debugger_state *debugger, int result); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/ptrace.c b/trunk/arch/um/kernel/tt/ptproxy/ptrace.c new file mode 100644 index 000000000000..4b4f6179b212 --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/ptrace.c @@ -0,0 +1,237 @@ +/********************************************************************** +ptrace.c + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. + +Jeff Dike (jdike@karaya.com) : Modified for integration into uml +**********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "ptproxy.h" +#include "debug.h" +#include "kern_util.h" +#include "ptrace_user.h" +#include "tt.h" +#include "os.h" + +long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, + long arg3, long arg4, pid_t child, int *ret) +{ + sigset_t relay; + long result; + int status; + + *ret = 0; + if(debugger->debugee->died) return(-ESRCH); + + switch(arg1){ + case PTRACE_ATTACH: + if(debugger->debugee->traced) return(-EPERM); + + debugger->debugee->pid = arg2; + debugger->debugee->traced = 1; + + if(is_valid_pid(arg2) && (arg2 != child)){ + debugger->debugee->in_context = 0; + kill(arg2, SIGSTOP); + debugger->debugee->event = 1; + debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); + } + else { + debugger->debugee->in_context = 1; + if(debugger->debugee->stopped) + child_proxy(child, W_STOPCODE(SIGSTOP)); + else kill(child, SIGSTOP); + } + + return(0); + + case PTRACE_DETACH: + if(!debugger->debugee->traced) return(-EPERM); + + debugger->debugee->traced = 0; + debugger->debugee->pid = 0; + if(!debugger->debugee->in_context) + kill(child, SIGCONT); + + return(0); + + case PTRACE_CONT: + if(!debugger->debugee->in_context) return(-EPERM); + *ret = PTRACE_CONT; + return(ptrace(PTRACE_CONT, child, arg3, arg4)); + +#ifdef UM_HAVE_GETFPREGS + case PTRACE_GETFPREGS: + { + long regs[FP_FRAME_SIZE]; + int i, result; + + result = ptrace(PTRACE_GETFPREGS, child, 0, regs); + if(result == -1) return(-errno); + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, + regs[i]); + return(result); + } +#endif + +#ifdef UM_HAVE_GETFPXREGS + case PTRACE_GETFPXREGS: + { + long regs[FPX_FRAME_SIZE]; + int i, result; + + result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); + if(result == -1) return(-errno); + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, + regs[i]); + return(result); + } +#endif + +#ifdef UM_HAVE_GETREGS + case PTRACE_GETREGS: + { + long regs[FRAME_SIZE]; + int i, result; + + result = ptrace(PTRACE_GETREGS, child, 0, regs); + if(result == -1) return(-errno); + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + ptrace (PTRACE_POKEDATA, debugger->pid, + arg4 + 4 * i, regs[i]); + return(result); + } + break; +#endif + + case PTRACE_KILL: + result = ptrace(PTRACE_KILL, child, arg3, arg4); + if(result == -1) return(-errno); + + return(result); + + case PTRACE_PEEKDATA: + case PTRACE_PEEKTEXT: + case PTRACE_PEEKUSR: + /* The value being read out could be -1, so we have to + * check errno to see if there's an error, and zero it + * beforehand so we're not faked out by an old error + */ + + errno = 0; + result = ptrace(arg1, child, arg3, 0); + if((result == -1) && (errno != 0)) return(-errno); + + result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); + if(result == -1) return(-errno); + + return(result); + + case PTRACE_POKEDATA: + case PTRACE_POKETEXT: + case PTRACE_POKEUSR: + result = ptrace(arg1, child, arg3, arg4); + if(result == -1) return(-errno); + + if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4); + return(result); + +#ifdef UM_HAVE_SETFPREGS + case PTRACE_SETFPREGS: + { + long regs[FP_FRAME_SIZE]; + int i; + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, + arg4 + 4 * i, 0); + result = ptrace(PTRACE_SETFPREGS, child, 0, regs); + if(result == -1) return(-errno); + + return(result); + } +#endif + +#ifdef UM_HAVE_SETFPXREGS + case PTRACE_SETFPXREGS: + { + long regs[FPX_FRAME_SIZE]; + int i; + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, + arg4 + 4 * i, 0); + result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); + if(result == -1) return(-errno); + + return(result); + } +#endif + +#ifdef UM_HAVE_SETREGS + case PTRACE_SETREGS: + { + long regs[FRAME_SIZE]; + int i; + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) + regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, + arg4 + 4 * i, 0); + result = ptrace(PTRACE_SETREGS, child, 0, regs); + if(result == -1) return(-errno); + + return(result); + } +#endif + + case PTRACE_SINGLESTEP: + if(!debugger->debugee->in_context) return(-EPERM); + sigemptyset(&relay); + sigaddset(&relay, SIGSEGV); + sigaddset(&relay, SIGILL); + sigaddset(&relay, SIGBUS); + result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); + if(result == -1) return(-errno); + + status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, + &relay); + child_proxy(child, status); + return(result); + + case PTRACE_SYSCALL: + if(!debugger->debugee->in_context) return(-EPERM); + result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); + if(result == -1) return(-errno); + + *ret = PTRACE_SYSCALL; + return(result); + + case PTRACE_TRACEME: + default: + return(-EINVAL); + } +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/sysdep.c b/trunk/arch/um/kernel/tt/ptproxy/sysdep.c new file mode 100644 index 000000000000..e0e1ab0588ad --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/sysdep.c @@ -0,0 +1,70 @@ +/********************************************************************** +sysdep.c + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. +**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "ptrace_user.h" +#include "user.h" +#include "os.h" + +int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, + long *arg5) +{ + *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0); + *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0); + *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0); + *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0); + *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0); + return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0)); +} + +void syscall_cancel(pid_t pid, int result) +{ + if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, + __NR_getpid) < 0) || + (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || + (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || + (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || + (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) + printk("ptproxy: couldn't cancel syscall: errno = %d\n", + errno); +} + +void syscall_set_result(pid_t pid, long result) +{ + ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result); +} + +void syscall_continue(pid_t pid) +{ + ptrace(PTRACE_SYSCALL, pid, 0, 0); +} + +int syscall_pause(pid_t pid) +{ + if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ + printk("syscall_change - ptrace failed, errno = %d\n", errno); + return(-1); + } + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/sysdep.h b/trunk/arch/um/kernel/tt/ptproxy/sysdep.h new file mode 100644 index 000000000000..735f488049aa --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/sysdep.h @@ -0,0 +1,25 @@ +/********************************************************************** +sysdep.h + +Copyright (C) 1999 Lars Brinkhoff. +Copyright (C) 2001 Jeff Dike (jdike@karaya.com) +See the file COPYING for licensing terms and conditions. +**********************************************************************/ + +extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, + long *arg4, long *arg5); +extern void syscall_cancel (pid_t pid, long result); +extern void syscall_set_result (pid_t pid, long result); +extern void syscall_continue (pid_t pid); +extern int syscall_pause(pid_t pid); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/wait.c b/trunk/arch/um/kernel/tt/ptproxy/wait.c new file mode 100644 index 000000000000..bdd4af4b65fc --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/wait.c @@ -0,0 +1,85 @@ +/********************************************************************** +wait.c + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. + +**********************************************************************/ + +#include +#include +#include + +#include "ptproxy.h" +#include "sysdep.h" +#include "wait.h" +#include "ptrace_user.h" +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" + +int proxy_wait_return(struct debugger *debugger, pid_t unused) +{ + debugger->waiting = 0; + + if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ + debugger_cancelled_return(debugger, -ECHILD); + return(0); + } + + if(debugger->debugee->zombie && debugger->debugee->event) + debugger->debugee->died = 1; + + if(debugger->debugee->event){ + debugger->debugee->event = 0; + ptrace(PTRACE_POKEDATA, debugger->pid, + debugger->wait_status_ptr, + debugger->debugee->wait_status); + /* if (wait4) + ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ + debugger_cancelled_return(debugger, debugger->debugee->pid); + return(0); + } + + /* pause will return -EINTR, which happens to be right for wait */ + debugger_normal_return(debugger, -1); + return(0); +} + +int parent_wait_return(struct debugger *debugger, pid_t unused) +{ + return(debugger_normal_return(debugger, -1)); +} + +int real_wait_return(struct debugger *debugger) +{ + unsigned long ip; + int pid; + + pid = debugger->pid; + + ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0); + IP_RESTART_SYSCALL(ip); + + if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0) + tracer_panic("real_wait_return : Failed to restart system " + "call, errno = %d\n", errno); + + if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || + (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || + (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || + debugger_normal_return(debugger, -1)) + tracer_panic("real_wait_return : gdb failed to wait, " + "errno = %d\n", errno); + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/ptproxy/wait.h b/trunk/arch/um/kernel/tt/ptproxy/wait.h new file mode 100644 index 000000000000..542e73ee2cee --- /dev/null +++ b/trunk/arch/um/kernel/tt/ptproxy/wait.h @@ -0,0 +1,15 @@ +/********************************************************************** +wait.h + +Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing +terms and conditions. +**********************************************************************/ + +#ifndef __PTPROXY_WAIT_H +#define __PTPROXY_WAIT_H + +extern int proxy_wait_return(struct debugger *debugger, pid_t unused); +extern int real_wait_return(struct debugger *debugger); +extern int parent_wait_return(struct debugger *debugger, pid_t unused); + +#endif diff --git a/trunk/arch/um/kernel/tt/syscall_kern.c b/trunk/arch/um/kernel/tt/syscall_kern.c new file mode 100644 index 000000000000..293caa6d0c2d --- /dev/null +++ b/trunk/arch/um/kernel/tt/syscall_kern.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/types.h" +#include "linux/utime.h" +#include "linux/sys.h" +#include "linux/ptrace.h" +#include "asm/unistd.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "asm/stat.h" +#include "sysdep/syscalls.h" +#include "sysdep/sigcontext.h" +#include "kern_util.h" +#include "syscall.h" + +void syscall_handler_tt(int sig, struct pt_regs *regs) +{ + void *sc; + long result; + int syscall; + + sc = UPT_SC(®s->regs); + SC_START_SYSCALL(sc); + + syscall = UPT_SYSCALL_NR(®s->regs); + syscall_trace(®s->regs, 0); + + current->thread.nsyscalls++; + nsyscalls++; + + if((syscall >= NR_syscalls) || (syscall < 0)) + result = -ENOSYS; + else result = EXECUTE_SYSCALL(syscall, regs); + + /* regs->sc may have changed while the system call ran (there may + * have been an interrupt or segfault), so it needs to be refreshed. + */ + UPT_SC(®s->regs) = sc; + + SC_SET_SYSCALL_RETURN(sc, result); + + syscall_trace(®s->regs, 1); +} diff --git a/trunk/arch/um/kernel/tt/syscall_user.c b/trunk/arch/um/kernel/tt/syscall_user.c new file mode 100644 index 000000000000..f52b47aff1d2 --- /dev/null +++ b/trunk/arch/um/kernel/tt/syscall_user.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include "sysdep/ptrace.h" +#include "sigcontext.h" +#include "ptrace_user.h" +#include "task.h" +#include "kern_util.h" +#include "syscall.h" +#include "tt.h" + +void do_sigtrap(void *task) +{ + UPT_SYSCALL_NR(TASK_REGS(task)) = -1; +} + +void do_syscall(void *task, int pid, int local_using_sysemu) +{ + unsigned long proc_regs[FRAME_SIZE]; + + if(ptrace_getregs(pid, proc_regs) < 0) + tracer_panic("Couldn't read registers"); + + UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); + +#ifdef UPT_ORIGGPR2 + UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs); +#endif + + if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && + ((unsigned long *) PT_IP(proc_regs) <= &_etext)) + tracer_panic("I'm tracing myself and I can't get out"); + + /* advanced sysemu mode set syscall number to -1 automatically */ + if (local_using_sysemu==2) + return; + + /* syscall number -1 in sysemu skips syscall restarting in host */ + if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, + local_using_sysemu ? -1 : __NR_getpid) < 0) + tracer_panic("do_syscall : Nullifying syscall failed, " + "errno = %d", errno); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/tlb.c b/trunk/arch/um/kernel/tt/tlb.c new file mode 100644 index 000000000000..7caa24fe05df --- /dev/null +++ b/trunk/arch/um/kernel/tt/tlb.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/kernel.h" +#include "linux/sched.h" +#include "linux/mm.h" +#include "asm/page.h" +#include "asm/pgtable.h" +#include "asm/uaccess.h" +#include "asm/tlbflush.h" +#include "mem_user.h" +#include "os.h" +#include "tlb.h" + +static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, + int finished, void **flush) +{ + struct host_vm_op *op; + int i, ret=0; + + for(i = 0; i <= last && !ret; i++){ + op = &ops[i]; + switch(op->type){ + case MMAP: + ret = os_map_memory((void *) op->u.mmap.addr, + op->u.mmap.fd, op->u.mmap.offset, + op->u.mmap.len, op->u.mmap.r, + op->u.mmap.w, op->u.mmap.x); + break; + case MUNMAP: + ret = os_unmap_memory((void *) op->u.munmap.addr, + op->u.munmap.len); + break; + case MPROTECT: + ret = protect_memory(op->u.mprotect.addr, + op->u.munmap.len, + op->u.mprotect.r, + op->u.mprotect.w, + op->u.mprotect.x, 1); + protect_memory(op->u.mprotect.addr, op->u.munmap.len, + op->u.mprotect.r, op->u.mprotect.w, + op->u.mprotect.x, 1); + break; + default: + printk("Unknown op type %d in do_ops\n", op->type); + break; + } + } + + return ret; +} + +static void fix_range(struct mm_struct *mm, unsigned long start_addr, + unsigned long end_addr, int force) +{ + if((current->thread.mode.tt.extern_pid != -1) && + (current->thread.mode.tt.extern_pid != os_getpid())) + panic("fix_range fixing wrong address space, current = 0x%p", + current); + + fix_range_common(mm, start_addr, end_addr, force, do_ops); +} + +atomic_t vmchange_seq = ATOMIC_INIT(1); + +void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end) +{ + if(flush_tlb_kernel_range_common(start, end)) + atomic_inc(&vmchange_seq); +} + +void flush_tlb_kernel_vm_tt(void) +{ + flush_tlb_kernel_range(start_vm, end_vm); +} + +void __flush_tlb_one_tt(unsigned long addr) +{ + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); +} + +void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + if(vma->vm_mm != current->mm) return; + + /* Assumes that the range start ... end is entirely within + * either process memory or kernel vm + */ + if((start >= start_vm) && (start < end_vm)){ + if(flush_tlb_kernel_range_common(start, end)) + atomic_inc(&vmchange_seq); + } + else fix_range(vma->vm_mm, start, end, 0); +} + +void flush_tlb_mm_tt(struct mm_struct *mm) +{ + unsigned long seq; + + if(mm != current->mm) return; + + fix_range(mm, 0, STACK_TOP, 0); + + seq = atomic_read(&vmchange_seq); + if(current->thread.mode.tt.vm_seq == seq) + return; + current->thread.mode.tt.vm_seq = seq; + flush_tlb_kernel_range_common(start_vm, end_vm); +} + +void force_flush_all_tt(void) +{ + fix_range(current->mm, 0, STACK_TOP, 1); + flush_tlb_kernel_range_common(start_vm, end_vm); +} diff --git a/trunk/arch/um/kernel/tt/tracer.c b/trunk/arch/um/kernel/tt/tracer.c new file mode 100644 index 000000000000..c23588393f6e --- /dev/null +++ b/trunk/arch/um/kernel/tt/tracer.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user.h" +#include "sysdep/ptrace.h" +#include "sigcontext.h" +#include "sysdep/sigcontext.h" +#include "os.h" +#include "mem_user.h" +#include "process.h" +#include "kern_util.h" +#include "chan_user.h" +#include "ptrace_user.h" +#include "irq_user.h" +#include "mode.h" +#include "tt.h" + +static int tracer_winch[2]; + +int is_tracer_winch(int pid, int fd, void *data) +{ + if(pid != os_getpgrp()) + return(0); + + register_winch_irq(tracer_winch[0], fd, -1, data); + return(1); +} + +static void tracer_winch_handler(int sig) +{ + int n; + char c = 1; + + n = os_write_file(tracer_winch[1], &c, sizeof(c)); + if(n != sizeof(c)) + printk("tracer_winch_handler - write failed, err = %d\n", -n); +} + +/* Called only by the tracing thread during initialization */ + +static void setup_tracer_winch(void) +{ + int err; + + err = os_pipe(tracer_winch, 1, 1); + if(err < 0){ + printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); + return; + } + signal(SIGWINCH, tracer_winch_handler); +} + +void attach_process(int pid) +{ + if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || + (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) + tracer_panic("OP_FORK failed to attach pid"); + wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); + if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) + tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); + if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) + tracer_panic("OP_FORK failed to continue process"); +} + +void tracer_panic(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + printf("\n"); + while(1) pause(); +} + +static void tracer_segv(int sig, struct sigcontext sc) +{ + struct faultinfo fi; + GET_FAULTINFO_FROM_SC(fi, &sc); + printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", + FAULT_ADDRESS(fi), SC_IP(&sc)); + while(1) + pause(); +} + +/* Changed early in boot, and then only read */ +int debug = 0; +int debug_stop = 1; +int debug_parent = 0; +int honeypot = 0; + +static int signal_tramp(void *arg) +{ + int (*proc)(void *); + + if(honeypot && munmap((void *) (host_task_size - 0x10000000), + 0x10000000)) + panic("Unmapping stack failed"); + if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) + panic("ptrace PTRACE_TRACEME failed"); + os_stop_process(os_getpid()); + change_sig(SIGWINCH, 0); + signal(SIGUSR1, SIG_IGN); + change_sig(SIGCHLD, 0); + signal(SIGSEGV, (__sighandler_t) sig_handler); + set_cmdline("(idle thread)"); + set_init_pid(os_getpid()); + init_irq_signals(0); + proc = arg; + return((*proc)(NULL)); +} + +static void sleeping_process_signal(int pid, int sig) +{ + switch(sig){ + /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is + * right because the process must be in the kernel already. + */ + case SIGCONT: + case SIGTSTP: + if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) + tracer_panic("sleeping_process_signal : Failed to " + "continue pid %d, signal = %d, " + "errno = %d\n", pid, sig, errno); + break; + + /* This happens when the debugger (e.g. strace) is doing system call + * tracing on the kernel. During a context switch, the current task + * will be set to the incoming process and the outgoing process will + * hop into write and then read. Since it's not the current process + * any more, the trace of those will land here. So, we need to just + * PTRACE_SYSCALL it. + */ + case (SIGTRAP + 0x80): + if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) + tracer_panic("sleeping_process_signal : Failed to " + "PTRACE_SYSCALL pid %d, errno = %d\n", + pid, errno); + break; + case SIGSTOP: + break; + default: + tracer_panic("sleeping process %d got unexpected " + "signal : %d\n", pid, sig); + break; + } +} + +/* Accessed only by the tracing thread */ +int debugger_pid = -1; +int debugger_parent = -1; +int debugger_fd = -1; +int gdb_pid = -1; + +struct { + int pid; + int signal; + unsigned long addr; + struct timeval time; +} signal_record[1024][32]; + +int signal_index[32]; +int nsignals = 0; +int debug_trace = 0; + +extern void signal_usr1(int sig); + +int tracing_pid = -1; + +int tracer(int (*init_proc)(void *), void *sp) +{ + void *task = NULL; + int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; + int proc_id = 0, n, err, old_tracing = 0, strace = 0; + int local_using_sysemu = 0; + + signal(SIGPIPE, SIG_IGN); + setup_tracer_winch(); + tracing_pid = os_getpid(); + printf("tracing thread pid = %d\n", tracing_pid); + + pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + if(n < 0){ + printf("waitpid on idle thread failed, errno = %d\n", errno); + exit(1); + } + if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { + printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); + exit(1); + } + if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ + printf("Failed to continue idle thread, errno = %d\n", errno); + exit(1); + } + + signal(SIGSEGV, (sighandler_t) tracer_segv); + signal(SIGUSR1, signal_usr1); + if(debug_trace){ + printf("Tracing thread pausing to be attached\n"); + stop(); + } + if(debug){ + if(gdb_pid != -1) + debugger_pid = attach_debugger(pid, gdb_pid, 1); + else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); + if(debug_parent){ + debugger_parent = os_process_parent(debugger_pid); + init_parent_proxy(debugger_parent); + err = attach(debugger_parent); + if(err){ + printf("Failed to attach debugger parent %d, " + "errno = %d\n", debugger_parent, -err); + debugger_parent = -1; + } + else { + if(ptrace(PTRACE_SYSCALL, debugger_parent, + 0, 0) < 0){ + printf("Failed to continue debugger " + "parent, errno = %d\n", errno); + debugger_parent = -1; + } + } + } + } + set_cmdline("(tracing thread)"); + while(1){ + CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); + if(pid <= 0){ + if(errno != ECHILD){ + printf("wait failed - errno = %d\n", errno); + } + continue; + } + if(pid == debugger_pid){ + int cont = 0; + + if(WIFEXITED(status) || WIFSIGNALED(status)) + debugger_pid = -1; + /* XXX Figure out how to deal with gdb and SMP */ + else cont = debugger_signal(status, cpu_tasks[0].pid); + if(cont == PTRACE_SYSCALL) strace = 1; + continue; + } + else if(pid == debugger_parent){ + debugger_parent_signal(status, pid); + continue; + } + nsignals++; + if(WIFEXITED(status)) ; +#ifdef notdef + { + printf("Child %d exited with status %d\n", pid, + WEXITSTATUS(status)); + } +#endif + else if(WIFSIGNALED(status)){ + sig = WTERMSIG(status); + if(sig != 9){ + printf("Child %d exited with signal %d\n", pid, + sig); + } + } + else if(WIFSTOPPED(status)){ + proc_id = pid_to_processor_id(pid); + sig = WSTOPSIG(status); + if(proc_id == -1){ + sleeping_process_signal(pid, sig); + continue; + } + + task = cpu_tasks[proc_id].task; + tracing = is_tracing(task); + old_tracing = tracing; + + /* Assume: no syscall, when coming from user */ + if ( tracing ) + do_sigtrap(task); + + switch(sig){ + case SIGUSR1: + sig = 0; + op = do_proc_op(task, proc_id); + switch(op){ + /* + * This is called when entering user mode; after + * this, we start intercepting syscalls. + * + * In fact, a process is started in kernel mode, + * so with is_tracing() == 0 (and that is reset + * when executing syscalls, since UML kernel has + * the right to do syscalls); + */ + case OP_TRACE_ON: + arch_leave_kernel(task, pid); + tracing = 1; + break; + case OP_REBOOT: + case OP_HALT: + unmap_physmem(); + kmalloc_ok = 0; + os_kill_ptraced_process(pid, 0); + /* Now let's reap remaining zombies */ + errno = 0; + do { + waitpid(-1, &status, + WUNTRACED); + } while (errno != ECHILD); + return(op == OP_REBOOT); + case OP_NONE: + printf("Detaching pid %d\n", pid); + detach(pid, SIGSTOP); + continue; + default: + break; + } + /* OP_EXEC switches host processes on us, + * we want to continue the new one. + */ + pid = cpu_tasks[proc_id].pid; + break; + case (SIGTRAP + 0x80): + if(!tracing && (debugger_pid != -1)){ + child_signal(pid, status & 0x7fff); + continue; + } + tracing = 0; + /* local_using_sysemu has been already set + * below, since if we are here, is_tracing() on + * the traced task was 1, i.e. the process had + * already run through one iteration of the + * loop which executed a OP_TRACE_ON request.*/ + do_syscall(task, pid, local_using_sysemu); + sig = SIGUSR2; + break; + case SIGTRAP: + if(!tracing && (debugger_pid != -1)){ + child_signal(pid, status); + continue; + } + tracing = 0; + break; + case SIGPROF: + if(tracing) sig = 0; + break; + case SIGCHLD: + case SIGHUP: + sig = 0; + break; + case SIGSEGV: + case SIGIO: + case SIGALRM: + case SIGVTALRM: + case SIGFPE: + case SIGBUS: + case SIGILL: + case SIGWINCH: + + default: + tracing = 0; + break; + } + set_tracing(task, tracing); + + if(!tracing && old_tracing) + arch_enter_kernel(task, pid); + + if(!tracing && (debugger_pid != -1) && (sig != 0) && + (sig != SIGALRM) && (sig != SIGVTALRM) && + (sig != SIGSEGV) && (sig != SIGTRAP) && + (sig != SIGUSR2) && (sig != SIGIO) && + (sig != SIGFPE)){ + child_signal(pid, status); + continue; + } + + local_using_sysemu = get_using_sysemu(); + + if(tracing) + cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu, + singlestepping(task)); + else if((debugger_pid != -1) && strace) + cont_type = PTRACE_SYSCALL; + else + cont_type = PTRACE_CONT; + + if(ptrace(cont_type, pid, 0, sig) != 0){ + tracer_panic("ptrace failed to continue " + "process - errno = %d\n", + errno); + } + } + } + return(0); +} + +static int __init uml_debug_setup(char *line, int *add) +{ + char *next; + + debug = 1; + *add = 0; + if(*line != '=') return(0); + line++; + + while(line != NULL){ + next = strchr(line, ','); + if(next) *next++ = '\0'; + + if(!strcmp(line, "go")) debug_stop = 0; + else if(!strcmp(line, "parent")) debug_parent = 1; + else printf("Unknown debug option : '%s'\n", line); + + line = next; + } + return(0); +} + +__uml_setup("debug", uml_debug_setup, +"debug\n" +" Starts up the kernel under the control of gdb. See the \n" +" kernel debugging tutorial and the debugging session pages\n" +" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" +); + +static int __init uml_debugtrace_setup(char *line, int *add) +{ + debug_trace = 1; + return 0; +} +__uml_setup("debugtrace", uml_debugtrace_setup, +"debugtrace\n" +" Causes the tracing thread to pause until it is attached by a\n" +" debugger and continued. This is mostly for debugging crashes\n" +" early during boot, and should be pretty much obsoleted by\n" +" the debug switch.\n\n" +); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/trap_user.c b/trunk/arch/um/kernel/tt/trap_user.c new file mode 100644 index 000000000000..3032eb5e2467 --- /dev/null +++ b/trunk/arch/um/kernel/tt/trap_user.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" +#include "kern_util.h" +#include "task.h" +#include "tt.h" +#include "os.h" + +void sig_handler_common_tt(int sig, void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + struct tt_regs save_regs, *r; + int save_errno = errno, is_user = 0; + void (*handler)(int, union uml_pt_regs *); + + /* This is done because to allow SIGSEGV to be delivered inside a SEGV + * handler. This can happen in copy_user, and if SEGV is disabled, + * the process will die. + */ + if(sig == SIGSEGV) + change_sig(SIGSEGV, 1); + + r = &TASK_REGS(get_current())->tt; + if ( sig == SIGFPE || sig == SIGSEGV || + sig == SIGBUS || sig == SIGILL || + sig == SIGTRAP ) { + GET_FAULTINFO_FROM_SC(r->faultinfo, sc); + } + save_regs = *r; + if (sc) + is_user = user_context(SC_SP(sc)); + r->sc = sc; + if(sig != SIGUSR2) + r->syscall = -1; + + handler = sig_info[sig]; + + /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ + if (sig != SIGIO && sig != SIGWINCH && + sig != SIGVTALRM && sig != SIGALRM) + unblock_signals(); + + handler(sig, (union uml_pt_regs *) r); + + if(is_user){ + interrupt_end(); + block_signals(); + set_user_mode(NULL); + } + *r = save_regs; + errno = save_errno; +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/uaccess.c b/trunk/arch/um/kernel/tt/uaccess.c new file mode 100644 index 000000000000..1cb60726567e --- /dev/null +++ b/trunk/arch/um/kernel/tt/uaccess.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "asm/uaccess.h" + +int copy_from_user_tt(void *to, const void __user *from, int n) +{ + if(!access_ok(VERIFY_READ, from, n)) + return(n); + + return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int copy_to_user_tt(void __user *to, const void *from, int n) +{ + if(!access_ok(VERIFY_WRITE, to, n)) + return(n); + + return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int strncpy_from_user_tt(char *dst, const char __user *src, int count) +{ + int n; + + if(!access_ok(VERIFY_READ, src, 1)) + return(-EFAULT); + + n = __do_strncpy_from_user(dst, src, count, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher); + if(n < 0) return(-EFAULT); + return(n); +} + +int __clear_user_tt(void __user *mem, int len) +{ + return(__do_clear_user(mem, len, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int clear_user_tt(void __user *mem, int len) +{ + if(!access_ok(VERIFY_WRITE, mem, len)) + return(len); + + return(__do_clear_user(mem, len, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int strnlen_user_tt(const void __user *str, int len) +{ + return(__do_strnlen_user(str, len, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/uaccess_user.c b/trunk/arch/um/kernel/tt/uaccess_user.c new file mode 100644 index 000000000000..0e5c82c5e5b7 --- /dev/null +++ b/trunk/arch/um/kernel/tt/uaccess_user.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include "uml_uaccess.h" +#include "task.h" +#include "kern_util.h" +#include "os.h" +#include "longjmp.h" + +int __do_copy_from_user(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher) +{ + struct tt_regs save = TASK_REGS(get_current())->tt; + unsigned long fault; + int faulted; + + fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, + __do_copy, &faulted); + TASK_REGS(get_current())->tt = save; + + if(!faulted) + return 0; + else if (fault) + return n - (fault - (unsigned long) from); + else + /* In case of a general protection fault, we don't have the + * fault address, so NULL is used instead. Pretend we didn't + * copy anything. */ + return n; +} + +static void __do_strncpy(void *dst, const void *src, int count) +{ + strncpy(dst, src, count); +} + +int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, + void **fault_addr, void **fault_catcher) +{ + struct tt_regs save = TASK_REGS(get_current())->tt; + unsigned long fault; + int faulted; + + fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, + __do_strncpy, &faulted); + TASK_REGS(get_current())->tt = save; + + if(!faulted) return(strlen(dst)); + else return(-1); +} + +static void __do_clear(void *to, const void *from, int n) +{ + memset(to, 0, n); +} + +int __do_clear_user(void *mem, unsigned long len, + void **fault_addr, void **fault_catcher) +{ + struct tt_regs save = TASK_REGS(get_current())->tt; + unsigned long fault; + int faulted; + + fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, + __do_clear, &faulted); + TASK_REGS(get_current())->tt = save; + + if(!faulted) return(0); + else return(len - (fault - (unsigned long) mem)); +} + +int __do_strnlen_user(const char *str, unsigned long n, + void **fault_addr, void **fault_catcher) +{ + struct tt_regs save = TASK_REGS(get_current())->tt; + int ret; + unsigned long *faddrp = (unsigned long *)fault_addr; + jmp_buf jbuf; + + *fault_catcher = &jbuf; + if(UML_SETJMP(&jbuf) == 0) + ret = strlen(str) + 1; + else ret = *faddrp - (unsigned long) str; + + *fault_addr = NULL; + *fault_catcher = NULL; + + TASK_REGS(get_current())->tt = save; + return ret; +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/uaccess.c b/trunk/arch/um/kernel/uaccess.c index d7436aacd26f..054e3de0784e 100644 --- a/trunk/arch/um/kernel/uaccess.c +++ b/trunk/arch/um/kernel/uaccess.c @@ -18,7 +18,7 @@ void __do_copy(void *to, const void *from, int n) int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher) + void **fault_addr, void **fault_catcher) { unsigned long fault; int faulted; diff --git a/trunk/arch/um/kernel/um_arch.c b/trunk/arch/um/kernel/um_arch.c index f1c71393f578..ecc458fe51b9 100644 --- a/trunk/arch/um/kernel/um_arch.c +++ b/trunk/arch/um/kernel/um_arch.c @@ -1,24 +1,46 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/delay.h" +#include "linux/kernel.h" +#include "linux/sched.h" +#include "linux/notifier.h" #include "linux/mm.h" -#include "linux/module.h" +#include "linux/types.h" +#include "linux/tty.h" +#include "linux/init.h" +#include "linux/bootmem.h" +#include "linux/spinlock.h" +#include "linux/utsname.h" +#include "linux/sysrq.h" #include "linux/seq_file.h" -#include "linux/string.h" +#include "linux/delay.h" +#include "linux/module.h" #include "linux/utsname.h" +#include "asm/page.h" #include "asm/pgtable.h" -#include "asm/processor.h" +#include "asm/ptrace.h" +#include "asm/elf.h" +#include "asm/user.h" #include "asm/setup.h" -#include "arch.h" +#include "ubd_user.h" +#include "asm/current.h" +#include "kern_util.h" #include "as-layout.h" -#include "init.h" +#include "arch.h" #include "kern.h" #include "mem_user.h" +#include "mem.h" +#include "initrd.h" +#include "init.h" #include "os.h" +#include "choose-mode.h" +#include "mode_kern.h" +#include "mode.h" +#ifdef UML_CONFIG_MODE_SKAS #include "skas.h" +#endif #define DEFAULT_COMMAND_LINE "root=98:0" @@ -31,7 +53,7 @@ static void __init add_arg(char *arg) printf("add_arg: Too many command line arguments!\n"); exit(1); } - if (strlen(command_line) > 0) + if(strlen(command_line) > 0) strcat(command_line, " "); strcat(command_line, arg); } @@ -48,8 +70,8 @@ struct cpuinfo_um boot_cpu_data = { unsigned long thread_saved_pc(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ - return os_process_pc(userspace_pid[0]); + return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, + task)); } /* Changed in setup_arch, which is called in early boot */ @@ -68,7 +90,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t: %d\n", index); seq_printf(m, "vendor_id\t: User Mode Linux\n"); seq_printf(m, "model name\t: UML\n"); - seq_printf(m, "mode\t\t: skas\n"); + seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); seq_printf(m, "host\t\t: %s\n", host_info); seq_printf(m, "bogomips\t: %lu.%02lu\n\n", loops_per_jiffy/(500000/HZ), @@ -110,13 +132,44 @@ unsigned long end_vm; /* Set in uml_ncpus_setup */ int ncpus = 1; +#ifdef CONFIG_CMDLINE_ON_HOST +/* Pointer set in linux_main, the array itself is private to each thread, + * and changed at address space creation time so this poses no concurrency + * problems. + */ +static char *argv1_begin = NULL; +static char *argv1_end = NULL; +#endif + /* Set in early boot */ static int have_root __initdata = 0; /* Set in uml_mem_setup and modified in linux_main */ long long physmem_size = 32 * 1024 * 1024; -static char *usage_string = +void set_cmdline(char *cmd) +{ +#ifdef CONFIG_CMDLINE_ON_HOST + char *umid, *ptr; + + if(CHOOSE_MODE(honeypot, 0)) return; + + umid = get_umid(); + if(*umid != '\0'){ + snprintf(argv1_begin, + (argv1_end - argv1_begin) * sizeof(*ptr), + "(%s) ", umid); + ptr = &argv1_begin[strlen(argv1_begin)]; + } + else ptr = argv1_begin; + + snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); + memset(argv1_begin + strlen(argv1_begin), '\0', + argv1_end - argv1_begin - strlen(argv1_begin)); +#endif +} + +static char *usage_string = "User Mode Linux v%s\n" " available at http://user-mode-linux.sourceforge.net/\n\n"; @@ -148,10 +201,13 @@ __uml_setup("root=", uml_root_setup, " root=/dev/ubd5\n\n" ); +#ifndef CONFIG_MODE_TT + static int __init no_skas_debug_setup(char *line, int *add) { printf("'debug' is not necessary to gdb UML in skas mode - run \n"); - printf("'gdb linux'"); + printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); + printf("doesn't work as expected\n"); return 0; } @@ -161,6 +217,8 @@ __uml_setup("debug", no_skas_debug_setup, " this flag is not needed to run gdb on UML in skas mode\n\n" ); +#endif + #ifdef CONFIG_SMP static int __init uml_ncpus_setup(char *line, int *add) { @@ -174,10 +232,56 @@ static int __init uml_ncpus_setup(char *line, int *add) __uml_setup("ncpus=", uml_ncpus_setup, "ncpus=<# of desired CPUs>\n" -" This tells an SMP kernel how many virtual processors to start.\n\n" +" This tells an SMP kernel how many virtual processors to start.\n\n" ); #endif +static int force_tt = 0; + +#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) +#define DEFAULT_TT 0 + +static int __init mode_tt_setup(char *line, int *add) +{ + force_tt = 1; + return 0; +} + +#else +#ifdef CONFIG_MODE_SKAS + +#define DEFAULT_TT 0 + +static int __init mode_tt_setup(char *line, int *add) +{ + printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); + return 0; +} + +#else +#ifdef CONFIG_MODE_TT + +#define DEFAULT_TT 1 + +static int __init mode_tt_setup(char *line, int *add) +{ + printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); + return 0; +} + +#endif +#endif +#endif + +__uml_setup("mode=tt", mode_tt_setup, +"mode=tt\n" +" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" +" forces UML to run in tt (tracing thread) mode. It is not the default\n" +" because it's slower and less secure than skas mode.\n\n" +); + +int mode_tt = DEFAULT_TT; + static int __init Usage(char *line, int *add) { const char **p; @@ -206,8 +310,9 @@ static int __init uml_checksetup(char *line, int *add) int n; n = strlen(p->str); - if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) - return 1; + if(!strncmp(line, p->str, n)){ + if (p->setup_func(line + n, add)) return 1; + } p++; } return 0; @@ -218,7 +323,7 @@ static void __init uml_postsetup(void) initcall_t *p; p = &__uml_postsetup_start; - while(p < &__uml_postsetup_end) { + while(p < &__uml_postsetup_end){ (*p)(); p++; } @@ -234,20 +339,6 @@ EXPORT_SYMBOL(end_iomem); extern char __binary_start; -static unsigned long set_task_sizes_skas(unsigned long *task_size_out) -{ - /* Round up to the nearest 4M */ - unsigned long host_task_size = ROUND_4M((unsigned long) - &host_task_size); - - if (!skas_needs_stub) - *task_size_out = host_task_size; - else - *task_size_out = STUB_START & PGDIR_MASK; - - return host_task_size; -} - int __init linux_main(int argc, char **argv) { unsigned long avail, diff; @@ -255,30 +346,45 @@ int __init linux_main(int argc, char **argv) unsigned int i, add; char * mode; - for (i = 1; i < argc; i++) { - if ((i == 1) && (argv[i][0] == ' ')) - continue; + for (i = 1; i < argc; i++){ + if((i == 1) && (argv[i][0] == ' ')) continue; add = 1; uml_checksetup(argv[i], &add); if (add) add_arg(argv[i]); } - if (have_root == 0) + if(have_root == 0) add_arg(DEFAULT_COMMAND_LINE); - /* OS sanity checks that need to happen before the kernel runs */ os_early_checks(); + if (force_tt) + clear_can_do_skas(); + mode_tt = force_tt ? 1 : !can_do_skas(); +#ifndef CONFIG_MODE_TT + if (mode_tt) { + /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, + * can_do_skas() returned 0, and the message is correct. */ + printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); + exit(1); + } +#endif - can_do_skas(); - - if (proc_mm && ptrace_faultinfo) +#ifndef CONFIG_MODE_SKAS + mode = "TT"; +#else + /* Show to the user the result of selection */ + if (mode_tt) + mode = "TT"; + else if (proc_mm && ptrace_faultinfo) mode = "SKAS3"; else mode = "SKAS0"; +#endif printf("UML running in %s mode\n", mode); - host_task_size = set_task_sizes_skas(&task_size); + host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, + set_task_sizes_skas, &task_size); /* * Setting up handlers to 'sig_info' struct @@ -286,15 +392,13 @@ int __init linux_main(int argc, char **argv) os_fill_handlinfo(handlinfo_kern); brk_start = (unsigned long) sbrk(0); - - /* - * Increase physical memory size for exec-shield users - * so they actually get what they asked for. This should - * add zero for non-exec shield users - */ + CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); + /* Increase physical memory size for exec-shield users + so they actually get what they asked for. This should + add zero for non-exec shield users */ diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); - if (diff > 1024 * 1024) { + if(diff > 1024 * 1024){ printf("Adding %ld bytes to physical memory to account for " "exec-shield gap\n", diff); physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); @@ -307,16 +411,20 @@ int __init linux_main(int argc, char **argv) setup_machinename(init_utsname()->machine); +#ifdef CONFIG_CMDLINE_ON_HOST + argv1_begin = argv[1]; + argv1_end = &argv[1][strlen(argv[1])]; +#endif + highmem = 0; iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; - /* - * Zones have to begin on a 1 << MAX_ORDER page boundary, + /* Zones have to begin on a 1 << MAX_ORDER page boundary, * so this makes sure that's true for highmem */ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); - if (physmem_size + iomem_size > max_physmem) { + if(physmem_size + iomem_size > max_physmem){ highmem = physmem_size + iomem_size - max_physmem; physmem_size -= highmem; #ifndef CONFIG_HIGHMEM @@ -333,7 +441,7 @@ int __init linux_main(int argc, char **argv) start_vm = VMALLOC_START; setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); - if (init_maps(physmem_size, iomem_size, highmem)) { + if(init_maps(physmem_size, iomem_size, highmem)){ printf("Failed to allocate mem_map for %Lu bytes of physical " "memory and %Lu bytes of highmem\n", physmem_size, highmem); @@ -342,11 +450,10 @@ int __init linux_main(int argc, char **argv) virtmem_size = physmem_size; avail = get_kmem_end() - start_vm; - if (physmem_size > avail) - virtmem_size = avail; + if(physmem_size > avail) virtmem_size = avail; end_vm = start_vm + virtmem_size; - if (virtmem_size < physmem_size) + if(virtmem_size < physmem_size) printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); @@ -355,7 +462,7 @@ int __init linux_main(int argc, char **argv) stack_protections((unsigned long) &init_thread_info); os_flush_stdout(); - return start_uml(); + return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); } extern int uml_exitcode; diff --git a/trunk/arch/um/kernel/uml.lds.S b/trunk/arch/um/kernel/uml.lds.S index 13df191e2b41..81acdc24348e 100644 --- a/trunk/arch/um/kernel/uml.lds.S +++ b/trunk/arch/um/kernel/uml.lds.S @@ -18,6 +18,13 @@ SECTIONS . = START + SIZEOF_HEADERS; +#ifdef MODE_TT + .remap_data : { UNMAP_PATH (.data .bss) } + .remap : { UNMAP_PATH (.text) } + + . = ALIGN(4096); /* Init code and data */ +#endif + _text = .; _stext = .; __init_begin = .; diff --git a/trunk/arch/um/os-Linux/Makefile b/trunk/arch/um/os-Linux/Makefile index 8e129af8170d..2f8c79464015 100644 --- a/trunk/arch/um/os-Linux/Makefile +++ b/trunk/arch/um/os-Linux/Makefile @@ -1,18 +1,23 @@ # -# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ - registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ - umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ + sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ + user_syms.o util.o drivers/ sys-$(SUBARCH)/ + +obj-$(CONFIG_MODE_SKAS) += skas/ + +obj-$(CONFIG_MODE_TT) += tt.o +user-objs-$(CONFIG_MODE_TT) += tt.o obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ - main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ - trap.o tty.o tls.o uaccess.o umid.o util.o + main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ + tls.o uaccess.o umid.o util.o CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/trunk/arch/um/os-Linux/aio.c b/trunk/arch/um/os-Linux/aio.c index 4158118c4a56..59348359f9ab 100644 --- a/trunk/arch/um/os-Linux/aio.c +++ b/trunk/arch/um/os-Linux/aio.c @@ -1,19 +1,20 @@ /* - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ +#include #include -#include #include #include -#include -#include +#include +#include +#include "os.h" #include "aio.h" #include "init.h" -#include "kern_constants.h" -#include "os.h" #include "user.h" +#include "mode.h" +#include "kern_constants.h" struct aio_thread_req { enum aio_type type; @@ -27,8 +28,7 @@ struct aio_thread_req { #if defined(HAVE_AIO_ABI) #include -/* - * If we have the headers, we are going to build with AIO enabled. +/* If we have the headers, we are going to build with AIO enabled. * If we don't have aio in libc, we define the necessary stubs here. */ @@ -52,8 +52,7 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, #endif -/* - * The AIO_MMAP cases force the mmapped page into memory here +/* The AIO_MMAP cases force the mmapped page into memory here * rather than in whatever place first touches the data. I used * to do this by touching the page, but that's delicate because * gcc is prone to optimizing that away. So, what's done here @@ -107,12 +106,12 @@ static int aio_thread(void *arg) signal(SIGWINCH, SIG_IGN); - while (1) { + while(1){ n = io_getevents(ctx, 1, 1, &event, NULL); - if (n < 0) { - if (errno == EINTR) + if(n < 0){ + if(errno == EINTR) continue; - printk(UM_KERN_ERR "aio_thread - io_getevents failed, " + printk("aio_thread - io_getevents failed, " "errno = %d\n", errno); } else { @@ -121,9 +120,9 @@ static int aio_thread(void *arg) .err = event.res }); reply_fd = ((struct aio_context *) reply.data)->reply_fd; err = write(reply_fd, &reply, sizeof(reply)); - if (err != sizeof(reply)) - printk(UM_KERN_ERR "aio_thread - write failed, " - "fd = %d, err = %d\n", reply_fd, errno); + if(err != sizeof(reply)) + printk("aio_thread - write failed, fd = %d, " + "err = %d\n", reply_fd, errno); } } return 0; @@ -138,10 +137,10 @@ static int do_not_aio(struct aio_thread_req *req) int n; actual = lseek64(req->io_fd, req->offset, SEEK_SET); - if (actual != req->offset) + if(actual != req->offset) return -errno; - switch(req->type) { + switch(req->type){ case AIO_READ: n = read(req->io_fd, req->buf, req->len); break; @@ -152,12 +151,11 @@ static int do_not_aio(struct aio_thread_req *req) n = read(req->io_fd, &c, sizeof(c)); break; default: - printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n", - req->type); + printk("do_not_aio - bad request type : %d\n", req->type); return -EINVAL; } - if (n < 0) + if(n < 0) return -errno; return 0; } @@ -175,18 +173,16 @@ static int not_aio_thread(void *arg) int err; signal(SIGWINCH, SIG_IGN); - while (1) { + while(1){ err = read(aio_req_fd_r, &req, sizeof(req)); - if (err != sizeof(req)) { - if (err < 0) - printk(UM_KERN_ERR "not_aio_thread - " - "read failed, fd = %d, err = %d\n", - aio_req_fd_r, + if(err != sizeof(req)){ + if(err < 0) + printk("not_aio_thread - read failed, " + "fd = %d, err = %d\n", aio_req_fd_r, errno); else { - printk(UM_KERN_ERR "not_aio_thread - short " - "read, fd = %d, length = %d\n", - aio_req_fd_r, err); + printk("not_aio_thread - short read, fd = %d, " + "length = %d\n", aio_req_fd_r, err); } continue; } @@ -194,9 +190,9 @@ static int not_aio_thread(void *arg) reply = ((struct aio_thread_reply) { .data = req.aio, .err = err }); err = write(req.aio->reply_fd, &reply, sizeof(reply)); - if (err != sizeof(reply)) - printk(UM_KERN_ERR "not_aio_thread - write failed, " - "fd = %d, err = %d\n", req.aio->reply_fd, errno); + if(err != sizeof(reply)) + printk("not_aio_thread - write failed, fd = %d, " + "err = %d\n", req.aio->reply_fd, errno); } return 0; @@ -207,36 +203,35 @@ static int init_aio_24(void) int fds[2], err; err = os_pipe(fds, 1, 1); - if (err) + if(err) goto out; aio_req_fd_w = fds[0]; aio_req_fd_r = fds[1]; err = os_set_fd_block(aio_req_fd_w, 0); - if (err) + if(err) goto out_close_pipe; err = run_helper_thread(not_aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if (err < 0) + if(err < 0) goto out_close_pipe; aio_pid = err; goto out; out_close_pipe: - close(fds[0]); - close(fds[1]); + os_close_file(fds[0]); + os_close_file(fds[1]); aio_req_fd_w = -1; aio_req_fd_r = -1; out: #ifndef HAVE_AIO_ABI - printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during " - "build\n"); + printk("/usr/include/linux/aio_abi.h not present during build\n"); #endif - printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to " - "I/O thread\n"); + printk("2.6 host AIO support not used - falling back to I/O " + "thread\n"); return 0; } @@ -246,21 +241,21 @@ static int init_aio_26(void) { int err; - if (io_setup(256, &ctx)) { + if(io_setup(256, &ctx)){ err = -errno; - printk(UM_KERN_ERR "aio_thread failed to initialize context, " - "err = %d\n", errno); + printk("aio_thread failed to initialize context, err = %d\n", + errno); return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if (err < 0) + if(err < 0) return err; aio_pid = err; - printk(UM_KERN_INFO "Using 2.6 host AIO\n"); + printk("Using 2.6 host AIO\n"); return 0; } @@ -271,13 +266,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, int err; err = do_aio(ctx, type, io_fd, buf, len, offset, aio); - if (err) { + if(err){ reply = ((struct aio_thread_reply) { .data = aio, .err = err }); err = write(aio->reply_fd, &reply, sizeof(reply)); - if (err != sizeof(reply)) { + if(err != sizeof(reply)){ err = -errno; - printk(UM_KERN_ERR "submit_aio_26 - write failed, " + printk("submit_aio_26 - write failed, " "fd = %d, err = %d\n", aio->reply_fd, -err); } else err = 0; @@ -325,24 +320,28 @@ static int init_aio(void) { int err; - if (!aio_24) { + CHOOSE_MODE(({ if(!aio_24){ + printk("Disabling 2.6 AIO in tt mode\n"); + aio_24 = 1; + } }), (void) 0); + + if(!aio_24){ err = init_aio_26(); - if (err && (errno == ENOSYS)) { - printk(UM_KERN_INFO "2.6 AIO not supported on the " - "host - reverting to 2.4 AIO\n"); + if(err && (errno == ENOSYS)){ + printk("2.6 AIO not supported on the host - " + "reverting to 2.4 AIO\n"); aio_24 = 1; } else return err; } - if (aio_24) + if(aio_24) return init_aio_24(); return 0; } -/* - * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio +/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio * needs to be called when the kernel is running because it calls run_helper, * which needs get_free_page. exit_aio is a __uml_exitcall because the generic * kernel does not run __exitcalls on shutdown, and can't because many of them @@ -373,7 +372,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, int err; err = write(aio_req_fd_w, &req, sizeof(req)); - if (err == sizeof(req)) + if(err == sizeof(req)) err = 0; else err = -errno; @@ -385,8 +384,9 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len, struct aio_context *aio) { aio->reply_fd = reply_fd; - if (aio_24) + if(aio_24) return submit_aio_24(type, io_fd, buf, len, offset, aio); - else + else { return submit_aio_26(type, io_fd, buf, len, offset, aio); + } } diff --git a/trunk/arch/um/os-Linux/drivers/etap.h b/trunk/arch/um/os-Linux/drivers/etap.h index ddffd41c3f3f..57ecdaf2f67e 100644 --- a/trunk/arch/um/os-Linux/drivers/etap.h +++ b/trunk/arch/um/os-Linux/drivers/etap.h @@ -1,11 +1,8 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#ifndef __DRIVERS_ETAP_H -#define __DRIVERS_ETAP_H - #include "net_user.h" struct ethertap_data { @@ -18,4 +15,13 @@ struct ethertap_data { extern const struct net_user_info ethertap_user_info; -#endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/os-Linux/drivers/ethertap_kern.c b/trunk/arch/um/os-Linux/drivers/ethertap_kern.c index 04f11b9f1ac0..12689141414d 100644 --- a/trunk/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/trunk/arch/um/os-Linux/drivers/ethertap_kern.c @@ -1,15 +1,16 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ #include "linux/init.h" -#include -#include "etap.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" #include "net_kern.h" +#include "net_user.h" +#include "etap.h" struct ethertap_init { char *dev_name; @@ -36,24 +37,32 @@ static void etap_init(struct net_device *dev, void *data) printk("\n"); } -static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) { int len; - len = net_recvfrom(fd, skb_mac_header(skb), - skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP); - if (len <= 0) - return(len); - - skb_pull(skb, 2); + *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); + if(*skb == NULL) return(-ENOMEM); + len = net_recvfrom(fd, skb_mac_header(*skb), + (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); + if(len <= 0) return(len); + skb_pull(*skb, 2); len -= 2; - return len; + return(len); } -static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - skb_push(skb, 2); - return net_send(fd, skb->data, skb->len); + if(skb_headroom(*skb) < 2){ + struct sk_buff *skb2; + + skb2 = skb_realloc_headroom(*skb, 2); + dev_kfree_skb(*skb); + if (skb2 == NULL) return(-ENOMEM); + *skb = skb2; + } + skb_push(*skb, 2); + return(net_send(fd, (*skb)->data, (*skb)->len)); } const struct net_kern_info ethertap_kern_info = { @@ -70,15 +79,15 @@ int ethertap_setup(char *str, char **mac_out, void *data) *init = ((struct ethertap_init) { .dev_name = NULL, .gate_addr = NULL }); - if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out, + if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, &init->gate_addr)) - return 0; - if (init->dev_name == NULL) { - printk(KERN_ERR "ethertap_setup : Missing tap device name\n"); - return 0; + return(0); + if(init->dev_name == NULL){ + printk("ethertap_setup : Missing tap device name\n"); + return(0); } - return 1; + return(1); } static struct transport ethertap_transport = { @@ -88,7 +97,6 @@ static struct transport ethertap_transport = { .user = ðertap_user_info, .kern = ðertap_kern_info, .private_size = sizeof(struct ethertap_data), - .setup_size = sizeof(struct ethertap_init), }; static int register_ethertap(void) diff --git a/trunk/arch/um/os-Linux/drivers/ethertap_user.c b/trunk/arch/um/os-Linux/drivers/ethertap_user.c index 4ff553603449..61d3953c7ac9 100644 --- a/trunk/arch/um/os-Linux/drivers/ethertap_user.c +++ b/trunk/arch/um/os-Linux/drivers/ethertap_user.c @@ -1,5 +1,4 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. @@ -8,16 +7,20 @@ #include #include -#include -#include +#include +#include +#include #include #include +#include +#include +#include "user.h" +#include "kern_util.h" +#include "net_user.h" #include "etap.h" -#include "kern_constants.h" #include "os.h" -#include "net_user.h" #include "um_malloc.h" -#include "user.h" +#include "kern_constants.h" #define MAX_PACKET ETH_MAX_PACKET @@ -46,18 +49,16 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); CATCH_EINTR(n = write(fd, &change, sizeof(change))); - if (n != sizeof(change)) { - printk(UM_KERN_ERR "etap_change - request failed, err = %d\n", - errno); + if(n != sizeof(change)){ + printk("etap_change - request failed, err = %d\n", errno); return; } output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); - if (output == NULL) - printk(UM_KERN_ERR "etap_change : Failed to allocate output " - "buffer\n"); + if(output == NULL) + printk("etap_change : Failed to allocate output buffer\n"); read_output(fd, output, UM_KERN_PAGE_SIZE); - if (output != NULL) { + if(output != NULL){ printk("%s", output); kfree(output); } @@ -86,11 +87,11 @@ static void etap_pre_exec(void *arg) struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - close(data->data_me); - close(data->control_me); + os_close_file(data->data_me); + os_close_file(data->control_me); } -static int etap_tramp(char *dev, char *gate, int control_me, +static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; @@ -100,13 +101,13 @@ static int etap_tramp(char *dev, char *gate, int control_me, char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, gate_buf, NULL }; - char *nosetup_args[] = { "uml_net", version_buf, "ethertap", + char *nosetup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, NULL }; char **args, c; sprintf(data_fd_buf, "%d", data_remote); sprintf(version_buf, "%d", UML_NET_VERSION); - if (gate != NULL) { + if(gate != NULL){ strcpy(gate_buf, gate); args = setup_args; } @@ -118,26 +119,24 @@ static int etap_tramp(char *dev, char *gate, int control_me, pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args); - if (pid < 0) + if(pid < 0) err = pid; - close(data_remote); - close(control_remote); + os_close_file(data_remote); + os_close_file(control_remote); CATCH_EINTR(n = read(control_me, &c, sizeof(c))); - if (n != sizeof(c)) { + if(n != sizeof(c)){ err = -errno; - printk(UM_KERN_ERR "etap_tramp : read of status failed, " - "err = %d\n", -err); + printk("etap_tramp : read of status failed, err = %d\n", -err); return err; } - if (c != 1) { - printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); + if(c != 1){ + printk("etap_tramp : uml_net failed\n"); err = -EINVAL; CATCH_EINTR(n = waitpid(pid, &status, 0)); - if (n < 0) + if(n < 0) err = -errno; - else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) - printk(UM_KERN_ERR "uml_net didn't exit with " - "status 1\n"); + else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) + printk("uml_net didn't exit with status 1\n"); } return err; } @@ -149,56 +148,43 @@ static int etap_open(void *data) int data_fds[2], control_fds[2], err, output_len; err = tap_open_common(pri->dev, pri->gate_addr); - if (err) + if(err) return err; - err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds); - if (err) { - err = -errno; - printk(UM_KERN_ERR "etap_open - data socketpair failed - " - "err = %d\n", errno); + err = os_pipe(data_fds, 0, 0); + if(err < 0){ + printk("data os_pipe failed - err = %d\n", -err); return err; } - err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds); - if (err) { - err = -errno; - printk(UM_KERN_ERR "etap_open - control socketpair failed - " - "err = %d\n", errno); - goto out_close_data; + err = os_pipe(control_fds, 1, 0); + if(err < 0){ + printk("control os_pipe failed - err = %d\n", -err); + return err; } - err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], + err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); - if (output == NULL) - printk(UM_KERN_ERR "etap_open : failed to allocate output " - "buffer\n"); + if(output == NULL) + printk("etap_open : failed to allocate output buffer\n"); else { printk("%s", output); kfree(output); } - if (err < 0) { - printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err); - goto out_close_control; + if(err < 0){ + printk("etap_tramp failed - err = %d\n", -err); + return err; } pri->data_fd = data_fds[0]; pri->control_fd = control_fds[0]; iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); return data_fds[0]; - -out_close_control: - close(control_fds[0]); - close(control_fds[1]); -out_close_data: - close(data_fds[0]); - close(data_fds[1]); - return err; } static void etap_close(int fd, void *data) @@ -206,41 +192,37 @@ static void etap_close(int fd, void *data) struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - close(fd); - - if (shutdown(pri->data_fd, SHUT_RDWR) < 0) - printk(UM_KERN_ERR "etap_close - shutdown data socket failed, " - "errno = %d\n", errno); - - if (shutdown(pri->control_fd, SHUT_RDWR) < 0) - printk(UM_KERN_ERR "etap_close - shutdown control socket " - "failed, errno = %d\n", errno); - - close(pri->data_fd); + os_close_file(fd); + os_shutdown_socket(pri->data_fd, 1, 1); + os_close_file(pri->data_fd); pri->data_fd = -1; - close(pri->control_fd); + os_close_file(pri->control_fd); pri->control_fd = -1; } +static int etap_set_mtu(int mtu, void *data) +{ + return mtu; +} + static void etap_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if (pri->control_fd == -1) + if(pri->control_fd == -1) return; etap_open_addr(addr, netmask, &pri->control_fd); } -static void etap_del_addr(unsigned char *addr, unsigned char *netmask, +static void etap_del_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; - if (pri->control_fd == -1) + if(pri->control_fd == -1) return; - etap_close_addr(addr, netmask, &pri->control_fd); } @@ -249,8 +231,8 @@ const struct net_user_info ethertap_user_info = { .open = etap_open, .close = etap_close, .remove = NULL, + .set_mtu = etap_set_mtu, .add_address = etap_add_addr, .delete_address = etap_del_addr, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP, + .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP }; diff --git a/trunk/arch/um/os-Linux/drivers/tuntap.h b/trunk/arch/um/os-Linux/drivers/tuntap.h index f17c31586c84..d3e8d3af6245 100644 --- a/trunk/arch/um/os-Linux/drivers/tuntap.h +++ b/trunk/arch/um/os-Linux/drivers/tuntap.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -19,3 +19,14 @@ struct tuntap_data { extern const struct net_user_info tuntap_user_info; #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/os-Linux/drivers/tuntap_kern.c b/trunk/arch/um/os-Linux/drivers/tuntap_kern.c index 9d384807b077..f1714e7fb1d0 100644 --- a/trunk/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/trunk/arch/um/os-Linux/drivers/tuntap_kern.c @@ -1,13 +1,16 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include -#include -#include +#include "linux/stddef.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "linux/skbuff.h" +#include "linux/init.h" +#include "asm/errno.h" #include "net_kern.h" +#include "net_user.h" #include "tuntap.h" struct tuntap_init { @@ -35,15 +38,19 @@ static void tuntap_init(struct net_device *dev, void *data) printk("\n"); } -static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int tuntap_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return net_read(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) return(-ENOMEM); + return(net_read(fd, skb_mac_header(*skb), + (*skb)->dev->mtu + ETH_HEADER_OTHER)); } -static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int tuntap_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) { - return net_write(fd, skb->data, skb->len); + return(net_write(fd, (*skb)->data, (*skb)->len)); } const struct net_kern_info tuntap_kern_info = { @@ -60,11 +67,11 @@ int tuntap_setup(char *str, char **mac_out, void *data) *init = ((struct tuntap_init) { .dev_name = NULL, .gate_addr = NULL }); - if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out, + if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, &init->gate_addr)) - return 0; + return(0); - return 1; + return(1); } static struct transport tuntap_transport = { diff --git a/trunk/arch/um/os-Linux/drivers/tuntap_user.c b/trunk/arch/um/os-Linux/drivers/tuntap_user.c index 6c55d3c8ead8..f848b4ea9343 100644 --- a/trunk/arch/um/os-Linux/drivers/tuntap_user.c +++ b/trunk/arch/um/os-Linux/drivers/tuntap_user.c @@ -1,22 +1,27 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ #include +#include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include #include -#include "kern_constants.h" -#include "os.h" +#include +#include +#include +#include "net_user.h" #include "tuntap.h" +#include "kern_util.h" #include "user.h" +#include "os.h" + +#define MAX_PACKET ETH_MAX_PACKET static int tuntap_user_init(void *data, void *dev) { @@ -32,7 +37,7 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, struct tuntap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if ((pri->fd == -1) || pri->fixed_config) + if((pri->fd == -1) || pri->fixed_config) return; open_addr(addr, netmask, pri->dev_name); } @@ -42,7 +47,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, { struct tuntap_data *pri = data; - if ((pri->fd == -1) || pri->fixed_config) + if((pri->fd == -1) || pri->fixed_config) return; close_addr(addr, netmask, pri->dev_name); } @@ -57,7 +62,7 @@ static void tuntap_pre_exec(void *arg) struct tuntap_pre_exec_data *data = arg; dup2(data->stdout, 1); - close(data->close_me); + os_close_file(data->close_me); } static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, @@ -80,14 +85,14 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, pid = run_helper(tuntap_pre_exec, &data, argv); - if (pid < 0) + if(pid < 0) return -pid; - close(remote); + os_close_file(remote); msg.msg_name = NULL; msg.msg_namelen = 0; - if (buffer != NULL) { + if(buffer != NULL){ iov = ((struct iovec) { buffer, buffer_len }); msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -101,28 +106,26 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, msg.msg_flags = 0; n = recvmsg(me, &msg, 0); *used_out = n; - if (n < 0) { + if(n < 0){ err = -errno; - printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - " - "errno = %d\n", errno); + printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", + errno); return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg == NULL) { - printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " - "message\n"); + if(cmsg == NULL){ + printk("tuntap_open_tramp : didn't receive a message\n"); return -EINVAL; } - if ((cmsg->cmsg_level != SOL_SOCKET) || - (cmsg->cmsg_type != SCM_RIGHTS)) { - printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " - "descriptor\n"); + if((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)){ + printk("tuntap_open_tramp : didn't receive a descriptor\n"); return -EINVAL; } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; - os_set_exec_close(*fd_out); + os_set_exec_close(*fd_out, 1); return 0; } @@ -134,51 +137,47 @@ static int tuntap_open(void *data) int err, fds[2], len, used; err = tap_open_common(pri->dev, pri->gate_addr); - if (err < 0) + if(err < 0) return err; - if (pri->fixed_config) { + if(pri->fixed_config){ pri->fd = os_open_file("/dev/net/tun", of_cloexec(of_rdwr(OPENFLAGS())), 0); - if (pri->fd < 0) { - printk(UM_KERN_ERR "Failed to open /dev/net/tun, " - "err = %d\n", -pri->fd); + if(pri->fd < 0){ + printk("Failed to open /dev/net/tun, err = %d\n", + -pri->fd); return pri->fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); - if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) { + if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ err = -errno; - printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", - errno); - close(pri->fd); + printk("TUNSETIFF failed, errno = %d\n", errno); + os_close_file(pri->fd); return err; } } else { - err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds); - if (err) { - err = -errno; - printk(UM_KERN_ERR "tuntap_open : socketpair failed - " - "errno = %d\n", errno); + err = os_pipe(fds, 0, 0); + if(err < 0){ + printk("tuntap_open : os_pipe failed - err = %d\n", + -err); return err; } buffer = get_output_buffer(&len); - if (buffer != NULL) - len--; + if(buffer != NULL) len--; used = 0; err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], fds[1], buffer, len, &used); output = buffer; - if (err < 0) { + if(err < 0) { printk("%s", output); free_output_buffer(buffer); - printk(UM_KERN_ERR "tuntap_open_tramp failed - " - "err = %d\n", -err); + printk("tuntap_open_tramp failed - err = %d\n", -err); return err; } @@ -187,7 +186,7 @@ static int tuntap_open(void *data) printk("%s", output); free_output_buffer(buffer); - close(fds[0]); + os_close_file(fds[0]); iter_addresses(pri->dev, open_addr, pri->dev_name); } @@ -198,19 +197,24 @@ static void tuntap_close(int fd, void *data) { struct tuntap_data *pri = data; - if (!pri->fixed_config) + if(!pri->fixed_config) iter_addresses(pri->dev, close_addr, pri->dev_name); - close(fd); + os_close_file(fd); pri->fd = -1; } +static int tuntap_set_mtu(int mtu, void *data) +{ + return mtu; +} + const struct net_user_info tuntap_user_info = { .init = tuntap_user_init, .open = tuntap_open, .close = tuntap_close, .remove = NULL, + .set_mtu = tuntap_set_mtu, .add_address = tuntap_add_addr, .delete_address = tuntap_del_addr, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, + .max_packet = MAX_PACKET }; diff --git a/trunk/arch/um/os-Linux/file.c b/trunk/arch/um/os-Linux/file.c index b542a3a021bf..c3ecc2a84e0c 100644 --- a/trunk/arch/um/os-Linux/file.c +++ b/trunk/arch/um/os-Linux/file.c @@ -82,6 +82,13 @@ int os_access(const char* file, int mode) return 0; } +void os_print_error(int error, const char* str) +{ + errno = error < 0 ? -error : error; + + perror(str); +} + /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) { @@ -94,6 +101,30 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) return err; } +int os_window_size(int fd, int *rows, int *cols) +{ + struct winsize size; + + if(ioctl(fd, TIOCGWINSZ, &size) < 0) + return -errno; + + *rows = size.ws_row; + *cols = size.ws_col; + + return 0; +} + +int os_new_tty_pgrp(int fd, int pid) +{ + if(ioctl(fd, TIOCSCTTY, 0) < 0) + return -errno; + + if(tcsetpgrp(fd, pid) < 0) + return -errno; + + return 0; +} + /* FIXME: ensure namebuf in os_get_if_name is big enough */ int os_get_ifname(int fd, char* namebuf) { @@ -174,19 +205,19 @@ int os_file_mode(char *file, struct openflags *mode_out) *mode_out = OPENFLAGS(); - err = access(file, W_OK); - if(err && (errno != EACCES)) - return -errno; - else if(!err) - *mode_out = of_write(*mode_out); + err = os_access(file, OS_ACC_W_OK); + if((err < 0) && (err != -EACCES)) + return(err); - err = access(file, R_OK); - if(err && (errno != EACCES)) - return -errno; - else if(!err) - *mode_out = of_read(*mode_out); + *mode_out = of_write(*mode_out); - return err; + err = os_access(file, OS_ACC_R_OK); + if((err < 0) && (err != -EACCES)) + return(err); + + *mode_out = of_read(*mode_out); + + return(0); } int os_open_file(char *file, struct openflags flags, int mode) @@ -205,15 +236,15 @@ int os_open_file(char *file, struct openflags flags, int mode) fd = open64(file, f, mode); if(fd < 0) - return -errno; + return(-errno); if(flags.cl && fcntl(fd, F_SETFD, 1)){ err = -errno; - close(fd); + os_close_file(fd); return err; } - return fd; + return(fd); } int os_connect_socket(char *name) @@ -249,9 +280,9 @@ void os_close_file(int fd) close(fd); } -int os_seek_file(int fd, unsigned long long offset) +int os_seek_file(int fd, __u64 offset) { - unsigned long long actual; + __u64 actual; actual = lseek64(fd, offset, SEEK_SET); if(actual != offset) @@ -285,33 +316,31 @@ int os_file_size(char *file, unsigned long long *size_out) err = os_stat_file(file, &buf); if(err < 0){ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); - return err; + return(err); } if(S_ISBLK(buf.ust_mode)){ int fd; long blocks; - fd = open(file, O_RDONLY, 0); - if(fd < 0) { - err = -errno; - printk("Couldn't open \"%s\", errno = %d\n", file, - errno); - return err; + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open \"%s\", errno = %d\n", file, -fd); + return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - close(fd); - return err; + os_close_file(fd); + return(err); } *size_out = ((long long) blocks) * 512; - close(fd); + os_close_file(fd); + return(0); } - else *size_out = buf.ust_size; - - return 0; + *size_out = buf.ust_size; + return(0); } int os_file_modtime(char *file, unsigned long *modtime) @@ -329,28 +358,35 @@ int os_file_modtime(char *file, unsigned long *modtime) return 0; } -int os_get_exec_close(int fd, int *close_on_exec) +int os_get_exec_close(int fd, int* close_on_exec) { int ret; - CATCH_EINTR(ret = fcntl(fd, F_GETFD)); + do { + ret = fcntl(fd, F_GETFD); + } while((ret < 0) && (errno == EINTR)) ; if(ret < 0) - return -errno; + return(-errno); - *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0; - return ret; + *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; + return(ret); } -int os_set_exec_close(int fd) +int os_set_exec_close(int fd, int close_on_exec) { - int err; + int flag, err; - CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); + if(close_on_exec) flag = FD_CLOEXEC; + else flag = 0; + + do { + err = fcntl(fd, F_SETFD, flag); + } while((err < 0) && (errno == EINTR)) ; if(err < 0) - return -errno; - return err; + return(-errno); + return(err); } int os_pipe(int *fds, int stream, int close_on_exec) @@ -359,16 +395,16 @@ int os_pipe(int *fds, int stream, int close_on_exec) err = socketpair(AF_UNIX, type, 0, fds); if(err < 0) - return -errno; + return(-errno); if(!close_on_exec) - return 0; + return(0); - err = os_set_exec_close(fds[0]); + err = os_set_exec_close(fds[0], 1); if(err < 0) goto error; - err = os_set_exec_close(fds[1]); + err = os_set_exec_close(fds[1], 1); if(err < 0) goto error; @@ -376,9 +412,9 @@ int os_pipe(int *fds, int stream, int close_on_exec) error: printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); - close(fds[1]); - close(fds[0]); - return err; + os_close_file(fds[1]); + os_close_file(fds[0]); + return(err); } int os_set_fd_async(int fd, int owner) @@ -525,7 +561,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) return -errno; if(close_on_exec) { - err = os_set_exec_close(sock); + err = os_set_exec_close(sock, 1); if(err < 0) printk("create_unix_socket : close_on_exec failed, " "err = %d", -err); diff --git a/trunk/arch/um/os-Linux/helper.c b/trunk/arch/um/os-Linux/helper.c index 7a72dbb61b0d..d81af7b8587a 100644 --- a/trunk/arch/um/os-Linux/helper.c +++ b/trunk/arch/um/os-Linux/helper.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "user.h" #include "kern_util.h" #include "os.h" @@ -55,14 +54,13 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) if (stack == 0) return -ENOMEM; - ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); + ret = os_pipe(fds, 1, 0); if (ret < 0) { - ret = -errno; - printk("run_helper : pipe failed, errno = %d\n", errno); + printk("run_helper : pipe failed, ret = %d\n", -ret); goto out_free; } - ret = os_set_exec_close(fds[1]); + ret = os_set_exec_close(fds[1], 1); if (ret < 0) { printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", -ret); diff --git a/trunk/arch/um/os-Linux/irq.c b/trunk/arch/um/os-Linux/irq.c index 6aa6f95d6524..a633fa8e0a94 100644 --- a/trunk/arch/um/os-Linux/irq.c +++ b/trunk/arch/um/os-Linux/irq.c @@ -145,7 +145,11 @@ void init_irq_signals(int on_sigstack) flags = on_sigstack ? SA_ONSTACK : 0; + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, + flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGWINCH, SIG_IGN); } diff --git a/trunk/arch/um/os-Linux/main.c b/trunk/arch/um/os-Linux/main.c index 82c3778627b8..e85f4995a011 100644 --- a/trunk/arch/um/os-Linux/main.c +++ b/trunk/arch/um/os-Linux/main.c @@ -1,21 +1,33 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include #include #include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include "kern_util.h" #include "as-layout.h" +#include "mem_user.h" +#include "irq_user.h" +#include "user.h" #include "init.h" -#include "kern_constants.h" -#include "kern_util.h" +#include "mode.h" +#include "choose-mode.h" +#include "uml-config.h" #include "os.h" #include "um_malloc.h" +#include "kern_constants.h" + +/* Set in main, unchanged thereafter */ +char *linux_prog; #define PGD_BOUND (4 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024) @@ -25,13 +37,13 @@ static void set_stklim(void) { struct rlimit lim; - if (getrlimit(RLIMIT_STACK, &lim) < 0) { + if(getrlimit(RLIMIT_STACK, &lim) < 0){ perror("getrlimit"); exit(1); } - if ((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)) { + if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ lim.rlim_cur = STACKSIZE; - if (setrlimit(RLIMIT_STACK, &lim) < 0) { + if(setrlimit(RLIMIT_STACK, &lim) < 0){ perror("setrlimit"); exit(1); } @@ -43,7 +55,7 @@ static __init void do_uml_initcalls(void) initcall_t *call; call = &__uml_initcall_start; - while (call < &__uml_initcall_end) { + while (call < &__uml_initcall_end){ (*call)(); call++; } @@ -62,8 +74,7 @@ static void install_fatal_handler(int sig) /* All signals are enabled in this handler ... */ sigemptyset(&action.sa_mask); - /* - * ... including the signal being handled, plus we want the + /* ... including the signal being handled, plus we want the * handler reset to the default behavior, so that if an exit * handler is hanging for some reason, the UML will just die * after this signal is sent a second time. @@ -71,7 +82,7 @@ static void install_fatal_handler(int sig) action.sa_flags = SA_RESETHAND | SA_NODEFER; action.sa_restorer = NULL; action.sa_handler = last_ditch_exit; - if (sigaction(sig, &action, NULL) < 0) { + if(sigaction(sig, &action, NULL) < 0){ printf("failed to install handler for signal %d - errno = %d\n", errno); exit(1); @@ -87,8 +98,7 @@ static void setup_env_path(void) int path_len = 0; old_path = getenv("PATH"); - /* - * if no PATH variable is set or it has an empty value + /* if no PATH variable is set or it has an empty value * just use the default + /usr/lib/uml */ if (!old_path || (path_len = strlen(old_path)) == 0) { @@ -116,68 +126,93 @@ int __init main(int argc, char **argv, char **envp) char **new_argv; int ret, i, err; +#ifdef UML_CONFIG_CMDLINE_ON_HOST + /* Allocate memory for thread command lines */ + if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ + + char padding[THREAD_NAME_LEN] = { + [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' + }; + + new_argv = malloc((argc + 2) * sizeof(char*)); + if(!new_argv) { + perror("Allocating extended argv"); + exit(1); + } + + new_argv[0] = argv[0]; + new_argv[1] = padding; + + for(i = 2; i <= argc; i++) + new_argv[i] = argv[i - 1]; + new_argv[argc + 1] = NULL; + + execvp(new_argv[0], new_argv); + perror("execing with extended args"); + exit(1); + } +#endif + + linux_prog = argv[0]; + set_stklim(); setup_env_path(); new_argv = malloc((argc + 1) * sizeof(char *)); - if (new_argv == NULL) { + if(new_argv == NULL){ perror("Mallocing argv"); exit(1); } - for (i = 0; i < argc; i++) { + for(i=0;i= uml_physmem) && (addr < high_physmem)) { - if (kmalloc_ok) + if((addr >= uml_physmem) && (addr < high_physmem)){ + if(CAN_KMALLOC()) kfree(ptr); } - else if ((addr >= start_vm) && (addr < end_vm)) { - if (kmalloc_ok) + else if((addr >= start_vm) && (addr < end_vm)){ + if(CAN_KMALLOC()) vfree(ptr); } else __real_free(ptr); diff --git a/trunk/arch/um/os-Linux/mem.c b/trunk/arch/um/os-Linux/mem.c index 436f8d20b20f..c6378c6d10d2 100644 --- a/trunk/arch/um/os-Linux/mem.c +++ b/trunk/arch/um/os-Linux/mem.c @@ -218,7 +218,7 @@ int __init create_tmp_file(unsigned long long len) err = fchmod(fd, 0777); if(err < 0){ - perror("fchmod"); + perror("os_mode_fd"); exit(1); } @@ -226,7 +226,7 @@ int __init create_tmp_file(unsigned long long len) * increase the file size by one byte, to the desired length. */ if (lseek64(fd, len - 1, SEEK_SET) < 0) { - perror("lseek64"); + perror("os_seek_file"); exit(1); } @@ -247,7 +247,7 @@ int __init create_mem_file(unsigned long long len) fd = create_tmp_file(len); - err = os_set_exec_close(fd); + err = os_set_exec_close(fd, 1); if(err < 0){ errno = -err; perror("exec_close"); diff --git a/trunk/arch/um/os-Linux/process.c b/trunk/arch/um/os-Linux/process.c index 37781db4ceca..e9c143297512 100644 --- a/trunk/arch/um/os-Linux/process.c +++ b/trunk/arch/um/os-Linux/process.c @@ -1,24 +1,27 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include #include +#include #include #include -#include #include -#include #include -#include -#include "init.h" -#include "kern_constants.h" -#include "longjmp.h" +#include +#include +#include "ptrace_user.h" #include "os.h" +#include "user.h" #include "process.h" +#include "irq_user.h" +#include "kern_util.h" +#include "longjmp.h" #include "skas_ptrace.h" -#include "user.h" +#include "kern_constants.h" +#include "uml-config.h" +#include "init.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -29,32 +32,30 @@ unsigned long os_process_pc(int pid) { char proc_stat[STAT_PATH_LEN], buf[256]; - unsigned long pc = ARBITRARY_ADDR; + unsigned long pc; int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); - fd = open(proc_stat, O_RDONLY, 0); - if (fd < 0) { - printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', " - "errno = %d\n", proc_stat, errno); - goto out; + fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("os_process_pc - couldn't open '%s', err = %d\n", + proc_stat, -fd); + return ARBITRARY_ADDR; } CATCH_EINTR(err = read(fd, buf, sizeof(buf))); - if (err < 0) { - printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', " - "err = %d\n", proc_stat, errno); - goto out_close; + if(err < 0){ + printk("os_process_pc - couldn't read '%s', err = %d\n", + proc_stat, errno); + os_close_file(fd); + return ARBITRARY_ADDR; } os_close_file(fd); pc = ARBITRARY_ADDR; - if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %lu", &pc) != 1) - printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n", - buf); - out_close: - close(fd); - out: + if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %lu", &pc) != 1){ + printk("os_process_pc - couldn't find pc in '%s'\n", buf); + } return pc; } @@ -62,32 +63,30 @@ int os_process_parent(int pid) { char stat[STAT_PATH_LEN]; char data[256]; - int parent = FAILURE_PID, n, fd; + int parent, n, fd; - if (pid == -1) - return parent; + if(pid == -1) + return -1; snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); - fd = open(stat, O_RDONLY, 0); - if (fd < 0) { - printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat, - errno); - return parent; + fd = os_open_file(stat, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open '%s', err = %d\n", stat, -fd); + return FAILURE_PID; } CATCH_EINTR(n = read(fd, data, sizeof(data))); - close(fd); + os_close_file(fd); - if (n < 0) { - printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat, - errno); - return parent; + if(n < 0){ + printk("Couldn't read '%s', err = %d\n", stat, errno); + return FAILURE_PID; } parent = FAILURE_PID; n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); - if (n != 1) - printk(UM_KERN_ERR "Failed to scan '%s'\n", data); + if(n != 1) + printk("Failed to scan '%s'\n", data); return parent; } @@ -100,8 +99,9 @@ void os_stop_process(int pid) void os_kill_process(int pid, int reap_child) { kill(pid, SIGKILL); - if (reap_child) + if(reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); + } /* This is here uniquely to have access to the userspace errno, i.e. the one @@ -129,10 +129,17 @@ void os_kill_ptraced_process(int pid, int reap_child) kill(pid, SIGKILL); ptrace(PTRACE_KILL, pid); ptrace(PTRACE_CONT, pid); - if (reap_child) + if(reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); } +#ifdef UML_CONFIG_MODE_TT +void os_usr1_process(int pid) +{ + kill(pid, SIGUSR1); +} +#endif + /* Don't use the glibc version, which caches the result in TLS. It misses some * syscalls, and also breaks with clone(), which does not unshare the TLS. */ @@ -153,35 +160,34 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, void *loc; int prot; - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, fd, off); - if (loc == MAP_FAILED) + if(loc == MAP_FAILED) return -errno; return 0; } int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) { - int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0)); - if (mprotect(addr, len, prot) < 0) + if(mprotect(addr, len, prot) < 0) return -errno; - - return 0; + return 0; } int os_unmap_memory(void *addr, int len) { - int err; + int err; - err = munmap(addr, len); - if (err < 0) + err = munmap(addr, len); + if(err < 0) return -errno; - return 0; + return 0; } #ifndef MADV_REMOVE @@ -193,7 +199,7 @@ int os_drop_memory(void *addr, int length) int err; err = madvise(addr, length, MADV_REMOVE); - if (err < 0) + if(err < 0) err = -errno; return err; } @@ -203,24 +209,22 @@ int __init can_drop_memory(void) void *addr; int fd, ok = 0; - printk(UM_KERN_INFO "Checking host MADV_REMOVE support..."); + printk("Checking host MADV_REMOVE support..."); fd = create_mem_file(UM_KERN_PAGE_SIZE); - if (fd < 0) { - printk(UM_KERN_ERR "Creating test memory file failed, " - "err = %d\n", -fd); + if(fd < 0){ + printk("Creating test memory file failed, err = %d\n", -fd); goto out; } addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - printk(UM_KERN_ERR "Mapping test memory file failed, " - "err = %d\n", -errno); + if(addr == MAP_FAILED){ + printk("Mapping test memory file failed, err = %d\n", -errno); goto out_close; } - if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) { - printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno); + if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ + printk("MADV_REMOVE failed, err = %d\n", -errno); goto out_unmap; } @@ -235,31 +239,58 @@ int __init can_drop_memory(void) return ok; } +#ifdef UML_CONFIG_MODE_TT +void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) +{ + int flags = 0, pages; + + if(sig_stack != NULL){ + pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); + set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE); + flags = SA_ONSTACK; + } + if(usr1_handler){ + struct sigaction sa; + + sa.sa_handler = usr1_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = flags; + sa.sa_restorer = NULL; + if(sigaction(SIGUSR1, &sa, NULL) < 0) + panic("init_new_thread_stack - sigaction failed - " + "errno = %d\n", errno); + } +} +#endif + void init_new_thread_signals(void) { set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + set_handler(SIGUSR2, (__sighandler_t) sig_handler, + SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, + -1); signal(SIGHUP, SIG_IGN); init_irq_signals(1); } -int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) +int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) { jmp_buf buf; int n; *jmp_ptr = &buf; n = UML_SETJMP(&buf); - if (n != 0) + if(n != 0) return n; (*fn)(arg); return 0; diff --git a/trunk/arch/um/os-Linux/registers.c b/trunk/arch/um/os-Linux/registers.c deleted file mode 100644 index a32ba6ab1211..000000000000 --- a/trunk/arch/um/os-Linux/registers.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2004 PathScale, Inc - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include "sysdep/ptrace.h" -#include "user.h" - -/* This is set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; - -void init_thread_registers(struct uml_pt_regs *to) -{ - memcpy(to->gp, exec_regs, sizeof(to->gp)); -} - -void save_registers(int pid, struct uml_pt_regs *regs) -{ - int err; - - err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); - if (err < 0) - panic("save_registers - saving registers failed, errno = %d\n", - errno); -} - -void restore_registers(int pid, struct uml_pt_regs *regs) -{ - int err; - - err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); - if (err < 0) - panic("restore_registers - saving registers failed, " - "errno = %d\n", errno); -} - -void init_registers(int pid) -{ - int err; - - err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); - if (err) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); - - arch_init_registers(pid); -} - -void get_safe_registers(unsigned long *regs) -{ - memcpy(regs, exec_regs, sizeof(exec_regs)); -} diff --git a/trunk/arch/um/os-Linux/signal.c b/trunk/arch/um/os-Linux/signal.c index e9800b0b5689..b98f7ea2d2f6 100644 --- a/trunk/arch/um/os-Linux/signal.c +++ b/trunk/arch/um/os-Linux/signal.c @@ -1,21 +1,26 @@ /* * Copyright (C) 2004 PathScale, Inc - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#include +#include +#include #include -#include #include -#include -#include -#include "os.h" -#include "sysdep/barrier.h" -#include "sysdep/sigcontext.h" +#include +#include +#include #include "user.h" +#include "signal_kern.h" +#include "sysdep/sigcontext.h" +#include "sysdep/barrier.h" +#include "sigcontext.h" +#include "mode.h" +#include "os.h" -/* - * These are the asynchronous signals. SIGPROF is excluded because we want to +/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled + * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to * be able to profile all of UML, not just the non-critical sections. If * profiling is not thread-safe, then that is not my problem. We can disable * profiling when SMP is enabled in that case. @@ -26,8 +31,10 @@ #define SIGVTALRM_BIT 1 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) -/* - * These are used by both the signal handlers and +#define SIGALRM_BIT 2 +#define SIGALRM_MASK (1 << SIGALRM_BIT) + +/* These are used by both the signal handlers and * block/unblock_signals. I don't want modifications cached in a * register - they must go straight to memory. */ @@ -39,27 +46,34 @@ void sig_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if (!enabled && (sig == SIGIO)) { + if(!enabled && (sig == SIGIO)){ pending |= SIGIO_MASK; return; } block_signals(); - sig_handler_common_skas(sig, sc); + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, + sig, sc); set_signals(enabled); } -static void real_alarm_handler(struct sigcontext *sc) +static void real_alarm_handler(int sig, struct sigcontext *sc) { - struct uml_pt_regs regs; + union uml_pt_regs regs; - if (sc != NULL) + if(sig == SIGALRM) + switch_timers(0); + + if(sc != NULL) copy_sc(®s, sc); - regs.is_user = 0; + regs.skas.is_user = 0; unblock_signals(); - timer_handler(SIGVTALRM, ®s); + timer_handler(sig, ®s); + + if(sig == SIGALRM) + switch_timers(1); } void alarm_handler(int sig, struct sigcontext *sc) @@ -67,30 +81,27 @@ void alarm_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if (!signals_enabled) { - pending |= SIGVTALRM_MASK; + if(!signals_enabled){ + if(sig == SIGVTALRM) + pending |= SIGVTALRM_MASK; + else pending |= SIGALRM_MASK; + return; } block_signals(); - real_alarm_handler(sc); + real_alarm_handler(sig, sc); set_signals(enabled); } -void timer_init(void) -{ - set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); -} - void set_sigstack(void *sig_stack, int size) { stack_t stack = ((stack_t) { .ss_flags = 0, .ss_sp = (__ptr_t) sig_stack, .ss_size = size - sizeof(void *) }); - if (sigaltstack(&stack, NULL) != 0) + if(sigaltstack(&stack, NULL) != 0) panic("enabling signal stack failed, errno = %d\n", errno); } @@ -100,7 +111,7 @@ void remove_sigstack(void) .ss_sp = NULL, .ss_size = 0 }); - if (sigaltstack(&stack, NULL) != 0) + if(sigaltstack(&stack, NULL) != 0) panic("disabling signal stack failed, errno = %d\n", errno); } @@ -124,27 +135,26 @@ void handle_signal(int sig, struct sigcontext *sc) * with this interrupt. */ bail = to_irq_stack(&pending); - if (bail) + if(bail) return; nested = pending & 1; pending &= ~1; - while ((sig = ffs(pending)) != 0){ + while((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); (*handlers[sig])(sig, sc); } - /* - * Again, pending comes back with a mask of signals + /* Again, pending comes back with a mask of signals * that arrived while tearing down the stack. If this * is non-zero, we just go back, set up the stack * again, and handle the new interrupts. */ - if (!nested) + if(!nested) pending = from_irq_stack(nested); - } while (pending); + } while(pending); } extern void hard_handler(int sig); @@ -162,18 +172,18 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) sigemptyset(&action.sa_mask); va_start(ap, flags); - while ((mask = va_arg(ap, int)) != -1) + while((mask = va_arg(ap, int)) != -1) sigaddset(&action.sa_mask, mask); va_end(ap); action.sa_flags = flags; action.sa_restorer = NULL; - if (sigaction(sig, &action, NULL) < 0) + if(sigaction(sig, &action, NULL) < 0) panic("sigaction failed - errno = %d\n", errno); sigemptyset(&sig_mask); sigaddset(&sig_mask, sig); - if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) + if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) panic("sigprocmask failed - errno = %d\n", errno); } @@ -184,14 +194,13 @@ int change_sig(int signal, int on) sigemptyset(&sigset); sigaddset(&sigset, signal); sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return !sigismember(&old, signal); + return(!sigismember(&old, signal)); } void block_signals(void) { signals_enabled = 0; - /* - * This must return with signals disabled, so this barrier + /* This must return with signals disabled, so this barrier * ensures that writes are flushed out before the return. * This might matter if gcc figures out how to inline this and * decides to shuffle this code into the caller. @@ -203,31 +212,27 @@ void unblock_signals(void) { int save_pending; - if (signals_enabled == 1) + if(signals_enabled == 1) return; - /* - * We loop because the IRQ handler returns with interrupts off. So, + /* We loop because the IRQ handler returns with interrupts off. So, * interrupts may have arrived and we need to re-enable them and * recheck pending. */ - while(1) { - /* - * Save and reset save_pending after enabling signals. This + while(1){ + /* Save and reset save_pending after enabling signals. This * way, pending won't be changed while we're reading it. */ signals_enabled = 1; - /* - * Setting signals_enabled and reading pending must + /* Setting signals_enabled and reading pending must * happen in this order. */ mb(); save_pending = pending; - if (save_pending == 0) { - /* - * This must return with signals enabled, so + if(save_pending == 0){ + /* This must return with signals enabled, so * this barrier ensures that writes are * flushed out before the return. This might * matter if gcc figures out how to inline @@ -240,24 +245,26 @@ void unblock_signals(void) pending = 0; - /* - * We have pending interrupts, so disable signals, as the + /* We have pending interrupts, so disable signals, as the * handlers expect them off when they are called. They will * be enabled again above. */ signals_enabled = 0; - /* - * Deal with SIGIO first because the alarm handler might + /* Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. */ - if (save_pending & SIGIO_MASK) - sig_handler_common_skas(SIGIO, NULL); + if(save_pending & SIGIO_MASK) + CHOOSE_MODE_PROC(sig_handler_common_tt, + sig_handler_common_skas, SIGIO, NULL); + + if(save_pending & SIGALRM_MASK) + real_alarm_handler(SIGALRM, NULL); - if (save_pending & SIGVTALRM_MASK) - real_alarm_handler(NULL); + if(save_pending & SIGVTALRM_MASK) + real_alarm_handler(SIGVTALRM, NULL); } } @@ -269,11 +276,11 @@ int get_signals(void) int set_signals(int enable) { int ret; - if (signals_enabled == enable) + if(signals_enabled == enable) return enable; ret = signals_enabled; - if (enable) + if(enable) unblock_signals(); else block_signals(); diff --git a/trunk/arch/um/os-Linux/skas/mem.c b/trunk/arch/um/os-Linux/skas/mem.c index 484e68f9f7ae..0f7df4eb903f 100644 --- a/trunk/arch/um/os-Linux/skas/mem.c +++ b/trunk/arch/um/os-Linux/skas/mem.c @@ -1,26 +1,31 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include +#include #include #include +#include #include -#include "init.h" -#include "kern_constants.h" -#include "as-layout.h" -#include "mm_id.h" +#include +#include +#include +#include "mem_user.h" +#include "mem.h" +#include "skas.h" +#include "user.h" #include "os.h" #include "proc_mm.h" #include "ptrace_user.h" +#include "kern_util.h" +#include "task.h" #include "registers.h" -#include "skas.h" -#include "user.h" +#include "uml-config.h" #include "sysdep/ptrace.h" #include "sysdep/stub.h" -#include "uml-config.h" +#include "init.h" +#include "kern_constants.h" extern unsigned long batch_syscall_stub, __syscall_stub_start; @@ -29,7 +34,7 @@ extern void wait_stub_done(int pid); static inline unsigned long *check_init_stack(struct mm_id * mm_idp, unsigned long *stack) { - if (stack == NULL) { + if(stack == NULL) { stack = (unsigned long *) mm_idp->stack + 2; *stack = 0; } @@ -40,8 +45,8 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - get_safe_registers(syscall_regs); - syscall_regs[REGS_IP_INDEX] = STUB_CODE + + get_safe_registers(syscall_regs, NULL); + syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + ((unsigned long) &batch_syscall_stub - (unsigned long) &__syscall_stub_start); return 0; @@ -63,30 +68,29 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) unsigned long * syscall; int err, pid = mm_idp->u.pid; - if (proc_mm) + if(proc_mm) /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; multi_count++; n = ptrace_setregs(pid, syscall_regs); - if (n < 0) { - printk(UM_KERN_ERR "Registers - \n"); - for (i = 0; i < MAX_REG_NR; i++) - printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]); + if(n < 0){ + printk("Registers - \n"); + for(i = 0; i < MAX_REG_NR; i++) + printk("\t%d\t0x%lx\n", i, syscall_regs[i]); panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", -n); } err = ptrace(PTRACE_CONT, pid, 0, 0); - if (err) + if(err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* - * When the stub stops, we find the following values on the + /* When the stub stops, we find the following values on the * beginning of the stack: * (long )return_value * (long )offset to failed sycall-data (0, if no error) @@ -94,26 +98,26 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) ret = *((unsigned long *) mm_idp->stack); offset = *((unsigned long *) mm_idp->stack + 1); if (offset) { - data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA); - printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, " + data = (unsigned long *)(mm_idp->stack + + offset - UML_CONFIG_STUB_DATA); + printk("do_syscall_stub : ret = %ld, offset = %ld, " "data = %p\n", ret, offset, data); syscall = (unsigned long *)((unsigned long)data + data[0]); - printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, " - "return value = 0x%lx, expected return value = 0x%lx\n", + printk("do_syscall_stub: syscall %ld failed, return value = " + "0x%lx, expected return value = 0x%lx\n", syscall[0], ret, syscall[7]); - printk(UM_KERN_ERR " syscall parameters: " + printk(" syscall parameters: " "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", syscall[1], syscall[2], syscall[3], syscall[4], syscall[5], syscall[6]); - for (n = 1; n < data[0]/sizeof(long); n++) { - if (n == 1) - printk(UM_KERN_ERR " additional syscall " - "data:"); - if (n % 4 == 1) - printk("\n" UM_KERN_ERR " "); + for(n = 1; n < data[0]/sizeof(long); n++) { + if(n == 1) + printk(" additional syscall data:"); + if(n % 4 == 1) + printk("\n "); printk(" 0x%lx", data[n]); } - if (n > 1) + if(n > 1) printk("\n"); } else ret = 0; @@ -129,7 +133,7 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, { unsigned long *stack = check_init_stack(mm_idp, *addr); - if (done && *addr == NULL) + if(done && *addr == NULL) single_count++; *stack += sizeof(long); @@ -146,8 +150,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, *stack = 0; multi_op_count++; - if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < - UM_KERN_PAGE_SIZE - 10 * sizeof(long))) { + if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < + UM_KERN_PAGE_SIZE - 10 * sizeof(long))){ *addr = stack; return 0; } @@ -162,15 +166,14 @@ long syscall_stub_data(struct mm_id * mm_idp, unsigned long *stack; int ret = 0; - /* - * If *addr still is uninitialized, it *must* contain NULL. + /* If *addr still is uninitialized, it *must* contain NULL. * Thus in this case do_syscall_stub correctly won't be called. */ - if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= + if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) { ret = do_syscall_stub(mm_idp, addr); /* in case of error, don't overwrite data on stack */ - if (ret) + if(ret) return ret; } @@ -182,7 +185,7 @@ long syscall_stub_data(struct mm_id * mm_idp, memcpy(stack + 1, data, data_count * sizeof(long)); *stub_addr = (void *)(((unsigned long)(stack + 1) & - ~UM_KERN_PAGE_MASK) + STUB_DATA); + ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA); return 0; } @@ -192,7 +195,7 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, { int ret; - if (proc_mm) { + if(proc_mm){ struct proc_mm_op map; int fd = mm_idp->u.mm_fd; @@ -208,10 +211,9 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, .offset= offset } } } ); CATCH_EINTR(ret = write(fd, &map, sizeof(map))); - if (ret != sizeof(map)) { + if(ret != sizeof(map)){ ret = -errno; - printk(UM_KERN_ERR "map : /proc/mm map failed, " - "err = %d\n", -ret); + printk("map : /proc/mm map failed, err = %d\n", -ret); } else ret = 0; } @@ -232,7 +234,7 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, { int ret; - if (proc_mm) { + if(proc_mm){ struct proc_mm_op unmap; int fd = mm_idp->u.mm_fd; @@ -243,10 +245,9 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, (unsigned long) addr, .len = len } } } ); CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); - if (ret != sizeof(unmap)) { + if(ret != sizeof(unmap)){ ret = -errno; - printk(UM_KERN_ERR "unmap - proc_mm write returned " - "%d\n", ret); + printk("unmap - proc_mm write returned %d\n", ret); } else ret = 0; } @@ -267,7 +268,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, struct proc_mm_op protect; int ret; - if (proc_mm) { + if(proc_mm){ int fd = mm_idp->u.mm_fd; protect = ((struct proc_mm_op) { .op = MM_MPROTECT, @@ -279,9 +280,9 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, .prot = prot } } } ); CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); - if (ret != sizeof(protect)) { + if(ret != sizeof(protect)){ ret = -errno; - printk(UM_KERN_ERR "protect failed, err = %d", -ret); + printk("protect failed, err = %d", -ret); } else ret = 0; } @@ -294,3 +295,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, return ret; } + +void before_mem_skas(unsigned long unused) +{ +} diff --git a/trunk/arch/um/os-Linux/skas/process.c b/trunk/arch/um/os-Linux/skas/process.c index d77c81d7068a..ba9af8d62055 100644 --- a/trunk/arch/um/os-Linux/skas/process.c +++ b/trunk/arch/um/os-Linux/skas/process.c @@ -1,38 +1,48 @@ /* - * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include +#include #include -#include #include -#include -#include -#include +#include +#include +#include "ptrace_user.h" #include -#include -#include "as-layout.h" -#include "chan_user.h" -#include "kern_constants.h" -#include "mem.h" +#include +#include +#include +#include +#include +#include "user.h" +#include "sysdep/ptrace.h" +#include "kern_util.h" +#include "skas.h" +#include "stub-data.h" +#include "mm_id.h" +#include "sysdep/sigcontext.h" +#include "sysdep/stub.h" #include "os.h" -#include "process.h" #include "proc_mm.h" -#include "ptrace_user.h" -#include "registers.h" -#include "skas.h" #include "skas_ptrace.h" -#include "user.h" -#include "sysdep/stub.h" +#include "chan_user.h" +#include "registers.h" +#include "mem.h" +#include "uml-config.h" +#include "process.h" +#include "longjmp.h" +#include "kern_constants.h" +#include "as-layout.h" int is_skas_winch(int pid, int fd, void *data) { - if (pid != getpgrp()) - return 0; + if(pid != os_getpgrp()) + return(0); register_winch_irq(-1, fd, -1, data, 0); - return 1; + return(1); } static int ptrace_dump_regs(int pid) @@ -40,12 +50,13 @@ static int ptrace_dump_regs(int pid) unsigned long regs[MAX_REG_NR]; int i; - if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) return -errno; - - printk(UM_KERN_ERR "Stub registers -\n"); - for (i = 0; i < ARRAY_SIZE(regs); i++) - printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); + else { + printk("Stub registers -\n"); + for(i = 0; i < ARRAY_SIZE(regs); i++) + printk("\t%d - %lx\n", i, regs[i]); + } return 0; } @@ -63,28 +74,27 @@ void wait_stub_done(int pid) { int n, status, err; - while (1) { + while(1){ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if ((n < 0) || !WIFSTOPPED(status)) + if((n < 0) || !WIFSTOPPED(status)) goto bad_wait; - if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) + if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) break; err = ptrace(PTRACE_CONT, pid, 0, 0); - if (err) + if(err) panic("wait_stub_done : continue failed, errno = %d\n", errno); } - if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) + if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) return; bad_wait: err = ptrace_dump_regs(pid); - if (err) - printk(UM_KERN_ERR "Failed to get registers from stub, " - "errno = %d\n", -err); + if(err) + printk("Failed to get registers from stub, errno = %d\n", -err); panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); } @@ -95,9 +105,9 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) { int err; - if (ptrace_faultinfo) { + if(ptrace_faultinfo){ err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if (err) + if(err) panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " "errno = %d\n", errno); @@ -109,57 +119,52 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) } else { err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); - if (err) + if(err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* - * faultinfo is prepared by the stub-segv-handler at start of + /* faultinfo is prepared by the stub-segv-handler at start of * the stub stack page. We just have to copy it. */ memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); } } -static void handle_segv(int pid, struct uml_pt_regs * regs) +static void handle_segv(int pid, union uml_pt_regs * regs) { - get_skas_faultinfo(pid, ®s->faultinfo); - segv(regs->faultinfo, 0, 1, NULL); + get_skas_faultinfo(pid, ®s->skas.faultinfo); + segv(regs->skas.faultinfo, 0, 1, NULL); } -/* - * To use the same value of using_sysemu as the caller, ask it that value - * (in local_using_sysemu - */ -static void handle_trap(int pid, struct uml_pt_regs *regs, - int local_using_sysemu) +/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ +static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) { int err, status; /* Mark this as a syscall */ - UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); + UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); if (!local_using_sysemu) { err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); - if (err < 0) - panic("handle_trap - nullifying syscall failed, " - "errno = %d\n", errno); + if(err < 0) + panic("handle_trap - nullifying syscall failed errno = %d\n", + errno); err = ptrace(PTRACE_SYSCALL, pid, 0, 0); - if (err < 0) - panic("handle_trap - continuing to end of syscall " - "failed, errno = %d\n", errno); + if(err < 0) + panic("handle_trap - continuing to end of syscall failed, " + "errno = %d\n", errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if ((err < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGTRAP + 0x80)) { + if((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)){ err = ptrace_dump_regs(pid); - if (err) - printk(UM_KERN_ERR "Failed to get registers " - "from process, errno = %d\n", -err); + if(err) + printk("Failed to get registers from process, " + "errno = %d\n", -err); panic("handle_trap - failed to wait at end of syscall, " "errno = %d, status = %d\n", errno, status); } @@ -177,64 +182,63 @@ static int userspace_tramp(void *stack) ptrace(PTRACE_TRACEME, 0, 0, 0); - signal(SIGTERM, SIG_DFL); - err = set_interval(); - if (err) + init_new_thread_signals(); + err = set_interval(1); + if(err) panic("userspace_tramp - setting timer failed, errno = %d\n", err); - if (!proc_mm) { - /* - * This has a pte, but it can't be mapped in with the usual + if(!proc_mm){ + /* This has a pte, but it can't be mapped in with the usual * tlb_flush mechanism because this is part of that mechanism */ int fd; - unsigned long long offset; + __u64 offset; fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); - addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, + addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE, PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); - if (addr == MAP_FAILED) { - printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " - "errno = %d\n", STUB_CODE, errno); + if(addr == MAP_FAILED){ + printk("mapping mmap stub failed, errno = %d\n", + errno); exit(1); } - if (stack != NULL) { + if(stack != NULL){ fd = phys_mapping(to_phys(stack), &offset); - addr = mmap((void *) STUB_DATA, + addr = mmap((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); - if (addr == MAP_FAILED) { - printk(UM_KERN_ERR "mapping segfault stack " - "at 0x%lx failed, errno = %d\n", - STUB_DATA, errno); + if(addr == MAP_FAILED){ + printk("mapping segfault stack failed, " + "errno = %d\n", errno); exit(1); } } } - if (!ptrace_faultinfo && (stack != NULL)) { + if(!ptrace_faultinfo && (stack != NULL)){ struct sigaction sa; - unsigned long v = STUB_CODE + + unsigned long v = UML_CONFIG_STUB_CODE + (unsigned long) stub_segv_handler - (unsigned long) &__syscall_stub_start; - set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); + set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGIO); sigaddset(&sa.sa_mask, SIGWINCH); + sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGVTALRM); sigaddset(&sa.sa_mask, SIGUSR1); sa.sa_flags = SA_ONSTACK; sa.sa_handler = (void *) v; sa.sa_restorer = NULL; - if (sigaction(SIGSEGV, &sa, NULL) < 0) + if(sigaction(SIGSEGV, &sa, NULL) < 0) panic("userspace_tramp - setting SIGSEGV handler " "failed - errno = %d\n", errno); } - kill(os_getpid(), SIGSTOP); - return 0; + os_stop_process(os_getpid()); + return(0); } /* Each element set once, and only accessed by a single processor anyway */ @@ -251,55 +255,44 @@ int start_userspace(unsigned long stub_stack) stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (stack == MAP_FAILED) + if(stack == MAP_FAILED) panic("start_userspace : mmap failed, errno = %d", errno); sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES | SIGCHLD; - if (proc_mm) - flags |= CLONE_VM; - + if(proc_mm) flags |= CLONE_VM; pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); - if (pid < 0) + if(pid < 0) panic("start_userspace : clone failed, errno = %d", errno); do { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if (n < 0) + if(n < 0) panic("start_userspace : wait failed, errno = %d", errno); - } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); + } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); - if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) panic("start_userspace : expected SIGSTOP, got status = %d", status); - if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, - (void *) PTRACE_O_TRACESYSGOOD) < 0) - panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " - "errno = %d\n", errno); + if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) + panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", + errno); - if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) + if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - return pid; + return(pid); } -void userspace(struct uml_pt_regs *regs) +void userspace(union uml_pt_regs *regs) { - struct itimerval timer; - unsigned long long nsecs, now; int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; - if (getitimer(ITIMER_VIRTUAL, &timer)) - printk("Failed to get itimer, errno = %d\n", errno); - nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + - timer.it_value.tv_usec * UM_NSEC_PER_USEC; - nsecs += os_nsecs(); - - while (1) { + while(1){ restore_registers(pid, regs); /* Now we set local_using_sysemu to be used for one loop */ @@ -309,28 +302,26 @@ void userspace(struct uml_pt_regs *regs) singlestepping(NULL)); err = ptrace(op, pid, 0, 0); - if (err) + if(err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", pid, op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if (err < 0) + if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); - regs->is_user = 1; + regs->skas.is_user = 1; save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ - if (WIFSTOPPED(status)) { + if(WIFSTOPPED(status)){ int sig = WSTOPSIG(status); - switch(sig) { + switch(sig){ case SIGSEGV: - if (PTRACE_FULL_FAULTINFO || - !ptrace_faultinfo) { - get_skas_faultinfo(pid, - ®s->faultinfo); + if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){ + get_skas_faultinfo(pid, ®s->skas.faultinfo); (*sig_info[SIGSEGV])(SIGSEGV, regs); } else handle_segv(pid, regs); @@ -341,20 +332,8 @@ void userspace(struct uml_pt_regs *regs) case SIGTRAP: relay_signal(SIGTRAP, regs); break; - case SIGVTALRM: - now = os_nsecs(); - if(now < nsecs) - break; - block_signals(); - (*sig_info[sig])(sig, regs); - unblock_signals(); - nsecs = timer.it_value.tv_sec * - UM_NSEC_PER_SEC + - timer.it_value.tv_usec * - UM_NSEC_PER_USEC; - nsecs += os_nsecs(); - break; case SIGIO: + case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: @@ -364,29 +343,30 @@ void userspace(struct uml_pt_regs *regs) unblock_signals(); break; default: - printk(UM_KERN_ERR "userspace - child stopped " - "with signal %d\n", sig); + printk("userspace - child stopped with signal " + "%d\n", sig); } pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ - if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) - PT_SYSCALL_NR(regs->gp) = -1; + if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) + PT_SYSCALL_NR(regs->skas.regs) = -1; } } } static unsigned long thread_regs[MAX_REG_NR]; +static unsigned long thread_fp_regs[HOST_FP_SIZE]; static int __init init_thread_regs(void) { - get_safe_registers(thread_regs); + get_safe_registers(thread_regs, thread_fp_regs); /* Set parent's instruction pointer to start of clone-stub */ - thread_regs[REGS_IP_INDEX] = STUB_CODE + + thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) &__syscall_stub_start; - thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - + thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; @@ -398,53 +378,53 @@ __initcall(init_thread_regs); int copy_context_skas0(unsigned long new_stack, int pid) { - struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ }; int err; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; struct stub_data *child_data = (struct stub_data *) new_stack; - unsigned long long new_offset; + __u64 new_offset; int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); - /* - * prepare offset and fd of child's stack as argument for parent's + /* prepare offset and fd of child's stack as argument for parent's * and child's mmap2 calls */ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), .fd = new_fd, .timer = ((struct itimerval) - { .it_value = tv, - .it_interval = tv }) }); - + { { 0, 1000000 / hz() }, + { 0, 1000000 / hz() }})}); err = ptrace_setregs(pid, thread_regs); - if (err < 0) + if(err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, -err); + err = ptrace_setfpregs(pid, thread_fp_regs); + if(err < 0) + panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " + "pid = %d, errno = %d\n", pid, -err); + /* set a well known return code for detection of child write failure */ child_data->err = 12345678; - /* - * Wait, until parent has finished its work: read child's pid from + /* Wait, until parent has finished its work: read child's pid from * parent's stack, and check, if bad result. */ err = ptrace(PTRACE_CONT, pid, 0, 0); - if (err) + if(err) panic("Failed to continue new process, pid = %d, " "errno = %d\n", pid, errno); wait_stub_done(pid); pid = data->err; - if (pid < 0) + if(pid < 0) panic("copy_context_skas0 - stub-parent reports error %d\n", -pid); - /* - * Wait, until child has finished too: read child's result from + /* Wait, until child has finished too: read child's result from * child's stack and check it. */ wait_stub_done(pid); - if (child_data->err != STUB_DATA) + if (child_data->err != UML_CONFIG_STUB_DATA) panic("copy_context_skas0 - stub-child reports error %ld\n", child_data->err); @@ -466,7 +446,7 @@ void map_stub_pages(int fd, unsigned long code, { struct proc_mm_op mmop; int n; - unsigned long long code_offset; + __u64 code_offset; int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), &code_offset); @@ -481,17 +461,16 @@ void map_stub_pages(int fd, unsigned long code, .offset = code_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if (n != sizeof(mmop)) { + if(n != sizeof(mmop)){ n = errno; - printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " - "offset = %llx\n", code, code_fd, - (unsigned long long) code_offset); + printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", + code, code_fd, (unsigned long long) code_offset); panic("map_stub_pages : /proc/mm map for code failed, " "err = %d\n", n); } - if (stack) { - unsigned long long map_offset; + if ( stack ) { + __u64 map_offset; int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, @@ -505,7 +484,7 @@ void map_stub_pages(int fd, unsigned long code, .offset = map_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if (n != sizeof(mmop)) + if(n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for data failed, " "err = %d\n", errno); } @@ -525,7 +504,7 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) void switch_threads(jmp_buf *me, jmp_buf *you) { - if (UML_SETJMP(me) == 0) + if(UML_SETJMP(me) == 0) UML_LONGJMP(you, 1); } @@ -541,7 +520,8 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, + SIGVTALRM, -1); /* * Can't use UML_SETJMP or UML_LONGJMP here because they save @@ -552,7 +532,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) * after returning to the jumper. */ n = setjmp(initial_jmpbuf); - switch(n) { + switch(n){ case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + @@ -564,10 +544,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) break; case INIT_JMP_HALT: kmalloc_ok = 0; - return 0; + return(0); case INIT_JMP_REBOOT: kmalloc_ok = 0; - return 1; + return(1); default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } @@ -583,7 +563,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) cb_back = &here; block_signals(); - if (UML_SETJMP(&here) == 0) + if(UML_SETJMP(&here) == 0) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); @@ -604,16 +584,16 @@ void reboot_skas(void) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); } -void __switch_mm(struct mm_id *mm_idp) +void switch_mm_skas(struct mm_id *mm_idp) { int err; - /* FIXME: need cpu pid in __switch_mm */ - if (proc_mm) { + /* FIXME: need cpu pid in switch_mm_skas */ + if(proc_mm){ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); - if (err) - panic("__switch_mm - PTRACE_SWITCH_MM failed, " + if(err) + panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " "errno = %d\n", errno); } else userspace_pid[0] = mm_idp->u.pid; diff --git a/trunk/arch/um/os-Linux/skas/trap.c b/trunk/arch/um/os-Linux/skas/trap.c index 3b1b9244f468..3b600c2e63b8 100644 --- a/trunk/arch/um/os-Linux/skas/trap.c +++ b/trunk/arch/um/os-Linux/skas/trap.c @@ -1,43 +1,37 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#if 0 +#include +#include #include "kern_util.h" +#include "as-layout.h" +#include "task.h" +#include "sigcontext.h" #include "skas.h" #include "ptrace_user.h" -#include "sysdep/ptrace_user.h" -#endif - -#include -#include #include "sysdep/ptrace.h" -#include "kern_constants.h" -#include "as-layout.h" +#include "sysdep/ptrace_user.h" #include "os.h" -#include "sigcontext.h" -#include "task.h" -static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; +static union uml_pt_regs ksig_regs[UM_NR_CPUS]; void sig_handler_common_skas(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; - struct uml_pt_regs *r; - void (*handler)(int, struct uml_pt_regs *); + union uml_pt_regs *r; + void (*handler)(int, union uml_pt_regs *); int save_user, save_errno = errno; - /* - * This is done because to allow SIGSEGV to be delivered inside a SEGV + /* This is done because to allow SIGSEGV to be delivered inside a SEGV * handler. This can happen in copy_user, and if SEGV is disabled, * the process will die. * XXX Figure out why this is better than SA_NODEFER */ - if (sig == SIGSEGV) { + if(sig == SIGSEGV) { change_sig(SIGSEGV, 1); - /* - * For segfaults, we want the data from the + /* For segfaults, we want the data from the * sigcontext. In this case, we don't want to mangle * the process registers, so use a static set of * registers. For other signals, the process @@ -48,22 +42,25 @@ void sig_handler_common_skas(int sig, void *sc_ptr) } else r = TASK_REGS(get_current()); - save_user = r->is_user; - r->is_user = 0; - if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || - (sig == SIGILL) || (sig == SIGTRAP)) - GET_FAULTINFO_FROM_SC(r->faultinfo, sc); + save_user = r->skas.is_user; + r->skas.is_user = 0; + if ( sig == SIGFPE || sig == SIGSEGV || + sig == SIGBUS || sig == SIGILL || + sig == SIGTRAP ) { + GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc); + } change_sig(SIGUSR1, 1); handler = sig_info[sig]; - /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) + /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ + if (sig != SIGIO && sig != SIGWINCH && + sig != SIGVTALRM && sig != SIGALRM) unblock_signals(); handler(sig, r); errno = save_errno; - r->is_user = save_user; + r->skas.is_user = save_user; } diff --git a/trunk/arch/um/os-Linux/start_up.c b/trunk/arch/um/os-Linux/start_up.c index 7b81f6c08a5e..46f613975c19 100644 --- a/trunk/arch/um/os-Linux/start_up.c +++ b/trunk/arch/um/os-Linux/start_up.c @@ -1,65 +1,75 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include #include -#include +#include #include +#include +#include #include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include "kern_util.h" +#include "user.h" +#include "signal_kern.h" +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" +#include "irq_user.h" +#include "ptrace_user.h" +#include "mem_user.h" #include "init.h" -#include "kern_constants.h" #include "os.h" -#include "mem_user.h" -#include "ptrace_user.h" -#include "registers.h" +#include "uml-config.h" +#include "choose-mode.h" +#include "mode.h" +#include "tempfile.h" +#include "kern_constants.h" + +#ifdef UML_CONFIG_MODE_SKAS +#include "skas.h" #include "skas_ptrace.h" +#include "registers.h" +#endif -static int ptrace_child(void) +static int ptrace_child(void *arg) { int ret; - /* Calling os_getpid because some libcs cached getpid incorrectly */ int pid = os_getpid(), ppid = getppid(); int sc_result; change_sig(SIGWINCH, 0); - if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { + if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ perror("ptrace"); - kill(pid, SIGKILL); + os_kill_process(pid, 0); } kill(pid, SIGSTOP); - /* - * This syscall will be intercepted by the parent. Don't call more than - * once, please. - */ + /*This syscall will be intercepted by the parent. Don't call more than + * once, please.*/ sc_result = os_getpid(); if (sc_result == pid) - /* Nothing modified by the parent, we are running normally. */ - ret = 1; + ret = 1; /*Nothing modified by the parent, we are running + normally.*/ else if (sc_result == ppid) - /* - * Expected in check_ptrace and check_sysemu when they succeed - * in modifying the stack frame - */ - ret = 0; + ret = 0; /*Expected in check_ptrace and check_sysemu when they + succeed in modifying the stack frame*/ else - /* Serious trouble! This could be caused by a bug in host 2.6 - * SKAS3/2.6 patch before release -V6, together with a bug in - * the UML code itself. - */ - ret = 2; + ret = 2; /*Serious trouble! This could be caused by a bug in + host 2.6 SKAS3/2.6 patch before release -V6, together + with a bug in the UML code itself.*/ _exit(ret); } @@ -91,23 +101,29 @@ static void non_fatal(char *fmt, ...) fflush(stdout); } -static int start_ptraced_child(void) +static int start_ptraced_child(void **stack_out) { + void *stack; + unsigned long sp; int pid, n, status; - pid = fork(); - if (pid == 0) - ptrace_child(); - else if (pid < 0) - fatal_perror("start_ptraced_child : fork failed"); - + stack = mmap(NULL, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(stack == MAP_FAILED) + fatal_perror("check_ptrace : mmap failed"); + sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); + pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); + if(pid < 0) + fatal_perror("start_ptraced_child : clone failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if (n < 0) - fatal_perror("check_ptrace : waitpid failed"); - if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if(n < 0) + fatal_perror("check_ptrace : clone failed"); + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) fatal("check_ptrace : expected SIGSTOP, got status = %d", status); + *stack_out = stack; return pid; } @@ -117,14 +133,15 @@ static int start_ptraced_child(void) * So only for SYSEMU features we test mustpanic, while normal host features * must work anyway! */ -static int stop_ptraced_child(int pid, int exitcode, int mustexit) +static int stop_ptraced_child(int pid, void *stack, int exitcode, + int mustexit) { int status, n, ret = 0; - if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) + if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) fatal_perror("stop_ptraced_child : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, 0)); - if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { + if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); if (exit_with == 2) non_fatal("check_ptrace : child exited with status 2. " @@ -137,6 +154,8 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) ret = -1; } + if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) + fatal_perror("check_ptrace : munmap failed"); return ret; } @@ -188,39 +207,40 @@ __uml_setup("nosysemu", nosysemu_cmd_param, static void __init check_sysemu(void) { + void *stack; unsigned long regs[MAX_REG_NR]; int pid, n, status, count=0; non_fatal("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); - if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) + if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if (n < 0) fatal_perror("check_sysemu : wait failed"); - if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) fatal("check_sysemu : expected SIGTRAP, got status = %d", status); - if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) fatal_perror("check_sysemu : PTRACE_GETREGS failed"); - if (PT_SYSCALL_NR(regs) != __NR_getpid) { + if(PT_SYSCALL_NR(regs) != __NR_getpid){ non_fatal("check_sysemu got system call number %d, " "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); goto fail; } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if (n < 0) { + if(n < 0){ non_fatal("check_sysemu : failed to modify system call " "return"); goto fail; } - if (stop_ptraced_child(pid, 0, 0) < 0) + if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 1; @@ -228,90 +248,90 @@ static void __init check_sysemu(void) set_using_sysemu(!force_sysemu_disabled); non_fatal("Checking advanced syscall emulation patch for ptrace..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); - if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while (1) { + while(1){ count++; - if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) + if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if (n < 0) + if(n < 0) fatal_perror("check_ptrace : wait failed"); - if (WIFSTOPPED(status) && - (WSTOPSIG(status) == (SIGTRAP|0x80))) { + if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ if (!count) fatal("check_ptrace : SYSEMU_SINGLESTEP " "doesn't singlestep"); n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if (n < 0) + if(n < 0) fatal_perror("check_sysemu : failed to modify " "system call return"); break; } - else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) + else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; else fatal("check_ptrace : expected SIGTRAP or " "(SIGTRAP | 0x80), got status = %d", status); } - if (stop_ptraced_child(pid, 0, 0) < 0) + if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 2; non_fatal("OK\n"); - if (!force_sysemu_disabled) + if ( !force_sysemu_disabled ) set_using_sysemu(sysemu_supported); return; fail: - stop_ptraced_child(pid, 1, 0); + stop_ptraced_child(pid, stack, 1, 0); fail_stopped: non_fatal("missing\n"); } static void __init check_ptrace(void) { + void *stack; int pid, syscall, n, status; non_fatal("Checking that ptrace can change system call numbers..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); - if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while (1) { - if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) + while(1){ + if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) fatal_perror("check_ptrace : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if (n < 0) + if(n < 0) fatal_perror("check_ptrace : wait failed"); - if (!WIFSTOPPED(status) || + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP | 0x80))) fatal("check_ptrace : expected (SIGTRAP|0x80), " "got status = %d", status); syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0); - if (syscall == __NR_getpid) { + if(syscall == __NR_getpid){ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getppid); - if (n < 0) + if(n < 0) fatal_perror("check_ptrace : failed to modify " "system call"); break; } } - stop_ptraced_child(pid, 0, 1); + stop_ptraced_child(pid, stack, 0, 1); non_fatal("OK\n"); check_sysemu(); } @@ -323,18 +343,18 @@ static void __init check_coredump_limit(void) struct rlimit lim; int err = getrlimit(RLIMIT_CORE, &lim); - if (err) { + if(err){ perror("Getting core dump limit"); return; } printf("Core dump limits :\n\tsoft - "); - if (lim.rlim_cur == RLIM_INFINITY) + if(lim.rlim_cur == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_cur); printf("\thard - "); - if (lim.rlim_max == RLIM_INFINITY) + if(lim.rlim_max == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_max); } @@ -388,18 +408,20 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param, " To support PTRACE_LDT, the host needs to be patched using\n" " the current skas3 patch.\n\n"); +#ifdef UML_CONFIG_MODE_SKAS static inline void check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; + void *stack; int pid, n; non_fatal(" - PTRACE_FAULTINFO..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { ptrace_faultinfo = 0; - if (errno == EIO) + if(errno == EIO) non_fatal("not found\n"); else perror("not found"); @@ -412,12 +434,13 @@ static inline void check_skas3_ptrace_faultinfo(void) } init_registers(pid); - stop_ptraced_child(pid, 1, 1); + stop_ptraced_child(pid, stack, 1, 1); } static inline void check_skas3_ptrace_ldt(void) { #ifdef PTRACE_LDT + void *stack; int pid, n; unsigned char ldtbuf[40]; struct ptrace_ldt ldt_op = (struct ptrace_ldt) { @@ -426,11 +449,11 @@ static inline void check_skas3_ptrace_ldt(void) .bytecount = sizeof(ldtbuf)}; non_fatal(" - PTRACE_LDT..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); if (n < 0) { - if (errno == EIO) + if(errno == EIO) non_fatal("not found\n"); else { perror("not found"); @@ -438,13 +461,13 @@ static inline void check_skas3_ptrace_ldt(void) ptrace_ldt = 0; } else { - if (ptrace_ldt) + if(ptrace_ldt) non_fatal("found\n"); else non_fatal("found, but use is disabled\n"); } - stop_ptraced_child(pid, 1, 1); + stop_ptraced_child(pid, stack, 1, 1); #else /* PTRACE_LDT might be disabled via cmdline option. * We want to override this, else we might use the stub @@ -461,9 +484,12 @@ static inline void check_skas3_proc_mm(void) proc_mm = 0; perror("not found"); } - else if (!proc_mm) - non_fatal("found but disabled on command line\n"); - else non_fatal("found\n"); + else { + if (!proc_mm) + non_fatal("found but disabled on command line\n"); + else + non_fatal("found\n"); + } } int can_do_skas(void) @@ -474,11 +500,17 @@ int can_do_skas(void) check_skas3_ptrace_faultinfo(); check_skas3_ptrace_ldt(); - if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) + if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) skas_needs_stub = 1; return 1; } +#else +int can_do_skas(void) +{ + return 0; +} +#endif int __init parse_iomem(char *str, int *add) { @@ -489,25 +521,25 @@ int __init parse_iomem(char *str, int *add) driver = str; file = strchr(str,','); - if (file == NULL) { + if(file == NULL){ printf("parse_iomem : failed to parse iomem\n"); goto out; } *file = '\0'; file++; fd = open(file, O_RDWR, 0); - if (fd < 0) { - perror("parse_iomem - Couldn't open io file"); + if(fd < 0){ + os_print_error(fd, "parse_iomem - Couldn't open io file"); goto out; } - if (fstat64(fd, &buf) < 0) { + if(fstat64(fd, &buf) < 0){ perror("parse_iomem - cannot stat_fd file"); goto out_close; } new = malloc(sizeof(*new)); - if (new == NULL) { + if(new == NULL){ perror("Couldn't allocate iomem_region struct"); goto out_close; } diff --git a/trunk/arch/um/os-Linux/sys-i386/Makefile b/trunk/arch/um/os-Linux/sys-i386/Makefile index a841262c594a..37806621b25d 100644 --- a/trunk/arch/um/os-Linux/sys-i386/Makefile +++ b/trunk/arch/um/os-Linux/sys-i386/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # -obj-y = registers.o signal.o tls.o +obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o USER_OBJS := $(obj-y) diff --git a/trunk/arch/um/os-Linux/sys-i386/registers.c b/trunk/arch/um/os-Linux/sys-i386/registers.c index d1997ca76e5c..84b44f9cd42a 100644 --- a/trunk/arch/um/os-Linux/sys-i386/registers.c +++ b/trunk/arch/um/os-Linux/sys-i386/registers.c @@ -1,73 +1,144 @@ /* * Copyright (C) 2004 PathScale, Inc - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include -#include "kern_constants.h" +#include +#include "sysdep/ptrace_user.h" +#include "sysdep/ptrace.h" +#include "uml-config.h" +#include "skas_ptregs.h" +#include "registers.h" #include "longjmp.h" #include "user.h" -#include "sysdep/ptrace_user.h" +/* These are set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[MAX_REG_NR]; +static unsigned long exec_fp_regs[HOST_FP_SIZE]; +static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; +static int have_fpx_regs = 1; + +void init_thread_registers(union uml_pt_regs *to) +{ + memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); + memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); + if(have_fpx_regs) + memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); +} + +/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs + * to pass in a sufficiently large buffer + */ int save_fp_registers(int pid, unsigned long *fp_regs) { - if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) + if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } int restore_fp_registers(int pid, unsigned long *fp_regs) { - if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) + if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } -int save_fpx_registers(int pid, unsigned long *fp_regs) +static int move_registers(int pid, int int_op, union uml_pt_regs *regs, + int fp_op, unsigned long *fp_regs) { - if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) return -errno; - return 0; -} -int restore_fpx_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) + if(ptrace(fp_op, pid, 0, fp_regs) < 0) return -errno; + return 0; } -unsigned long get_thread_reg(int reg, jmp_buf *buf) +void save_registers(int pid, union uml_pt_regs *regs) { - switch (reg) { - case EIP: - return buf[0]->__eip; - case UESP: - return buf[0]->__esp; - case EBP: - return buf[0]->__ebp; - default: - printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", - reg); - return 0; + unsigned long *fp_regs; + int err, fp_op; + + if(have_fpx_regs){ + fp_op = PTRACE_GETFPXREGS; + fp_regs = regs->skas.xfp; + } + else { + fp_op = PTRACE_GETFPREGS; + fp_regs = regs->skas.fp; } + + err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); + if(err) + panic("save_registers - saving registers failed, errno = %d\n", + -err); } -int have_fpx_regs = 1; +void restore_registers(int pid, union uml_pt_regs *regs) +{ + unsigned long *fp_regs; + int err, fp_op; -void arch_init_registers(int pid) + if(have_fpx_regs){ + fp_op = PTRACE_SETFPXREGS; + fp_regs = regs->skas.xfp; + } + else { + fp_op = PTRACE_SETFPREGS; + fp_regs = regs->skas.fp; + } + + err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); + if(err) + panic("restore_registers - saving registers failed, " + "errno = %d\n", -err); +} + +void init_registers(int pid) { - unsigned long fpx_regs[HOST_XFP_SIZE]; int err; - err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); + memset(exec_regs, 0, sizeof(exec_regs)); + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if(err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", + errno); + + errno = 0; + err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); if(!err) return; - if(errno != EIO) panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", errno); have_fpx_regs = 0; + + err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); + if(err) + panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", + errno); +} + +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) +{ + memcpy(regs, exec_regs, sizeof(exec_regs)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); +} + +unsigned long get_thread_reg(int reg, jmp_buf *buf) +{ + switch(reg){ + case EIP: return buf[0]->__eip; + case UESP: return buf[0]->__esp; + case EBP: return buf[0]->__ebp; + default: + printk("get_thread_regs - unknown register %d\n", reg); + return 0; + } } diff --git a/trunk/arch/um/os-Linux/sys-x86_64/Makefile b/trunk/arch/um/os-Linux/sys-x86_64/Makefile index a42a4ef02e1e..7955e061a678 100644 --- a/trunk/arch/um/os-Linux/sys-x86_64/Makefile +++ b/trunk/arch/um/os-Linux/sys-x86_64/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # -obj-y = registers.o prctl.o signal.o +obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o USER_OBJS := $(obj-y) diff --git a/trunk/arch/um/os-Linux/sys-x86_64/registers.c b/trunk/arch/um/os-Linux/sys-x86_64/registers.c index 9bfa789992de..9467315b8059 100644 --- a/trunk/arch/um/os-Linux/sys-x86_64/registers.c +++ b/trunk/arch/um/os-Linux/sys-x86_64/registers.c @@ -1,15 +1,23 @@ /* - * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2004 PathScale, Inc * Licensed under the GPL */ #include #include -#define __FRAME_OFFSETS -#include +#include +#include "ptrace_user.h" +#include "uml-config.h" +#include "skas_ptregs.h" +#include "registers.h" #include "longjmp.h" #include "user.h" +/* These are set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[MAX_REG_NR]; +static unsigned long exec_fp_regs[HOST_FP_SIZE]; + int save_fp_registers(int pid, unsigned long *fp_regs) { if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) @@ -24,6 +32,67 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) return 0; } +void init_thread_registers(union uml_pt_regs *to) +{ + memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); + memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); +} + +static int move_registers(int pid, int int_op, int fp_op, + union uml_pt_regs *regs) +{ + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) + return -errno; + + if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) + return -errno; + + return 0; +} + +void save_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); + if(err) + panic("save_registers - saving registers failed, errno = %d\n", + -err); +} + +void restore_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); + if(err) + panic("restore_registers - saving registers failed, " + "errno = %d\n", -err); +} + +void init_registers(int pid) +{ + int err; + + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if(err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", + errno); + + err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); + if(err) + panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", + errno); +} + +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) +{ + memcpy(regs, exec_regs, sizeof(exec_regs)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); +} + unsigned long get_thread_reg(int reg, jmp_buf *buf) { switch(reg){ diff --git a/trunk/arch/um/os-Linux/time.c b/trunk/arch/um/os-Linux/time.c index e34e1effe0f5..5de169b168f6 100644 --- a/trunk/arch/um/os-Linux/time.c +++ b/trunk/arch/um/os-Linux/time.c @@ -1,86 +1,101 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include -#include -#include +#include +#include +#include #include #include +#include +#include +#include "kern_util.h" +#include "user.h" +#include "process.h" #include "kern_constants.h" #include "os.h" -#include "user.h" +#include "uml-config.h" -int set_interval(void) +int set_interval(int is_virtual) { - int usec = UM_USEC_PER_SEC / UM_HZ; + int usec = 1000000/hz(); + int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL; struct itimerval interval = ((struct itimerval) { { 0, usec }, { 0, usec } }); - if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) + if(setitimer(timer_type, &interval, NULL) == -1) return -errno; return 0; } -int timer_one_shot(int ticks) +#ifdef UML_CONFIG_MODE_TT +void enable_timer(void) { - unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ; - unsigned long sec = usec / UM_USEC_PER_SEC; - struct itimerval interval; - - usec %= UM_USEC_PER_SEC; - interval = ((struct itimerval) { { 0, 0 }, { sec, usec } }); - - if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) - return -errno; - - return 0; + set_interval(1); } +#endif -/** - * timeval_to_ns - Convert timeval to nanoseconds - * @ts: pointer to the timeval variable to be converted - * - * Returns the scalar nanosecond representation of the timeval - * parameter. - * - * Ripped from linux/time.h because it's a kernel header, and thus - * unusable from here. - */ -static inline long long timeval_to_ns(const struct timeval *tv) +void disable_timer(void) { - return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + - tv->tv_usec * UM_NSEC_PER_USEC; + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); + /* If there are signals already queued, after unblocking ignore them */ + signal(SIGALRM, SIG_IGN); + signal(SIGVTALRM, SIG_IGN); } -long long disable_timer(void) +void switch_timers(int to_real) { - struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, + { 0, 1000000/hz() }}); + int old, new; + + if(to_real){ + old = ITIMER_VIRTUAL; + new = ITIMER_REAL; + } + else { + old = ITIMER_REAL; + new = ITIMER_VIRTUAL; + } + + if((setitimer(old, &disable, NULL) < 0) || + (setitimer(new, &enable, NULL))) + printk("switch_timers - setitimer failed, errno = %d\n", + errno); +} - if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0) - printk(UM_KERN_ERR "disable_timer - setitimer failed, " - "errno = %d\n", errno); +#ifdef UML_CONFIG_MODE_TT +void uml_idle_timer(void) +{ + if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) + panic("Couldn't unset SIGVTALRM handler"); - return timeval_to_ns(&time.it_value); + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + set_interval(0); } +#endif -long long os_nsecs(void) +unsigned long long os_nsecs(void) { struct timeval tv; gettimeofday(&tv, NULL); - return timeval_to_ns(&tv); + return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); } -extern void alarm_handler(int sig, struct sigcontext *sc); - -void idle_sleep(unsigned long long nsecs) +void idle_sleep(int secs) { - struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC, - .tv_nsec = nsecs % UM_NSEC_PER_SEC }; + struct timespec ts; - if (nanosleep(&ts, &ts) == 0) - alarm_handler(SIGVTALRM, NULL); + ts.tv_sec = secs; + ts.tv_nsec = 0; + nanosleep(&ts, NULL); } diff --git a/trunk/arch/um/os-Linux/tls.c b/trunk/arch/um/os-Linux/tls.c index 73277801ef14..16215b990804 100644 --- a/trunk/arch/um/os-Linux/tls.c +++ b/trunk/arch/um/os-Linux/tls.c @@ -1,9 +1,18 @@ #include +#include #include +#include +#include #include "sysdep/tls.h" +#include "uml-config.h" /* TLS support - we basically rely on the host's one.*/ +/* In TT mode, this should be called only by the tracing thread, and makes sense + * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. + * + */ + #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 25 #endif @@ -23,6 +32,8 @@ int os_set_thread_area(user_desc_t *info, int pid) return ret; } +#ifdef UML_CONFIG_MODE_SKAS + int os_get_thread_area(user_desc_t *info, int pid) { int ret; @@ -33,3 +44,32 @@ int os_get_thread_area(user_desc_t *info, int pid) ret = -errno; return ret; } + +#endif + +#ifdef UML_CONFIG_MODE_TT +#include "linux/unistd.h" + +int do_set_thread_area_tt(user_desc_t *info) +{ + int ret; + + ret = syscall(__NR_set_thread_area,info); + if (ret < 0) { + ret = -errno; + } + return ret; +} + +int do_get_thread_area_tt(user_desc_t *info) +{ + int ret; + + ret = syscall(__NR_get_thread_area,info); + if (ret < 0) { + ret = -errno; + } + return ret; +} + +#endif /* UML_CONFIG_MODE_TT */ diff --git a/trunk/arch/um/os-Linux/trap.c b/trunk/arch/um/os-Linux/trap.c index 2a1c9843e32e..295da657931a 100644 --- a/trunk/arch/um/os-Linux/trap.c +++ b/trunk/arch/um/os-Linux/trap.c @@ -1,14 +1,22 @@ /* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include #include +#include "kern_util.h" #include "os.h" -#include "sysdep/ptrace.h" +#include "mode.h" +#include "longjmp.h" + +void usr2_handler(int sig, union uml_pt_regs *regs) +{ + CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); +} /* Initialized from linux_main() */ -void (*sig_info[NSIG])(int, struct uml_pt_regs *); +void (*sig_info[NSIG])(int, union uml_pt_regs *); void os_fill_handlinfo(struct kern_handlers h) { @@ -20,4 +28,13 @@ void os_fill_handlinfo(struct kern_handlers h) sig_info[SIGSEGV] = h.page_fault; sig_info[SIGIO] = h.sigio_handler; sig_info[SIGVTALRM] = h.timer_handler; + sig_info[SIGALRM] = h.timer_handler; + sig_info[SIGUSR2] = usr2_handler; +} + +void do_longjmp(void *b, int val) +{ + jmp_buf *buf = b; + + UML_LONGJMP(buf, val); } diff --git a/trunk/arch/um/os-Linux/tt.c b/trunk/arch/um/os-Linux/tt.c new file mode 100644 index 000000000000..bcf9359c4e9f --- /dev/null +++ b/trunk/arch/um/os-Linux/tt.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kern_util.h" +#include "user.h" +#include "signal_kern.h" +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" +#include "irq_user.h" +#include "ptrace_user.h" +#include "init.h" +#include "os.h" +#include "uml-config.h" +#include "choose-mode.h" +#include "mode.h" +#include "tempfile.h" +#include "kern_constants.h" + +int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, + int must_succeed) +{ + int err; + + err = os_protect_memory((void *) addr, len, r, w, x); + if(err < 0){ + if(must_succeed) + panic("protect failed, err = %d", -err); + else return(err); + } + return(0); +} + +void kill_child_dead(int pid) +{ + kill(pid, SIGKILL); + kill(pid, SIGCONT); + do { + int n; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + if (n > 0) + kill(pid, SIGCONT); + else + break; + } while(1); +} + +void stop(void) +{ + while(1) sleep(1000000); +} + +int wait_for_stop(int pid, int sig, int cont_type, void *relay) +{ + sigset_t *relay_signals = relay; + int status, ret; + + while(1){ + CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); + if((ret < 0) || + !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ + if(ret < 0){ + printk("wait failed, errno = %d\n", + errno); + } + else if(WIFEXITED(status)) + printk("process %d exited with status %d\n", + pid, WEXITSTATUS(status)); + else if(WIFSIGNALED(status)) + printk("process %d exited with signal %d\n", + pid, WTERMSIG(status)); + else if((WSTOPSIG(status) == SIGVTALRM) || + (WSTOPSIG(status) == SIGALRM) || + (WSTOPSIG(status) == SIGIO) || + (WSTOPSIG(status) == SIGPROF) || + (WSTOPSIG(status) == SIGCHLD) || + (WSTOPSIG(status) == SIGWINCH) || + (WSTOPSIG(status) == SIGINT)){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else if((relay_signals != NULL) && + sigismember(relay_signals, WSTOPSIG(status))){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else printk("process %d stopped with signal %d\n", + pid, WSTOPSIG(status)); + panic("wait_for_stop failed to wait for %d to stop " + "with %d\n", pid, sig); + } + return(status); + } +} + +void forward_ipi(int fd, int pid) +{ + int err; + + err = os_set_owner(fd, pid); + if(err < 0) + printk("forward_ipi: set_owner failed, fd = %d, me = %d, " + "target = %d, err = %d\n", fd, os_getpid(), pid, -err); +} + +/* + *------------------------- + * only for tt mode (will be deleted in future...) + *------------------------- + */ + +struct tramp { + int (*tramp)(void *); + void *tramp_data; + unsigned long temp_stack; + int flags; + int pid; +}; + +/* See above for why sigkill is here */ + +int sigkill = SIGKILL; + +int outer_tramp(void *arg) +{ + struct tramp *t; + int sig = sigkill; + + t = arg; + t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2, + t->flags, t->tramp_data); + if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); + kill(os_getpid(), sig); + _exit(0); +} + +int start_fork_tramp(void *thread_arg, unsigned long temp_stack, + int clone_flags, int (*tramp)(void *)) +{ + struct tramp arg; + unsigned long sp; + int new_pid, status, err; + + /* The trampoline will run on the temporary stack */ + sp = stack_sp(temp_stack); + + clone_flags |= CLONE_FILES | SIGCHLD; + + arg.tramp = tramp; + arg.tramp_data = thread_arg; + arg.temp_stack = temp_stack; + arg.flags = clone_flags; + + /* Start the process and wait for it to kill itself */ + new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); + if(new_pid < 0) + return(new_pid); + + CATCH_EINTR(err = waitpid(new_pid, &status, 0)); + if(err < 0) + panic("Waiting for outer trampoline failed - errno = %d", + errno); + + if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) + panic("outer trampoline didn't exit with SIGKILL, " + "status = %d", status); + + return(arg.pid); +} + +void forward_pending_sigio(int target) +{ + sigset_t sigs; + + if(sigpending(&sigs)) + panic("forward_pending_sigio : sigpending failed"); + if(sigismember(&sigs, SIGIO)) + kill(target, SIGIO); +} + diff --git a/trunk/arch/um/os-Linux/uaccess.c b/trunk/arch/um/os-Linux/uaccess.c index 8d27b6d1df91..bbb73a650370 100644 --- a/trunk/arch/um/os-Linux/uaccess.c +++ b/trunk/arch/um/os-Linux/uaccess.c @@ -8,7 +8,7 @@ #include "longjmp.h" unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher, + void **fault_addr, void **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out) { diff --git a/trunk/arch/um/os-Linux/umid.c b/trunk/arch/um/os-Linux/umid.c index 106fa8641553..b462863f7172 100644 --- a/trunk/arch/um/os-Linux/umid.c +++ b/trunk/arch/um/os-Linux/umid.c @@ -1,21 +1,17 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - #include +#include #include -#include +#include #include -#include #include -#include -#include +#include +#include #include +#include #include "init.h" -#include "kern_constants.h" #include "os.h" #include "user.h" +#include "mode.h" #define UML_DIR "~/.uml/" @@ -32,13 +28,13 @@ static int __init make_uml_dir(void) char dir[512] = { '\0' }; int len, err; - if (*uml_dir == '~') { + if(*uml_dir == '~'){ char *home = getenv("HOME"); err = -ENOENT; - if (home == NULL) { - printk(UM_KERN_ERR "make_uml_dir : no value in " - "environment for $HOME\n"); + if(home == NULL){ + printk("make_uml_dir : no value in environment for " + "$HOME\n"); goto err; } strlcpy(dir, home, sizeof(dir)); @@ -57,7 +53,7 @@ static int __init make_uml_dir(void) } strcpy(uml_dir, dir); - if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { + if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); err = -errno; goto err_free; @@ -74,8 +70,8 @@ static int __init make_uml_dir(void) /* * Unlinks the files contained in @dir and then removes @dir. * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We - * ignore ENOENT errors for anything (they happen, strangely enough - possibly - * due to races between multiple dying UML threads). + * ignore ENOENT errors for anything (they happen, strangely enough - possibly due + * to races between multiple dying UML threads). */ static int remove_files_and_dir(char *dir) { @@ -120,8 +116,7 @@ static int remove_files_and_dir(char *dir) return ret; } -/* - * This says that there isn't already a user of the specified directory even if +/* This says that there isn't already a user of the specified directory even if * there are errors during the checking. This is because if these errors * happen, the directory is unusable by the pre-existing UML, so we might as * well take it over. This could happen either by @@ -139,45 +134,44 @@ static inline int is_umdir_used(char *dir) int dead, fd, p, n, err; n = snprintf(file, sizeof(file), "%s/pid", dir); - if (n >= sizeof(file)) { - printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); + if(n >= sizeof(file)){ + printk("is_umdir_used - pid filename too long\n"); err = -E2BIG; goto out; } dead = 0; fd = open(file, O_RDONLY); - if (fd < 0) { + if(fd < 0) { fd = -errno; - if (fd != -ENOENT) { - printk(UM_KERN_ERR "is_umdir_used : couldn't open pid " - "file '%s', err = %d\n", file, -fd); + if(fd != -ENOENT){ + printk("is_umdir_used : couldn't open pid file '%s', " + "err = %d\n", file, -fd); } goto out; } err = 0; n = read(fd, pid, sizeof(pid)); - if (n < 0) { - printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " - "'%s', err = %d\n", file, errno); + if(n < 0){ + printk("is_umdir_used : couldn't read pid file '%s', " + "err = %d\n", file, errno); goto out_close; - } else if (n == 0) { - printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " - "'%s', 0-byte read\n", file); + } else if(n == 0){ + printk("is_umdir_used : couldn't read pid file '%s', " + "0-byte read\n", file); goto out_close; } p = strtoul(pid, &end, 0); - if (end == pid) { - printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file " - "'%s', errno = %d\n", file, errno); + if(end == pid){ + printk("is_umdir_used : couldn't parse pid file '%s', " + "errno = %d\n", file, errno); goto out_close; } - if ((kill(p, 0) == 0) || (errno != ESRCH)) { - printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n", - umid, p); + if((kill(p, 0) == 0) || (errno != ESRCH)){ + printk("umid \"%s\" is already in use by pid %d\n", umid, p); return 1; } @@ -201,8 +195,8 @@ static int umdir_take_if_dead(char *dir) ret = remove_files_and_dir(dir); if (ret) { - printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir " - "failed with err = %d\n", ret); + printk("is_umdir_used - remove_files_and_dir failed with " + "err = %d\n", ret); } return ret; } @@ -213,28 +207,27 @@ static void __init create_pid_file(void) char pid[sizeof("nnnnn\0")]; int fd, n; - if (umid_file_name("pid", file, sizeof(file))) + if(umid_file_name("pid", file, sizeof(file))) return; fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " - "%s\n", file, strerror(errno)); + if(fd < 0){ + printk("Open of machine pid file \"%s\" failed: %s\n", + file, strerror(errno)); return; } snprintf(pid, sizeof(pid), "%d\n", getpid()); n = write(fd, pid, strlen(pid)); - if (n != strlen(pid)) - printk(UM_KERN_ERR "Write of pid file failed - err = %d\n", - errno); + if(n != strlen(pid)) + printk("Write of pid file failed - err = %d\n", errno); close(fd); } int __init set_umid(char *name) { - if (strlen(name) > UMID_LEN - 1) + if(strlen(name) > UMID_LEN - 1) return -E2BIG; strlcpy(umid, name, sizeof(umid)); @@ -250,18 +243,18 @@ int __init make_umid(void) int fd, err; char tmp[256]; - if (umid_setup) + if(umid_setup) return 0; make_uml_dir(); - if (*umid == '\0') { + if(*umid == '\0'){ strlcpy(tmp, uml_dir, sizeof(tmp)); strlcat(tmp, "XXXXXX", sizeof(tmp)); fd = mkstemp(tmp); - if (fd < 0) { - printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: " - "%s\n", tmp, strerror(errno)); + if(fd < 0){ + printk("make_umid - mkstemp(%s) failed: %s\n", + tmp, strerror(errno)); err = -errno; goto err; } @@ -270,12 +263,11 @@ int __init make_umid(void) set_umid(&tmp[strlen(uml_dir)]); - /* - * There's a nice tiny little race between this unlink and + /* There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ - if (unlink(tmp)) { + if(unlink(tmp)){ err = -errno; goto err; } @@ -283,9 +275,9 @@ int __init make_umid(void) snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); err = mkdir(tmp, 0777); - if (err < 0) { + if(err < 0){ err = -errno; - if (err != -EEXIST) + if(err != -EEXIST) goto err; if (umdir_take_if_dead(tmp) < 0) @@ -293,10 +285,9 @@ int __init make_umid(void) err = mkdir(tmp, 0777); } - if (err) { + if(err){ err = -errno; - printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid, - errno); + printk("Failed to create '%s' - err = %d\n", umid, -errno); goto err; } @@ -311,15 +302,14 @@ int __init make_umid(void) static int __init make_umid_init(void) { - if (!make_umid()) + if(!make_umid()) return 0; - /* - * If initializing with the given umid failed, then try again with + /* If initializing with the given umid failed, then try again with * a random one. */ - printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a " - "random umid\n", umid); + printk("Failed to initialize umid \"%s\", trying with a random umid\n", + umid); *umid = '\0'; make_umid(); @@ -333,12 +323,12 @@ int __init umid_file_name(char *name, char *buf, int len) int n, err; err = make_umid(); - if (err) + if(err) return err; n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); - if (n >= len) { - printk(UM_KERN_ERR "umid_file_name : buffer too short\n"); + if(n >= len){ + printk("umid_file_name : buffer too short\n"); return -E2BIG; } @@ -352,22 +342,21 @@ char *get_umid(void) static int __init set_uml_dir(char *name, int *add) { - if (*name == '\0') { + if(*name == '\0'){ printf("uml_dir can't be an empty string\n"); return 0; } - if (name[strlen(name) - 1] == '/') { + if(name[strlen(name) - 1] == '/'){ uml_dir = name; return 0; } uml_dir = malloc(strlen(name) + 2); - if (uml_dir == NULL) { + if(uml_dir == NULL){ printf("Failed to malloc uml_dir - error = %d\n", errno); - /* - * Return 0 here because do_initcalls doesn't look at + /* Return 0 here because do_initcalls doesn't look at * the return value. */ return 0; @@ -388,7 +377,7 @@ static void remove_umid_dir(void) sprintf(dir, "%s%s", uml_dir, umid); err = remove_files_and_dir(dir); - if (err) + if(err) printf("remove_umid_dir - remove_files_and_dir failed with " "err = %d\n", err); } diff --git a/trunk/arch/um/os-Linux/util.c b/trunk/arch/um/os-Linux/util.c index ef095436a78c..7cbcf484e13d 100644 --- a/trunk/arch/um/os-Linux/util.c +++ b/trunk/arch/um/os-Linux/util.c @@ -105,44 +105,6 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) void os_dump_core(void) { - int pid; - signal(SIGSEGV, SIG_DFL); - - /* - * We are about to SIGTERM this entire process group to ensure that - * nothing is around to run after the kernel exits. The - * kernel wants to abort, not die through SIGTERM, so we - * ignore it here. - */ - - signal(SIGTERM, SIG_IGN); - kill(0, SIGTERM); - /* - * Most of the other processes associated with this UML are - * likely sTopped, so give them a SIGCONT so they see the - * SIGTERM. - */ - kill(0, SIGCONT); - - /* - * Now, having sent signals to everyone but us, make sure they - * die by ptrace. Processes can survive what's been done to - * them so far - the mechanism I understand is receiving a - * SIGSEGV and segfaulting immediately upon return. There is - * always a SIGSEGV pending, and (I'm guessing) signals are - * processed in numeric order so the SIGTERM (signal 15 vs - * SIGSEGV being signal 11) is never handled. - * - * Run a waitpid loop until we get some kind of error. - * Hopefully, it's ECHILD, but there's not a lot we can do if - * it's something else. Tell os_kill_ptraced_process not to - * wait for the child to report its death because there's - * nothing reasonable to do if that fails. - */ - - while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) - os_kill_ptraced_process(pid, 0); - abort(); } diff --git a/trunk/arch/um/scripts/Makefile.rules b/trunk/arch/um/scripts/Makefile.rules index 61107b68e05b..bf23dd3e24d0 100644 --- a/trunk/arch/um/scripts/Makefile.rules +++ b/trunk/arch/um/scripts/Makefile.rules @@ -21,7 +21,7 @@ $(UNPROFILE_OBJS:.o=.%): \ $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) -# The stubs can't try to call mcount or update basic block data +# The stubs and unmap.o can't try to call mcount or update basic block data define unprofile $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) endef diff --git a/trunk/arch/um/sys-i386/Makefile b/trunk/arch/um/sys-i386/Makefile index 964dc1a04c37..a4618b6b85b9 100644 --- a/trunk/arch/um/sys-i386/Makefile +++ b/trunk/arch/um/sys-i386/Makefile @@ -1,21 +1,23 @@ -# -# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) -# - obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ - ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ + ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ sys_call_table.o tls.o +obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o + subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o -USER_OBJS := bugs.o ptrace_user.o fault.o +USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o USER_OBJS += user-offsets.s extra-y += user-offsets.s +extra-$(CONFIG_MODE_TT) += unmap.o + UNPROFILE_OBJS := stub_segv.o CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) include arch/um/scripts/Makefile.rules + +$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) diff --git a/trunk/arch/um/sys-i386/bugs.c b/trunk/arch/um/sys-i386/bugs.c index 806895d73bcc..0393e44813e7 100644 --- a/trunk/arch/um/sys-i386/bugs.c +++ b/trunk/arch/um/sys-i386/bugs.c @@ -1,15 +1,18 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include #include -#include #include -#include "kern_constants.h" -#include "os.h" -#include "task.h" +#include +#include +#include "kern_util.h" #include "user.h" +#include "sysdep/ptrace.h" +#include "task.h" +#include "os.h" #define MAXTOKEN 64 @@ -27,20 +30,18 @@ static char token(int fd, char *buf, int len, char stop) do { n = os_read_file(fd, ptr, sizeof(*ptr)); c = *ptr++; - if (n != sizeof(*ptr)) { - if (n == 0) + if(n != sizeof(*ptr)){ + if(n == 0) return 0; - printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, " - "err = %d\n", -n); - if (n < 0) + printk("Reading /proc/cpuinfo failed, err = %d\n", -n); + if(n < 0) return n; else return -EIO; } - } while ((c != '\n') && (c != stop) && (ptr < end)); + } while((c != '\n') && (c != stop) && (ptr < end)); - if (ptr == end) { - printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n", - stop); + if(ptr == end){ + printk("Failed to find '%c' in /proc/cpuinfo\n", stop); return -1; } *(ptr - 1) = '\0'; @@ -53,27 +54,26 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) char c; scratch[len - 1] = '\0'; - while (1) { + while(1){ c = token(fd, scratch, len - 1, ':'); - if (c <= 0) + if(c <= 0) return 0; - else if (c != ':') { - printk(UM_KERN_ERR "Failed to find ':' in " - "/proc/cpuinfo\n"); + else if(c != ':'){ + printk("Failed to find ':' in /proc/cpuinfo\n"); return 0; } - if (!strncmp(scratch, key, strlen(key))) + if(!strncmp(scratch, key, strlen(key))) return 1; do { n = os_read_file(fd, &c, sizeof(c)); - if (n != sizeof(c)) { - printk(UM_KERN_ERR "Failed to find newline in " + if(n != sizeof(c)){ + printk("Failed to find newline in " "/proc/cpuinfo, err = %d\n", -n); return 0; } - } while (c != '\n'); + } while(c != '\n'); } return 0; } @@ -83,50 +83,46 @@ static int check_cpu_flag(char *feature, int *have_it) char buf[MAXTOKEN], c; int fd, len = ARRAY_SIZE(buf); - printk(UM_KERN_INFO "Checking for host processor %s support...", - feature); + printk("Checking for host processor %s support...", feature); fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); - if (fd < 0) { - printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n", - -fd); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); return 0; } *have_it = 0; - if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) + if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) goto out; c = token(fd, buf, len - 1, ' '); - if (c < 0) + if(c < 0) goto out; - else if (c != ' ') { - printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n"); + else if(c != ' '){ + printk("Failed to find ' ' in /proc/cpuinfo\n"); goto out; } - while (1) { + while(1){ c = token(fd, buf, len - 1, ' '); - if (c < 0) + if(c < 0) goto out; - else if (c == '\n') - break; + else if(c == '\n') break; - if (!strcmp(buf, feature)) { + if(!strcmp(buf, feature)){ *have_it = 1; goto out; } } out: - if (*have_it == 0) + if(*have_it == 0) printk("No\n"); - else if (*have_it == 1) + else if(*have_it == 1) printk("Yes\n"); os_close_file(fd); return 1; } -#if 0 /* - * This doesn't work in tt mode, plus it's causing compilation problems +#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems * for some people. */ static void disable_lcall(void) @@ -139,9 +135,8 @@ static void disable_lcall(void) ldt.base_addr = 0; ldt.limit = 0; err = modify_ldt(1, &ldt, sizeof(ldt)); - if (err) - printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n", - errno); + if(err) + printk("Failed to disable lcall7 - errno = %d\n", errno); } #endif @@ -156,41 +151,40 @@ void arch_check_bugs(void) { int have_it; - if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) { - printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU " - "capability checks\n"); + if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ + printk("/proc/cpuinfo not available - skipping CPU capability " + "checks\n"); return; } - if (check_cpu_flag("cmov", &have_it)) + if(check_cpu_flag("cmov", &have_it)) host_has_cmov = have_it; - if (check_cpu_flag("xmm", &have_it)) + if(check_cpu_flag("xmm", &have_it)) host_has_xmm = have_it; } -int arch_handle_signal(int sig, struct uml_pt_regs *regs) +int arch_handle_signal(int sig, union uml_pt_regs *regs) { unsigned char tmp[2]; - /* - * This is testing for a cmov (0x0f 0x4x) instruction causing a + /* This is testing for a cmov (0x0f 0x4x) instruction causing a * SIGILL in init. */ - if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) + if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return 0; if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) panic("SIGILL in init, could not read instructions!\n"); - if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) + if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) return 0; - if (host_has_cmov == 0) + if(host_has_cmov == 0) panic("SIGILL caused by cmov, which this processor doesn't " "implement, boot a filesystem compiled for older " "processors"); - else if (host_has_cmov == 1) + else if(host_has_cmov == 1) panic("SIGILL caused by cmov, which this processor claims to " "implement"); - else if (host_has_cmov == -1) + else if(host_has_cmov == -1) panic("SIGILL caused by cmov, couldn't tell if this processor " "implements it, boot a filesystem compiled for older " "processors"); diff --git a/trunk/arch/um/sys-i386/fault.c b/trunk/arch/um/sys-i386/fault.c index d670f68532f4..745b4fd49e9f 100644 --- a/trunk/arch/um/sys-i386/fault.c +++ b/trunk/arch/um/sys-i386/fault.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -15,14 +15,14 @@ struct exception_table_entry const struct exception_table_entry *search_exception_tables(unsigned long add); /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ -int arch_fixup(unsigned long address, struct uml_pt_regs *regs) +int arch_fixup(unsigned long address, union uml_pt_regs *regs) { const struct exception_table_entry *fixup; fixup = search_exception_tables(address); - if (fixup != 0) { + if(fixup != 0){ UPT_IP(regs) = fixup->fixup; - return 1; + return(1); } - return 0; + return(0); } diff --git a/trunk/arch/um/sys-i386/ldt.c b/trunk/arch/um/sys-i386/ldt.c index 67c0958eb984..a939a7ef0227 100644 --- a/trunk/arch/um/sys-i386/ldt.c +++ b/trunk/arch/um/sys-i386/ldt.c @@ -1,30 +1,106 @@ /* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/mm.h" +#include "linux/sched.h" +#include "linux/slab.h" +#include "linux/types.h" +#include "linux/errno.h" +#include "linux/spinlock.h" +#include "asm/uaccess.h" +#include "asm/smp.h" +#include "asm/ldt.h" #include "asm/unistd.h" +#include "choose-mode.h" +#include "kern.h" +#include "mode_kern.h" #include "os.h" -#include "proc_mm.h" -#include "skas.h" -#include "skas_ptrace.h" -#include "sysdep/tls.h" extern int modify_ldt(int func, void *ptr, unsigned long bytecount); +#ifdef CONFIG_MODE_TT + +static long do_modify_ldt_tt(int func, void __user *ptr, + unsigned long bytecount) +{ + struct user_desc info; + int res = 0; + void *buf = NULL; + void *p = NULL; /* What we pass to host. */ + + switch(func){ + case 1: + case 0x11: /* write_ldt */ + /* Do this check now to avoid overflows. */ + if (bytecount != sizeof(struct user_desc)) { + res = -EINVAL; + goto out; + } + + if(copy_from_user(&info, ptr, sizeof(info))) { + res = -EFAULT; + goto out; + } + + p = &info; + break; + case 0: + case 2: /* read_ldt */ + + /* The use of info avoids kmalloc on the write case, not on the + * read one. */ + buf = kmalloc(bytecount, GFP_KERNEL); + if (!buf) { + res = -ENOMEM; + goto out; + } + p = buf; + break; + default: + res = -ENOSYS; + goto out; + } + + res = modify_ldt(func, p, bytecount); + if(res < 0) + goto out; + + switch(func){ + case 0: + case 2: + /* Modify_ldt was for reading and returned the number of read + * bytes.*/ + if(copy_to_user(ptr, p, res)) + res = -EFAULT; + break; + } + +out: + kfree(buf); + return res; +} + +#endif + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" +#include "skas_ptrace.h" +#include "asm/mmu_context.h" +#include "proc_mm.h" + long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, void **addr, int done) { long res; - if (proc_mm) { - /* - * This is a special handling for the case, that the mm to + if(proc_mm){ + /* This is a special handling for the case, that the mm to * modify isn't current->active_mm. * If this is called directly by modify_ldt, * (current->active_mm->context.skas.u == mm_idp) - * will be true. So no call to __switch_mm(mm_idp) is done. + * will be true. So no call to switch_mm_skas(mm_idp) is done. * If this is called in case of init_new_ldt or PTRACE_LDT, * mm_idp won't belong to current->active_mm, but child->mm. * So we need to switch child's mm into our userspace, then @@ -32,12 +108,12 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, * * Note: I'm unsure: should interrupts be disabled here? */ - if (!current->active_mm || current->active_mm == &init_mm || - mm_idp != ¤t->active_mm->context.id) - __switch_mm(mm_idp); + if(!current->active_mm || current->active_mm == &init_mm || + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(mm_idp); } - if (ptrace_ldt) { + if(ptrace_ldt) { struct ptrace_ldt ldt_op = (struct ptrace_ldt) { .func = func, .ptr = desc, @@ -45,7 +121,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, u32 cpu; int pid; - if (!proc_mm) + if(!proc_mm) pid = mm_idp->u.pid; else { cpu = get_cpu(); @@ -54,7 +130,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); - if (proc_mm) + if(proc_mm) put_cpu(); } else { @@ -63,7 +139,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, (sizeof(*desc) + sizeof(long) - 1) & ~(sizeof(long) - 1), addr, &stub_addr); - if (!res) { + if(!res){ unsigned long args[] = { func, (unsigned long)stub_addr, sizeof(*desc), @@ -73,14 +149,13 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, } } - if (proc_mm) { - /* - * This is the second part of special handling, that makes + if(proc_mm){ + /* This is the second part of special handling, that makes * PTRACE_LDT possible to implement. */ - if (current->active_mm && current->active_mm != &init_mm && - mm_idp != ¤t->active_mm->context.id) - __switch_mm(¤t->active_mm->context.id); + if(current->active_mm && current->active_mm != &init_mm && + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(¤t->active_mm->context.skas.id); } return res; @@ -95,22 +170,21 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) .ptr = kmalloc(bytecount, GFP_KERNEL)}; u32 cpu; - if (ptrace_ldt.ptr == NULL) + if(ptrace_ldt.ptr == NULL) return -ENOMEM; - /* - * This is called from sys_modify_ldt only, so userspace_pid gives + /* This is called from sys_modify_ldt only, so userspace_pid gives * us the right number */ cpu = get_cpu(); res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); put_cpu(); - if (res < 0) + if(res < 0) goto out; n = copy_to_user(ptr, ptrace_ldt.ptr, res); - if (n != 0) + if(n != 0) res = -EFAULT; out: @@ -135,34 +209,35 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) { int i, err = 0; unsigned long size; - uml_ldt_t * ldt = ¤t->mm->context.ldt; + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; - if (!ldt->entry_count) + if(!ldt->entry_count) goto out; - if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) + if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; err = bytecount; - if (ptrace_ldt) + if(ptrace_ldt){ return read_ldt_from_host(ptr, bytecount); + } down(&ldt->semaphore); - if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { + if(ldt->entry_count <= LDT_DIRECT_ENTRIES){ size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; - if (size > bytecount) + if(size > bytecount) size = bytecount; - if (copy_to_user(ptr, ldt->u.entries, size)) + if(copy_to_user(ptr, ldt->u.entries, size)) err = -EFAULT; bytecount -= size; ptr += size; } else { - for (i=0; ientry_count/LDT_ENTRIES_PER_PAGE && bytecount; - i++) { + for(i=0; ientry_count/LDT_ENTRIES_PER_PAGE && bytecount; + i++){ size = PAGE_SIZE; - if (size > bytecount) + if(size > bytecount) size = bytecount; - if (copy_to_user(ptr, ldt->u.pages[i], size)) { + if(copy_to_user(ptr, ldt->u.pages[i], size)){ err = -EFAULT; break; } @@ -172,10 +247,10 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) } up(&ldt->semaphore); - if (bytecount == 0 || err == -EFAULT) + if(bytecount == 0 || err == -EFAULT) goto out; - if (clear_user(ptr, bytecount)) + if(clear_user(ptr, bytecount)) err = -EFAULT; out: @@ -186,16 +261,15 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) { int err; - if (bytecount > 5*LDT_ENTRY_SIZE) + if(bytecount > 5*LDT_ENTRY_SIZE) bytecount = 5*LDT_ENTRY_SIZE; err = bytecount; - /* - * UML doesn't support lcall7 and lcall27. + /* UML doesn't support lcall7 and lcall27. * So, we don't really have a default ldt, but emulate * an empty ldt of common host default ldt size. */ - if (clear_user(ptr, bytecount)) + if(clear_user(ptr, bytecount)) err = -EFAULT; return err; @@ -203,60 +277,60 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) static int write_ldt(void __user * ptr, unsigned long bytecount, int func) { - uml_ldt_t * ldt = ¤t->mm->context.ldt; - struct mm_id * mm_idp = ¤t->mm->context.id; + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + struct mm_id * mm_idp = ¤t->mm->context.skas.id; int i, err; struct user_desc ldt_info; struct ldt_entry entry0, *ldt_p; void *addr = NULL; err = -EINVAL; - if (bytecount != sizeof(ldt_info)) + if(bytecount != sizeof(ldt_info)) goto out; err = -EFAULT; - if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) + if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) goto out; err = -EINVAL; - if (ldt_info.entry_number >= LDT_ENTRIES) + if(ldt_info.entry_number >= LDT_ENTRIES) goto out; - if (ldt_info.contents == 3) { + if(ldt_info.contents == 3){ if (func == 1) goto out; if (ldt_info.seg_not_present == 0) goto out; } - if (!ptrace_ldt) - down(&ldt->semaphore); + if(!ptrace_ldt) + down(&ldt->semaphore); err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); - if (err) + if(err) goto out_unlock; - else if (ptrace_ldt) { - /* With PTRACE_LDT available, this is used as a flag only */ - ldt->entry_count = 1; - goto out; - } - - if (ldt_info.entry_number >= ldt->entry_count && - ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { - for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; - i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; - i++) { - if (i == 0) + else if(ptrace_ldt) { + /* With PTRACE_LDT available, this is used as a flag only */ + ldt->entry_count = 1; + goto out; + } + + if(ldt_info.entry_number >= ldt->entry_count && + ldt_info.entry_number >= LDT_DIRECT_ENTRIES){ + for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; + i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; + i++){ + if(i == 0) memcpy(&entry0, ldt->u.entries, sizeof(entry0)); ldt->u.pages[i] = (struct ldt_entry *) __get_free_page(GFP_KERNEL|__GFP_ZERO); - if (!ldt->u.pages[i]) { + if(!ldt->u.pages[i]){ err = -ENOMEM; /* Undo the change in host */ memset(&ldt_info, 0, sizeof(ldt_info)); write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); goto out_unlock; } - if (i == 0) { + if(i == 0) { memcpy(ldt->u.pages[0], &entry0, sizeof(entry0)); memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, @@ -265,17 +339,17 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; } } - if (ldt->entry_count <= ldt_info.entry_number) + if(ldt->entry_count <= ldt_info.entry_number) ldt->entry_count = ldt_info.entry_number + 1; - if (ldt->entry_count <= LDT_DIRECT_ENTRIES) + if(ldt->entry_count <= LDT_DIRECT_ENTRIES) ldt_p = ldt->u.entries + ldt_info.entry_number; else ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; - if (ldt_info.base_addr == 0 && ldt_info.limit == 0 && - (func == 1 || LDT_empty(&ldt_info))) { + if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && + (func == 1 || LDT_empty(&ldt_info))){ ldt_p->a = 0; ldt_p->b = 0; } @@ -326,7 +400,7 @@ static void ldt_get_host_info(void) spin_lock(&host_ldt_lock); - if (host_ldt_entries != NULL) { + if(host_ldt_entries != NULL){ spin_unlock(&host_ldt_lock); return; } @@ -334,49 +408,49 @@ static void ldt_get_host_info(void) spin_unlock(&host_ldt_lock); - for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++) - ; + for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); ldt = (struct ldt_entry *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); - if (ldt == NULL) { - printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer " - "for host ldt\n"); + if(ldt == NULL) { + printk("ldt_get_host_info: couldn't allocate buffer for host " + "ldt\n"); return; } ret = modify_ldt(0, ldt, (1<ldt.semaphore); - if (!from_mm) { + if(!from_mm){ memset(&desc, 0, sizeof(desc)); /* * We have to initialize a clean ldt. */ - if (proc_mm) { + if(proc_mm) { /* * If the new mm was created using proc_mm, host's * default-ldt currently is assigned, which normally @@ -410,7 +485,8 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) * To remove these gates, we simply write an empty * entry as number 0 to the host. */ - err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); + err = write_ldt_entry(&new_mm->id, 1, &desc, + &addr, 1); } else{ /* @@ -419,11 +495,11 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) * will be reset in the following loop */ ldt_get_host_info(); - for (num_p=host_ldt_entries; *num_p != -1; num_p++) { + for(num_p=host_ldt_entries; *num_p != -1; num_p++){ desc.entry_number = *num_p; err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, *(num_p + 1) == -1); - if (err) + if(err) break; } } @@ -432,9 +508,8 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) goto out; } - if (proc_mm) { - /* - * We have a valid from_mm, so we now have to copy the LDT of + if(proc_mm){ + /* We have a valid from_mm, so we now have to copy the LDT of * from_mm to new_mm, because using proc_mm an new mm with * an empty/default LDT was created in new_mm() */ @@ -443,27 +518,27 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) { .copy_segments = from_mm->id.u.mm_fd } } ); i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); - if (i != sizeof(copy)) - printk(KERN_ERR "new_mm : /proc/mm copy_segments " - "failed, err = %d\n", -i); + if(i != sizeof(copy)) + printk("new_mm : /proc/mm copy_segments failed, " + "err = %d\n", -i); } - if (!ptrace_ldt) { - /* - * Our local LDT is used to supply the data for + if(!ptrace_ldt) { + /* Our local LDT is used to supply the data for * modify_ldt(READLDT), if PTRACE_LDT isn't available, * i.e., we have to use the stub for modify_ldt, which * can't handle the big read buffer of up to 64kB. */ down(&from_mm->ldt.semaphore); - if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) + if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, sizeof(new_mm->ldt.u.entries)); - else { + } + else{ i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while (i-->0) { + while(i-->0){ page = __get_free_page(GFP_KERNEL|__GFP_ZERO); - if (!page) { + if (!page){ err = -ENOMEM; break; } @@ -482,19 +557,22 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) } -void free_ldt(struct mm_context *mm) +void free_ldt(struct mmu_context_skas * mm) { int i; - if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) { + if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while (i-- > 0) - free_page((long) mm->ldt.u.pages[i]); + while(i-- > 0){ + free_page((long )mm->ldt.u.pages[i]); + } } mm->ldt.entry_count = 0; } +#endif int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { - return do_modify_ldt_skas(func, ptr, bytecount); + return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, + ptr, bytecount); } diff --git a/trunk/arch/um/sys-i386/ptrace.c b/trunk/arch/um/sys-i386/ptrace.c index 9657c89fdf31..28bf01150323 100644 --- a/trunk/arch/um/sys-i386/ptrace.c +++ b/trunk/arch/um/sys-i386/ptrace.c @@ -1,26 +1,35 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ -#include "linux/mm.h" +#include #include "linux/sched.h" +#include "linux/mm.h" +#include "asm/elf.h" +#include "asm/ptrace.h" #include "asm/uaccess.h" -#include "skas.h" +#include "asm/unistd.h" +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" +#include "sysdep/sc.h" -extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); +void arch_switch_to_tt(struct task_struct *from, struct task_struct *to) +{ + update_debugregs(to->thread.arch.debugregs_seq); + arch_switch_tls_tt(from, to); +} -void arch_switch_to(struct task_struct *from, struct task_struct *to) +void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) { - int err = arch_switch_tls(from, to); + int err = arch_switch_tls_skas(from, to); if (!err) return; if (err != -EINVAL) - printk(KERN_WARNING "arch_switch_tls failed, errno %d, " - "not EINVAL\n", -err); + printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err); else - printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); + printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n"); } int is_syscall(unsigned long addr) @@ -29,21 +38,21 @@ int is_syscall(unsigned long addr) int n; n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n) { + if(n){ /* access_process_vm() grants access to vsyscall and stub, * while copy_from_user doesn't. Maybe access_process_vm is * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if (n != sizeof(instr)) { - printk(KERN_ERR "is_syscall : failed to read " - "instruction from 0x%lx\n", addr); - return 1; + if(n != sizeof(instr)) { + printk("is_syscall : failed to read instruction from " + "0x%lx\n", addr); + return(1); } } /* int 0x80 or sysenter */ - return (instr == 0x80cd) || (instr == 0x340f); + return((instr == 0x80cd) || (instr == 0x340f)); } /* determines which flags the user has access to. */ @@ -87,21 +96,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) int poke_user(struct task_struct *child, long addr, long data) { - if ((addr & 3) || addr < 0) - return -EIO; + if ((addr & 3) || addr < 0) + return -EIO; - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if ((addr == 4) || (addr == 5)) - return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; + if (addr < MAX_REG_OFFSET) + return putreg(child, addr, data); + + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if((addr == 4) || (addr == 5)) return -EIO; + child->thread.arch.debugregs[addr] = data; + return 0; + } + return -EIO; } unsigned long getreg(struct task_struct *child, int regno) @@ -124,20 +133,20 @@ unsigned long getreg(struct task_struct *child, int regno) return retval; } -/* read the word at location addr in the USER area. */ int peek_user(struct task_struct *child, long addr, long data) { +/* read the word at location addr in the USER area. */ unsigned long tmp; if ((addr & 3) || addr < 0) return -EIO; tmp = 0; /* Default return condition */ - if (addr < MAX_REG_OFFSET) { + if(addr < MAX_REG_OFFSET){ tmp = getreg(child, addr); } - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ addr -= offsetof(struct user, u_debugreg[0]); addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; @@ -145,68 +154,277 @@ int peek_user(struct task_struct *child, long addr, long data) return put_user(tmp, (unsigned long __user *) data); } -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +struct i387_fxsave_struct { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fop; + long fip; + long fcs; + long foo; + long fos; + long mxcsr; + long reserved; + long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long padding[56]; +}; + +/* + * FPU tag word conversions. + */ + +static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) { - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + unsigned int tmp; /* to avoid 16 bit prefixes in the code */ + + /* Transform each pair of bits into 01 (valid) or 00 (empty) */ + tmp = ~twd; + tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ + /* and move the valid bits to the lower byte. */ + tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ + tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ + tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ + return tmp; +} - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fp_registers(userspace_pid[cpu], fpregs); - if (err) - return err; +static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) +{ + struct _fpxreg *st = NULL; + unsigned long twd = (unsigned long) fxsave->twd; + unsigned long tag; + unsigned long ret = 0xffff0000; + int i; - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; +#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); - return n; + for ( i = 0 ; i < 8 ; i++ ) { + if ( twd & 0x1 ) { + st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); + + switch ( st->exponent & 0x7fff ) { + case 0x7fff: + tag = 2; /* Special */ + break; + case 0x0000: + if ( !st->significand[0] && + !st->significand[1] && + !st->significand[2] && + !st->significand[3] ) { + tag = 1; /* Zero */ + } else { + tag = 2; /* Special */ + } + break; + default: + if ( st->significand[3] & 0x8000 ) { + tag = 0; /* Valid */ + } else { + tag = 2; /* Special */ + } + break; + } + } else { + tag = 3; /* Empty */ + } + ret |= (tag << (2 * i)); + twd = twd >> 1; + } + return ret; } -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +/* + * FXSR floating point environment conversions. + */ + +#ifdef CONFIG_MODE_TT +static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, + struct pt_regs *regs) { - int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); + unsigned long env[7]; + struct _fpreg __user *to; + struct _fpxreg *from; + int i; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; + env[0] = (unsigned long)fxsave->cwd | 0xffff0000; + env[1] = (unsigned long)fxsave->swd | 0xffff0000; + env[2] = twd_fxsr_to_i387(fxsave); + env[3] = fxsave->fip; + env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); + env[5] = fxsave->foo; + env[6] = fxsave->fos; - return restore_fp_registers(userspace_pid[cpu], fpregs); + if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) + return 1; + + to = &buf->_st[0]; + from = (struct _fpxreg *) &fxsave->st_space[0]; + for ( i = 0 ; i < 8 ; i++, to++, from++ ) { + if ( __copy_to_user( to, from, sizeof(*to) ) ) + return 1; + } + return 0; } +#endif -int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) +static inline int convert_fxsr_to_user(struct _fpstate __user *buf, + struct pt_regs *regs) { - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); +} - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fpx_registers(userspace_pid[cpu], fpregs); - if (err) - return err; +#ifdef CONFIG_MODE_TT +static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, + struct _fpstate __user *buf) +{ + struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); + unsigned long env[7]; + struct _fpxreg *to; + struct _fpreg __user *from; + int i; + + if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) + return 1; - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; + fxsave->cwd = (unsigned short)(env[0] & 0xffff); + fxsave->swd = (unsigned short)(env[1] & 0xffff); + fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); + fxsave->fip = env[3]; + fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); + fxsave->fcs = (env[4] & 0xffff); + fxsave->foo = env[5]; + fxsave->fos = env[6]; - return n; + to = (struct _fpxreg *) &fxsave->st_space[0]; + from = &buf->_st[0]; + for ( i = 0 ; i < 8 ; i++, to++, from++ ) { + if ( __copy_from_user( to, from, sizeof(*from) ) ) + return 1; + } + return 0; +} +#endif + +static inline int convert_fxsr_from_user(struct pt_regs *regs, + struct _fpstate __user *buf) +{ + return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); +} + +int get_fpregs(unsigned long buf, struct task_struct *child) +{ + int err; + + err = convert_fxsr_to_user((struct _fpstate __user *) buf, + &child->thread.regs); + if(err) return(-EFAULT); + else return(0); +} + +int set_fpregs(unsigned long buf, struct task_struct *child) +{ + int err; + + err = convert_fxsr_from_user(&child->thread.regs, + (struct _fpstate __user *) buf); + if(err) return(-EFAULT); + else return(0); +} + +#ifdef CONFIG_MODE_TT +int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) +{ + struct pt_regs *regs = &tsk->thread.regs; + struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); + int err; + + err = __copy_to_user((void __user *) buf, fxsave, + sizeof(struct user_fxsr_struct)); + if(err) return -EFAULT; + else return 0; +} +#endif + +int get_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); +} + +#ifdef CONFIG_MODE_TT +int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) +{ + struct pt_regs *regs = &tsk->thread.regs; + struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); + int err; + + err = __copy_from_user(fxsave, (void __user *) buf, + sizeof(struct user_fxsr_struct) ); + if(err) return -EFAULT; + else return 0; +} +#endif + +int set_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); +} + +#ifdef notdef +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) +{ + fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | + (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); + fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; + fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); + fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; + fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); + fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); + fpu->fos = 0; + memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), + sizeof(fpu->st_space)); + return(1); } +#endif -int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) +#ifdef CONFIG_MODE_TT +static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, + struct user_i387_struct *buf) { - int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); + unsigned short *to; + unsigned short *from; + int i; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; + memcpy( buf, fpu, 7 * sizeof(long) ); - return restore_fpx_registers(userspace_pid[cpu], fpregs); + to = (unsigned short *) &buf->st_space[0]; + from = (unsigned short *) &fpu->st_space[0]; + for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { + memcpy( to, from, 5 * sizeof(unsigned short) ); + } } +#endif -long subarch_ptrace(struct task_struct *child, long request, long addr, - long data) +static inline void copy_fpu_fxsave(struct pt_regs *regs, + struct user_i387_struct *buf) { - return -EIO; + (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); } + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) +{ + copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); + return(1); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/sys-i386/ptrace_user.c b/trunk/arch/um/sys-i386/ptrace_user.c index 5cf97bc229b9..40ff0c831bd0 100644 --- a/trunk/arch/um/sys-i386/ptrace_user.c +++ b/trunk/arch/um/sys-i386/ptrace_user.c @@ -1,10 +1,20 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ +#include +#include #include -#include +#include +#include "ptrace_user.h" +/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */ +#include +#include "kern_util.h" +#include "sysdep/thread.h" +#include "user.h" +#include "os.h" +#include "uml-config.h" int ptrace_getregs(long pid, unsigned long *regs_out) { @@ -33,3 +43,89 @@ int ptrace_setfpregs(long pid, unsigned long *regs) return -errno; return 0; } + +#ifdef UML_CONFIG_MODE_TT + +static void write_debugregs(int pid, unsigned long *regs) +{ + struct user *dummy; + int nregs, i; + + dummy = NULL; + nregs = ARRAY_SIZE(dummy->u_debugreg); + for(i = 0; i < nregs; i++){ + if((i == 4) || (i == 5)) continue; + if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], + regs[i]) < 0) + printk("write_debugregs - ptrace failed on " + "register %d, value = 0x%lx, errno = %d\n", i, + regs[i], errno); + } +} + +static void read_debugregs(int pid, unsigned long *regs) +{ + struct user *dummy; + int nregs, i; + + dummy = NULL; + nregs = ARRAY_SIZE(dummy->u_debugreg); + for(i = 0; i < nregs; i++){ + regs[i] = ptrace(PTRACE_PEEKUSR, pid, + &dummy->u_debugreg[i], 0); + } +} + +/* Accessed only by the tracing thread */ +static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; + +void arch_enter_kernel(void *task, int pid) +{ + read_debugregs(pid, TASK_DEBUGREGS(task)); + write_debugregs(pid, kernel_debugregs); +} + +void arch_leave_kernel(void *task, int pid) +{ + read_debugregs(pid, kernel_debugregs); + write_debugregs(pid, TASK_DEBUGREGS(task)); +} + +#ifdef UML_CONFIG_PT_PROXY +/* Accessed only by the tracing thread */ +static int debugregs_seq; + +/* Only called by the ptrace proxy */ +void ptrace_pokeuser(unsigned long addr, unsigned long data) +{ + if((addr < offsetof(struct user, u_debugreg[0])) || + (addr > offsetof(struct user, u_debugreg[7]))) + return; + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if(kernel_debugregs[addr] == data) return; + + kernel_debugregs[addr] = data; + debugregs_seq++; +} + +static void update_debugregs_cb(void *arg) +{ + int pid = *((int *) arg); + + write_debugregs(pid, kernel_debugregs); +} + +/* Optimized out in its header when not defined */ +void update_debugregs(int seq) +{ + int me; + + if(seq == debugregs_seq) return; + + me = os_getpid(); + initial_thread_cb(update_debugregs_cb, &me); +} +#endif + +#endif diff --git a/trunk/arch/um/sys-i386/sigcontext.c b/trunk/arch/um/sys-i386/sigcontext.c new file mode 100644 index 000000000000..467d489c31cd --- /dev/null +++ b/trunk/arch/um/sys-i386/sigcontext.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include "sysdep/ptrace.h" +#include "kern_util.h" + +void sc_to_sc(void *to_ptr, void *from_ptr) +{ + struct sigcontext *to = to_ptr, *from = from_ptr; + + memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate)); + if(from->fpstate != NULL) + to->fpstate = (struct _fpstate *) (to + 1); +} + +unsigned long *sc_sigmask(void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + return &sc->oldmask; +} + +int sc_get_fpregs(unsigned long buf, void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; + int err = 0; + + if(from == NULL){ + err |= clear_user_proc(&to->cw, sizeof(to->cw)); + err |= clear_user_proc(&to->sw, sizeof(to->sw)); + err |= clear_user_proc(&to->tag, sizeof(to->tag)); + err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); + err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); + err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); + err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); + err |= clear_user_proc(&to->_st, sizeof(to->_st)); + } + else { + err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); + err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); + err |= copy_to_user_proc(&to->tag, &from->tag, + sizeof(to->tag)); + err |= copy_to_user_proc(&to->ipoff, &from->ipoff, + sizeof(to->ipoff)); + err |= copy_to_user_proc(&to->cssel,& from->cssel, + sizeof(to->cssel)); + err |= copy_to_user_proc(&to->dataoff, &from->dataoff, + sizeof(to->dataoff)); + err |= copy_to_user_proc(&to->datasel, &from->datasel, + sizeof(to->datasel)); + err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); + } + return(err); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/sys-i386/signal.c b/trunk/arch/um/sys-i386/signal.c index 0147227ce18d..1cbf95f6858a 100644 --- a/trunk/arch/um/sys-i386/signal.c +++ b/trunk/arch/um/sys-i386/signal.c @@ -1,293 +1,189 @@ /* - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ +#include "linux/signal.h" #include "linux/ptrace.h" -#include "asm/unistd.h" -#include "asm/uaccess.h" +#include "asm/current.h" #include "asm/ucontext.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" #include "frame_kern.h" +#include "sigcontext.h" +#include "registers.h" +#include "mode.h" + +#ifdef CONFIG_MODE_SKAS + #include "skas.h" -void copy_sc(struct uml_pt_regs *regs, void *from) +void copy_sc(union uml_pt_regs *regs, void *from) { struct sigcontext *sc = from; - REGS_GS(regs->gp) = sc->gs; - REGS_FS(regs->gp) = sc->fs; - REGS_ES(regs->gp) = sc->es; - REGS_DS(regs->gp) = sc->ds; - REGS_EDI(regs->gp) = sc->edi; - REGS_ESI(regs->gp) = sc->esi; - REGS_EBP(regs->gp) = sc->ebp; - REGS_SP(regs->gp) = sc->esp; - REGS_EBX(regs->gp) = sc->ebx; - REGS_EDX(regs->gp) = sc->edx; - REGS_ECX(regs->gp) = sc->ecx; - REGS_EAX(regs->gp) = sc->eax; - REGS_IP(regs->gp) = sc->eip; - REGS_CS(regs->gp) = sc->cs; - REGS_EFLAGS(regs->gp) = sc->eflags; - REGS_SS(regs->gp) = sc->ss; + REGS_GS(regs->skas.regs) = sc->gs; + REGS_FS(regs->skas.regs) = sc->fs; + REGS_ES(regs->skas.regs) = sc->es; + REGS_DS(regs->skas.regs) = sc->ds; + REGS_EDI(regs->skas.regs) = sc->edi; + REGS_ESI(regs->skas.regs) = sc->esi; + REGS_EBP(regs->skas.regs) = sc->ebp; + REGS_SP(regs->skas.regs) = sc->esp; + REGS_EBX(regs->skas.regs) = sc->ebx; + REGS_EDX(regs->skas.regs) = sc->edx; + REGS_ECX(regs->skas.regs) = sc->ecx; + REGS_EAX(regs->skas.regs) = sc->eax; + REGS_IP(regs->skas.regs) = sc->eip; + REGS_CS(regs->skas.regs) = sc->cs; + REGS_EFLAGS(regs->skas.regs) = sc->eflags; + REGS_SS(regs->skas.regs) = sc->ss; } -/* - * FPU tag word conversions. - */ - -static inline unsigned short twd_i387_to_fxsr(unsigned short twd) -{ - unsigned int tmp; /* to avoid 16 bit prefixes in the code */ - - /* Transform each pair of bits into 01 (valid) or 00 (empty) */ - tmp = ~twd; - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* and move the valid bits to the lower byte. */ - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ - return tmp; -} - -static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) +static int copy_sc_from_user_skas(struct pt_regs *regs, + struct sigcontext __user *from) { - struct _fpxreg *st = NULL; - unsigned long twd = (unsigned long) fxsave->twd; - unsigned long tag; - unsigned long ret = 0xffff0000; - int i; - -#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); - - for (i = 0; i < 8; i++) { - if (twd & 0x1) { - st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); - - switch (st->exponent & 0x7fff) { - case 0x7fff: - tag = 2; /* Special */ - break; - case 0x0000: - if ( !st->significand[0] && - !st->significand[1] && - !st->significand[2] && - !st->significand[3] ) { - tag = 1; /* Zero */ - } else { - tag = 2; /* Special */ - } - break; - default: - if (st->significand[3] & 0x8000) { - tag = 0; /* Valid */ - } else { - tag = 2; /* Special */ - } - break; - } - } else { - tag = 3; /* Empty */ - } - ret |= (tag << (2 * i)); - twd = twd >> 1; - } - return ret; -} + struct sigcontext sc; + unsigned long fpregs[HOST_FP_SIZE]; + int err; -static int convert_fxsr_to_user(struct _fpstate __user *buf, - struct user_fxsr_struct *fxsave) -{ - unsigned long env[7]; - struct _fpreg __user *to; - struct _fpxreg *from; - int i; - - env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; - env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; - env[2] = twd_fxsr_to_i387(fxsave); - env[3] = fxsave->fip; - env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); - env[5] = fxsave->foo; - env[6] = fxsave->fos; - - if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) - return 1; + err = copy_from_user(&sc, from, sizeof(sc)); + err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); + if(err) + return err; - to = &buf->_st[0]; - from = (struct _fpxreg *) &fxsave->st_space[0]; - for (i = 0; i < 8; i++, to++, from++) { - unsigned long __user *t = (unsigned long __user *)to; - unsigned long *f = (unsigned long *)from; + copy_sc(®s->regs, &sc); - if (__put_user(*f, t) || - __put_user(*(f + 1), t + 1) || - __put_user(from->exponent, &to->exponent)) - return 1; + err = restore_fp_registers(userspace_pid[0], fpregs); + if(err < 0) { + printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " + "errno = %d\n", -err); + return err; } + return 0; } -static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, - struct _fpstate __user *buf) +int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, + struct pt_regs *regs, unsigned long sp) { - unsigned long env[7]; - struct _fpxreg *to; - struct _fpreg __user *from; - int i; + struct sigcontext sc; + unsigned long fpregs[HOST_FP_SIZE]; + struct faultinfo * fi = ¤t->thread.arch.faultinfo; + int err; - if (copy_from_user( env, buf, 7 * sizeof(long))) + sc.gs = REGS_GS(regs->regs.skas.regs); + sc.fs = REGS_FS(regs->regs.skas.regs); + sc.es = REGS_ES(regs->regs.skas.regs); + sc.ds = REGS_DS(regs->regs.skas.regs); + sc.edi = REGS_EDI(regs->regs.skas.regs); + sc.esi = REGS_ESI(regs->regs.skas.regs); + sc.ebp = REGS_EBP(regs->regs.skas.regs); + sc.esp = sp; + sc.ebx = REGS_EBX(regs->regs.skas.regs); + sc.edx = REGS_EDX(regs->regs.skas.regs); + sc.ecx = REGS_ECX(regs->regs.skas.regs); + sc.eax = REGS_EAX(regs->regs.skas.regs); + sc.eip = REGS_IP(regs->regs.skas.regs); + sc.cs = REGS_CS(regs->regs.skas.regs); + sc.eflags = REGS_EFLAGS(regs->regs.skas.regs); + sc.esp_at_signal = regs->regs.skas.regs[UESP]; + sc.ss = regs->regs.skas.regs[SS]; + sc.cr2 = fi->cr2; + sc.err = fi->error_code; + sc.trapno = fi->trap_no; + + err = save_fp_registers(userspace_pid[0], fpregs); + if(err < 0){ + printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " + "errno = %d\n", err); return 1; - - fxsave->cwd = (unsigned short)(env[0] & 0xffff); - fxsave->swd = (unsigned short)(env[1] & 0xffff); - fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); - fxsave->fip = env[3]; - fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); - fxsave->fcs = (env[4] & 0xffff); - fxsave->foo = env[5]; - fxsave->fos = env[6]; - - to = (struct _fpxreg *) &fxsave->st_space[0]; - from = &buf->_st[0]; - for (i = 0; i < 8; i++, to++, from++) { - unsigned long *t = (unsigned long *)to; - unsigned long __user *f = (unsigned long __user *)from; - - if (__get_user(*t, f) || - __get_user(*(t + 1), f + 1) || - __get_user(to->exponent, &from->exponent)) - return 1; } - return 0; + to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); + sc.fpstate = to_fp; + + if(err) + return err; + + return copy_to_user(to, &sc, sizeof(sc)) || + copy_to_user(to_fp, fpregs, sizeof(fpregs)); } +#endif -extern int have_fpx_regs; +#ifdef CONFIG_MODE_TT -static int copy_sc_from_user(struct pt_regs *regs, - struct sigcontext __user *from) +/* These copy a sigcontext to/from userspace. They copy the fpstate pointer, + * blowing away the old, good one. So, that value is saved, and then restored + * after the sigcontext copy. In copy_from, the variable holding the saved + * fpstate pointer, and the sigcontext that it should be restored to are both + * in the kernel, so we can just restore using an assignment. In copy_to, the + * saved pointer is in the kernel, but the sigcontext is in userspace, so we + * copy_to_user it. + */ +int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, + int fpsize) { - struct sigcontext sc; + struct _fpstate *to_fp; + struct _fpstate __user *from_fp; + unsigned long sigs; int err; - err = copy_from_user(&sc, from, sizeof(sc)); - if (err) - return err; - - copy_sc(®s->regs, &sc); - if (have_fpx_regs) { - struct user_fxsr_struct fpx; - - err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0], - sizeof(struct user_fxsr_struct)); - if (err) - return 1; - - err = convert_fxsr_from_user(&fpx, sc.fpstate); - if (err) - return 1; - - err = restore_fpx_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fpx); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fpx_registers failed, errno = %d\n", - -err); - return 1; - } - } - else { - struct user_i387_struct fp; - - err = copy_from_user(&fp, sc.fpstate, - sizeof(struct user_i387_struct)); - if (err) - return 1; - - err = restore_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fp_registers failed, errno = %d\n", - -err); - return 1; - } - } - - return 0; + to_fp = to->fpstate; + sigs = to->oldmask; + err = copy_from_user(to, from, sizeof(*to)); + from_fp = to->fpstate; + to->oldmask = sigs; + to->fpstate = to_fp; + if(to_fp != NULL) + err |= copy_from_user(to_fp, from_fp, fpsize); + return err; } -static int copy_sc_to_user(struct sigcontext __user *to, - struct _fpstate __user *to_fp, struct pt_regs *regs, - unsigned long sp) +int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, + struct sigcontext *from, int fpsize, unsigned long sp) { - struct sigcontext sc; - struct faultinfo * fi = ¤t->thread.arch.faultinfo; + struct _fpstate __user *to_fp; + struct _fpstate *from_fp; int err; - sc.gs = REGS_GS(regs->regs.gp); - sc.fs = REGS_FS(regs->regs.gp); - sc.es = REGS_ES(regs->regs.gp); - sc.ds = REGS_DS(regs->regs.gp); - sc.edi = REGS_EDI(regs->regs.gp); - sc.esi = REGS_ESI(regs->regs.gp); - sc.ebp = REGS_EBP(regs->regs.gp); - sc.esp = sp; - sc.ebx = REGS_EBX(regs->regs.gp); - sc.edx = REGS_EDX(regs->regs.gp); - sc.ecx = REGS_ECX(regs->regs.gp); - sc.eax = REGS_EAX(regs->regs.gp); - sc.eip = REGS_IP(regs->regs.gp); - sc.cs = REGS_CS(regs->regs.gp); - sc.eflags = REGS_EFLAGS(regs->regs.gp); - sc.esp_at_signal = regs->regs.gp[UESP]; - sc.ss = regs->regs.gp[SS]; - sc.cr2 = fi->cr2; - sc.err = fi->error_code; - sc.trapno = fi->trap_no; + to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); + from_fp = from->fpstate; + err = copy_to_user(to, from, sizeof(*to)); - to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); - sc.fpstate = to_fp; + /* The SP in the sigcontext is the updated one for the signal + * delivery. The sp passed in is the original, and this needs + * to be restored, so we stick it in separately. + */ + err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); - if (have_fpx_regs) { - struct user_fxsr_struct fpx; - - err = save_fpx_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fpx); - if (err < 0){ - printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " - "failed, errno = %d\n", err); - return 1; - } - - err = convert_fxsr_to_user(to_fp, &fpx); - if (err) - return 1; - - err |= __put_user(fpx.swd, &to_fp->status); - err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); - if (err) - return 1; - - if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, - sizeof(struct user_fxsr_struct))) - return 1; + if(from_fp != NULL){ + err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); + err |= copy_to_user(to_fp, from_fp, fpsize); } - else { - struct user_i387_struct fp; + return err; +} +#endif - err = save_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); - if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) - return 1; - } +static int copy_sc_from_user(struct pt_regs *to, void __user *from) +{ + int ret; - return copy_to_user(to, &sc, sizeof(sc)); + ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, + sizeof(struct _fpstate)), + copy_sc_from_user_skas(to, from)); + return ret; +} + +static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, + struct pt_regs *from, unsigned long sp) +{ + return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), + sizeof(*fp), sp), + copy_sc_to_user_skas(to, fp, from, sp)); } -static int copy_ucontext_to_user(struct ucontext __user *uc, - struct _fpstate __user *fp, sigset_t *set, - unsigned long sp) +static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, + sigset_t *set, unsigned long sp) { int err = 0; @@ -337,7 +233,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, return 1; restorer = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) + if(ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; /* Update SP now because the page fault handler refuses to extend @@ -369,7 +265,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); - if (err) + if(err) goto err; PT_REGS_SP(regs) = (unsigned long) frame; @@ -402,7 +298,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, return 1; restorer = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) + if(ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; /* See comment above about why this is here */ @@ -427,7 +323,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); - if (err) + if(err) goto err; PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; @@ -454,8 +350,8 @@ long sys_sigreturn(struct pt_regs regs) unsigned long __user *extramask = frame->extramask; int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); - if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || - copy_from_user(&set.sig[1], extramask, sig_size)) + if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || + copy_from_user(&set.sig[1], extramask, sig_size)) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -465,7 +361,7 @@ long sys_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (copy_sc_from_user(¤t->thread.regs, sc)) + if(copy_sc_from_user(¤t->thread.regs, sc)) goto segfault; /* Avoid ERESTART handling */ @@ -480,13 +376,12 @@ long sys_sigreturn(struct pt_regs regs) long sys_rt_sigreturn(struct pt_regs regs) { unsigned long sp = PT_REGS_SP(¤t->thread.regs); - struct rt_sigframe __user *frame = - (struct rt_sigframe __user *) (sp - 4); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4); sigset_t set; struct ucontext __user *uc = &frame->uc; int sig_size = _NSIG_WORDS * sizeof(unsigned long); - if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) + if(copy_from_user(&set, &uc->uc_sigmask, sig_size)) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -496,7 +391,7 @@ long sys_rt_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) + if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) goto segfault; /* Avoid ERESTART handling */ diff --git a/trunk/arch/um/sys-i386/stub.S b/trunk/arch/um/sys-i386/stub.S index e730772c401b..6a70d9ab5c29 100644 --- a/trunk/arch/um/sys-i386/stub.S +++ b/trunk/arch/um/sys-i386/stub.S @@ -1,5 +1,4 @@ #include "uml-config.h" -#include "as-layout.h" .globl syscall_stub .section .__syscall_stub, "x" @@ -7,7 +6,7 @@ .globl batch_syscall_stub batch_syscall_stub: /* load pointer to first operation */ - mov $(ASM_STUB_DATA+8), %esp + mov $(UML_CONFIG_STUB_DATA+8), %esp again: /* load length of additional data */ @@ -15,12 +14,12 @@ again: /* if(length == 0) : end of list */ /* write possible 0 to header */ - mov %eax, ASM_STUB_DATA+4 + mov %eax, UML_CONFIG_STUB_DATA+4 cmpl $0, %eax jz done /* save current pointer */ - mov %esp, ASM_STUB_DATA+4 + mov %esp, UML_CONFIG_STUB_DATA+4 /* skip additional data */ add %eax, %esp @@ -46,7 +45,7 @@ again: done: /* save return value */ - mov %eax, ASM_STUB_DATA + mov %eax, UML_CONFIG_STUB_DATA /* stop */ int3 diff --git a/trunk/arch/um/sys-i386/stub_segv.c b/trunk/arch/um/sys-i386/stub_segv.c index b3999cb76bfd..2355dc19c46c 100644 --- a/trunk/arch/um/sys-i386/stub_segv.c +++ b/trunk/arch/um/sys-i386/stub_segv.c @@ -6,7 +6,6 @@ #include #include /* The only way I can see to get sigset_t */ #include -#include "as-layout.h" #include "uml-config.h" #include "sysdep/stub.h" #include "sysdep/sigcontext.h" @@ -18,7 +17,8 @@ stub_segv_handler(int sig) struct sigcontext *sc = (struct sigcontext *) (&sig + 1); int pid; - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + sc); pid = stub_syscall0(__NR_getpid); stub_syscall2(__NR_kill, pid, SIGUSR1); diff --git a/trunk/arch/um/sys-i386/tls.c b/trunk/arch/um/sys-i386/tls.c index b02266ab5c55..fea8e5e15cc4 100644 --- a/trunk/arch/um/sys-i386/tls.c +++ b/trunk/arch/um/sys-i386/tls.c @@ -3,12 +3,25 @@ * Licensed under the GPL */ -#include "linux/percpu.h" +#include "linux/kernel.h" #include "linux/sched.h" +#include "linux/slab.h" +#include "linux/types.h" #include "asm/uaccess.h" +#include "asm/ptrace.h" +#include "asm/segment.h" +#include "asm/smp.h" +#include "asm/desc.h" +#include "choose-mode.h" +#include "kern.h" +#include "kern_util.h" +#include "mode_kern.h" #include "os.h" +#include "mode.h" + +#ifdef CONFIG_MODE_SKAS #include "skas.h" -#include "sysdep/tls.h" +#endif /* * If needed we can detect when it's uninitialized. @@ -18,7 +31,8 @@ static int host_supports_tls = -1; int host_gdt_entry_tls_min; -int do_set_thread_area(struct user_desc *info) +#ifdef CONFIG_MODE_SKAS +int do_set_thread_area_skas(struct user_desc *info) { int ret; u32 cpu; @@ -29,7 +43,7 @@ int do_set_thread_area(struct user_desc *info) return ret; } -int do_get_thread_area(struct user_desc *info) +int do_get_thread_area_skas(struct user_desc *info) { int ret; u32 cpu; @@ -39,6 +53,7 @@ int do_get_thread_area(struct user_desc *info) put_cpu(); return ret; } +#endif /* * sys_get_thread_area: get a yet unused TLS descriptor index. @@ -67,8 +82,7 @@ static inline void clear_user_desc(struct user_desc* info) /* Postcondition: LDT_empty(info) returns true. */ memset(info, 0, sizeof(*info)); - /* - * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain + /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain * indeed an empty user_desc. */ info->read_exec_only = 1; @@ -83,13 +97,10 @@ static int load_TLS(int flags, struct task_struct *to) int idx; for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { - struct uml_tls_struct* curr = - &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; - /* - * Actually, now if it wasn't flushed it gets cleared and - * flushed to the host, which will clear it. - */ + /* Actually, now if it wasn't flushed it gets cleared and + * flushed to the host, which will clear it.*/ if (!curr->present) { if (!curr->flushed) { clear_user_desc(&curr->tls); @@ -113,8 +124,7 @@ static int load_TLS(int flags, struct task_struct *to) return ret; } -/* - * Verify if we need to do a flush for the new process, i.e. if there are any +/* Verify if we need to do a flush for the new process, i.e. if there are any * present desc's, only if they haven't been flushed. */ static inline int needs_TLS_update(struct task_struct *task) @@ -123,13 +133,10 @@ static inline int needs_TLS_update(struct task_struct *task) int ret = 0; for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = - &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - /* - * Can't test curr->present, we may need to clear a descriptor - * which had a value. - */ + /* Can't test curr->present, we may need to clear a descriptor + * which had a value. */ if (curr->flushed) continue; ret = 1; @@ -138,8 +145,7 @@ static inline int needs_TLS_update(struct task_struct *task) return ret; } -/* - * On a newly forked process, the TLS descriptors haven't yet been flushed. So +/* On a newly forked process, the TLS descriptors haven't yet been flushed. So * we mark them as such and the first switch_to will do the job. */ void clear_flushed_tls(struct task_struct *task) @@ -147,13 +153,10 @@ void clear_flushed_tls(struct task_struct *task) int i; for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = - &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - /* - * Still correct to do this, if it wasn't present on the host it - * will remain as flushed as it was. - */ + /* Still correct to do this, if it wasn't present on the host it + * will remain as flushed as it was. */ if (!curr->present) continue; @@ -161,33 +164,40 @@ void clear_flushed_tls(struct task_struct *task) } } -/* - * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a +/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a * common host process. So this is needed in SKAS0 too. * * However, if each thread had a different host process (and this was discussed * for SMP support) this won't be needed. * * And this will not need be used when (and if) we'll add support to the host - * SKAS patch. - */ + * SKAS patch. */ -int arch_switch_tls(struct task_struct *from, struct task_struct *to) +int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) { if (!host_supports_tls) return 0; - /* - * We have no need whatsoever to switch TLS for kernel threads; beyond + /* We have no need whatsoever to switch TLS for kernel threads; beyond * that, that would also result in us calling os_set_thread_area with - * userspace_pid[cpu] == 0, which gives an error. - */ + * userspace_pid[cpu] == 0, which gives an error. */ if (likely(to->mm)) return load_TLS(O_FORCE, to); return 0; } +int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to) +{ + if (!host_supports_tls) + return 0; + + if (needs_TLS_update(to)) + return load_TLS(0, to); + + return 0; +} + static int set_tls_entry(struct task_struct* task, struct user_desc *info, int idx, int flushed) { @@ -241,20 +251,17 @@ static int get_tls_entry(struct task_struct* task, struct user_desc *info, int i *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; out: - /* - * Temporary debugging check, to make sure that things have been + /* Temporary debugging check, to make sure that things have been * flushed. This could be triggered if load_TLS() failed. */ - if (unlikely(task == current && - !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { + if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { printk(KERN_ERR "get_tls_entry: task with pid %d got here " "without flushed TLS.", current->pid); } return 0; clear: - /* - * When the TLS entry has not been set, the values read to user in the + /* When the TLS entry has not been set, the values read to user in the * tls_array are 0 (because it's cleared at boot, see * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. */ @@ -286,7 +293,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) return -EFAULT; } - ret = do_set_thread_area(&info); + ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info); if (ret) return ret; return set_tls_entry(current, &info, idx, 1); @@ -356,10 +363,8 @@ int ptrace_get_thread_area(struct task_struct *child, int idx, } -/* - * XXX: This part is probably common to i386 and x86-64. Don't create a common - * file for now, do that when implementing x86-64 support. - */ +/* XXX: This part is probably common to i386 and x86-64. Don't create a common + * file for now, do that when implementing x86-64 support.*/ static int __init __setup_host_supports_tls(void) { check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); diff --git a/trunk/arch/um/sys-i386/unmap.c b/trunk/arch/um/sys-i386/unmap.c new file mode 100644 index 000000000000..1b0ad0e4adcd --- /dev/null +++ b/trunk/arch/um/sys-i386/unmap.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include + +static int errno; + +static inline _syscall2(int,munmap,void *,start,size_t,len) +static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) +int switcheroo(int fd, int prot, void *from, void *to, int size) +{ + if(munmap(to, size) < 0){ + return(-1); + } + if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ + return(-1); + } + if(munmap(from, size) < 0){ + return(-1); + } + return(0); +} diff --git a/trunk/arch/um/sys-i386/user-offsets.c b/trunk/arch/um/sys-i386/user-offsets.c index 514241526a1b..29118cf5ff25 100644 --- a/trunk/arch/um/sys-i386/user-offsets.c +++ b/trunk/arch/um/sys-i386/user-offsets.c @@ -2,9 +2,9 @@ #include #include #include -#include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -48,8 +48,8 @@ void foo(void) OFFSET(HOST_SC_FP_ST, _fpstate, _st); OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); - DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); - DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct)); + DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); + DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); DEFINE(HOST_IP, EIP); DEFINE(HOST_SP, UESP); diff --git a/trunk/arch/um/sys-ppc/Makefile b/trunk/arch/um/sys-ppc/Makefile index a9814a7ae60e..af200268fddb 100644 --- a/trunk/arch/um/sys-ppc/Makefile +++ b/trunk/arch/um/sys-ppc/Makefile @@ -1,7 +1,7 @@ OBJ = built-in.o .S.o: - $(CC) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ ptrace_user.o sysrq.o @@ -57,13 +57,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \ checksum.o: checksum.S rm -f asm ln -s $(TOPDIR)/include/asm-ppc asm - $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm misc.o: misc.S ppc_defs.h rm -f asm ln -s $(TOPDIR)/include/asm-ppc asm - $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c diff --git a/trunk/arch/um/sys-x86_64/Makefile b/trunk/arch/um/sys-x86_64/Makefile index 3c22de532088..ea8185d85404 100644 --- a/trunk/arch/um/sys-x86_64/Makefile +++ b/trunk/arch/um/sys-x86_64/Makefile @@ -5,9 +5,10 @@ # obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ - setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ - sysrq.o ksyms.o tls.o + setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ + ksyms.o tls.o +obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o obj-$(CONFIG_MODULES) += um_module.o subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o @@ -15,12 +16,16 @@ subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o ldt-y = ../sys-i386/ldt.o -USER_OBJS := ptrace_user.o +USER_OBJS := ptrace_user.o sigcontext.o USER_OBJS += user-offsets.s extra-y += user-offsets.s +extra-$(CONFIG_MODE_TT) += unmap.o + UNPROFILE_OBJS := stub_segv.o CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) include arch/um/scripts/Makefile.rules + +$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) diff --git a/trunk/arch/um/sys-x86_64/bugs.c b/trunk/arch/um/sys-x86_64/bugs.c index 506b6765bbcb..095478890371 100644 --- a/trunk/arch/um/sys-x86_64/bugs.c +++ b/trunk/arch/um/sys-x86_64/bugs.c @@ -14,7 +14,7 @@ void arch_check_bugs(void) { } -int arch_handle_signal(int sig, struct uml_pt_regs *regs) +int arch_handle_signal(int sig, union uml_pt_regs *regs) { return 0; } diff --git a/trunk/arch/um/sys-x86_64/fault.c b/trunk/arch/um/sys-x86_64/fault.c index ce85117fc64e..4636b1465b6c 100644 --- a/trunk/arch/um/sys-x86_64/fault.c +++ b/trunk/arch/um/sys-x86_64/fault.c @@ -14,15 +14,14 @@ struct exception_table_entry }; const struct exception_table_entry *search_exception_tables(unsigned long add); - -int arch_fixup(unsigned long address, struct uml_pt_regs *regs) +int arch_fixup(unsigned long address, union uml_pt_regs *regs) { const struct exception_table_entry *fixup; fixup = search_exception_tables(address); - if (fixup != 0) { + if(fixup != 0){ UPT_IP(regs) = fixup->fixup; - return 1; + return(1); } - return 0; + return(0); } diff --git a/trunk/arch/um/sys-x86_64/ptrace.c b/trunk/arch/um/sys-x86_64/ptrace.c index a3cfeed17af4..1970d78aa528 100644 --- a/trunk/arch/um/sys-x86_64/ptrace.c +++ b/trunk/arch/um/sys-x86_64/ptrace.c @@ -1,6 +1,5 @@ /* * Copyright 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * Licensed under the GPL */ @@ -13,10 +12,17 @@ #include #include -/* - * determines which flags the user has access to. - * 1 = access 0 = no access - */ +/* XXX x86_64 */ +unsigned long not_ss; +unsigned long not_ds; +unsigned long not_es; + +#define SC_SS(r) (not_ss) +#define SC_DS(r) (not_ds) +#define SC_ES(r) (not_es) + +/* determines which flags the user has access to. */ +/* 1 = access 0 = no access */ #define FLAG_MASK 0x44dd5UL int putreg(struct task_struct *child, int regno, unsigned long value) @@ -60,21 +66,20 @@ int putreg(struct task_struct *child, int regno, unsigned long value) int poke_user(struct task_struct *child, long addr, long data) { - if ((addr & 3) || addr < 0) - return -EIO; - - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if ((addr == 4) || (addr == 5)) - return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; + if ((addr & 3) || addr < 0) + return -EIO; + + if (addr < MAX_REG_OFFSET) + return putreg(child, addr, data); + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if((addr == 4) || (addr == 5)) return -EIO; + child->thread.arch.debugregs[addr] = data; + return 0; + } + return -EIO; } unsigned long getreg(struct task_struct *child, int regno) @@ -102,22 +107,29 @@ unsigned long getreg(struct task_struct *child, int regno) int peek_user(struct task_struct *child, long addr, long data) { /* read the word at location addr in the USER area. */ - unsigned long tmp; - - if ((addr & 3) || addr < 0) - return -EIO; + unsigned long tmp; + + if ((addr & 3) || addr < 0) + return -EIO; + + tmp = 0; /* Default return condition */ + if(addr < MAX_REG_OFFSET){ + tmp = getreg(child, addr); + } + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + tmp = child->thread.arch.debugregs[addr]; + } + return put_user(tmp, (unsigned long *) data); +} - tmp = 0; /* Default return condition */ - if (addr < MAX_REG_OFFSET){ - tmp = getreg(child, addr); - } - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - tmp = child->thread.arch.debugregs[addr]; - } - return put_user(tmp, (unsigned long *) data); +void arch_switch(void) +{ +/* XXX + printk("arch_switch\n"); +*/ } /* XXX Mostly copied from sys-i386 */ @@ -127,68 +139,54 @@ int is_syscall(unsigned long addr) int n; n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n){ + if(n){ /* access_process_vm() grants access to vsyscall and stub, * while copy_from_user doesn't. Maybe access_process_vm is * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if (n != sizeof(instr)) { + if(n != sizeof(instr)) { printk("is_syscall : failed to read instruction from " "0x%lx\n", addr); - return 1; + return(1); } } /* sysenter */ - return instr == 0x050f; + return(instr == 0x050f); } -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +int get_fpregs(unsigned long buf, struct task_struct *child) { - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; - - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fp_registers(userspace_pid[cpu], fpregs); - if (err) - return err; - - n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; - - return n; + panic("get_fpregs"); + return(0); } -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +int set_fpregs(unsigned long buf, struct task_struct *child) { - int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; - - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fp_registers(userspace_pid[cpu], fpregs); + panic("set_fpregs"); + return(0); } -long subarch_ptrace(struct task_struct *child, long request, long addr, - long data) +int get_fpxregs(unsigned long buf, struct task_struct *tsk) { - int ret = -EIO; - - switch (request) { - case PTRACE_GETFPXREGS: /* Get the child FPU state. */ - ret = get_fpregs((struct user_i387_struct __user *) data, - child); - break; - case PTRACE_SETFPXREGS: /* Set the child FPU state. */ - ret = set_fpregs((struct user_i387_struct __user *) data, - child); - break; - } + panic("get_fpxregs"); + return(0); +} - return ret; +int set_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + panic("set_fxpregs"); + return(0); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/sys-x86_64/sigcontext.c b/trunk/arch/um/sys-x86_64/sigcontext.c new file mode 100644 index 000000000000..c88e64def6f2 --- /dev/null +++ b/trunk/arch/um/sys-x86_64/sigcontext.c @@ -0,0 +1,39 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include +#include +#include +#include "user.h" + +void sc_to_sc(void *to_ptr, void *from_ptr) +{ + struct sigcontext *to = to_ptr, *from = from_ptr; + int size = sizeof(*to); /* + sizeof(struct _fpstate); */ + + memcpy(to, from, size); + if(from->fpstate != NULL) + to->fpstate = (struct _fpstate *) (to + 1); + + to->fpstate = NULL; +} + +unsigned long *sc_sigmask(void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + + return(&sc->oldmask); +} + +/* Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/sys-x86_64/signal.c b/trunk/arch/um/sys-x86_64/signal.c index 1778d33808f4..fe8ec04d35bb 100644 --- a/trunk/arch/um/sys-x86_64/signal.c +++ b/trunk/arch/um/sys-x86_64/signal.c @@ -1,121 +1,111 @@ /* * Copyright (C) 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#include "linux/stddef.h" +#include "linux/errno.h" #include "linux/personality.h" #include "linux/ptrace.h" -#include "asm/unistd.h" +#include "asm/current.h" #include "asm/uaccess.h" -#include "asm/ucontext.h" +#include "asm/sigcontext.h" +#include "asm/ptrace.h" +#include "asm/arch/ucontext.h" +#include "choose-mode.h" +#include "sysdep/ptrace.h" #include "frame_kern.h" + +#ifdef CONFIG_MODE_SKAS + #include "skas.h" -void copy_sc(struct uml_pt_regs *regs, void *from) +void copy_sc(union uml_pt_regs *regs, void *from) { struct sigcontext *sc = from; -#define GETREG(regs, regno, sc, regname) \ - (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname - - GETREG(regs, R8, sc, r8); - GETREG(regs, R9, sc, r9); - GETREG(regs, R10, sc, r10); - GETREG(regs, R11, sc, r11); - GETREG(regs, R12, sc, r12); - GETREG(regs, R13, sc, r13); - GETREG(regs, R14, sc, r14); - GETREG(regs, R15, sc, r15); - GETREG(regs, RDI, sc, rdi); - GETREG(regs, RSI, sc, rsi); - GETREG(regs, RBP, sc, rbp); - GETREG(regs, RBX, sc, rbx); - GETREG(regs, RDX, sc, rdx); - GETREG(regs, RAX, sc, rax); - GETREG(regs, RCX, sc, rcx); - GETREG(regs, RSP, sc, rsp); - GETREG(regs, RIP, sc, rip); - GETREG(regs, EFLAGS, sc, eflags); - GETREG(regs, CS, sc, cs); +#define GETREG(regs, regno, sc, regname) \ + (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname + + GETREG(regs, R8, sc, r8); + GETREG(regs, R9, sc, r9); + GETREG(regs, R10, sc, r10); + GETREG(regs, R11, sc, r11); + GETREG(regs, R12, sc, r12); + GETREG(regs, R13, sc, r13); + GETREG(regs, R14, sc, r14); + GETREG(regs, R15, sc, r15); + GETREG(regs, RDI, sc, rdi); + GETREG(regs, RSI, sc, rsi); + GETREG(regs, RBP, sc, rbp); + GETREG(regs, RBX, sc, rbx); + GETREG(regs, RDX, sc, rdx); + GETREG(regs, RAX, sc, rax); + GETREG(regs, RCX, sc, rcx); + GETREG(regs, RSP, sc, rsp); + GETREG(regs, RIP, sc, rip); + GETREG(regs, EFLAGS, sc, eflags); + GETREG(regs, CS, sc, cs); #undef GETREG } -static int copy_sc_from_user(struct pt_regs *regs, - struct sigcontext __user *from, - struct _fpstate __user *fpp) +static int copy_sc_from_user_skas(struct pt_regs *regs, + struct sigcontext __user *from) { - struct user_i387_struct fp; - int err = 0; - -#define GETREG(regs, regno, sc, regname) \ - __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) - - err |= GETREG(regs, R8, from, r8); - err |= GETREG(regs, R9, from, r9); - err |= GETREG(regs, R10, from, r10); - err |= GETREG(regs, R11, from, r11); - err |= GETREG(regs, R12, from, r12); - err |= GETREG(regs, R13, from, r13); - err |= GETREG(regs, R14, from, r14); - err |= GETREG(regs, R15, from, r15); - err |= GETREG(regs, RDI, from, rdi); - err |= GETREG(regs, RSI, from, rsi); - err |= GETREG(regs, RBP, from, rbp); - err |= GETREG(regs, RBX, from, rbx); - err |= GETREG(regs, RDX, from, rdx); - err |= GETREG(regs, RAX, from, rax); - err |= GETREG(regs, RCX, from, rcx); - err |= GETREG(regs, RSP, from, rsp); - err |= GETREG(regs, RIP, from, rip); - err |= GETREG(regs, EFLAGS, from, eflags); - err |= GETREG(regs, CS, from, cs); - if (err) - return 1; + int err = 0; + +#define GETREG(regs, regno, sc, regname) \ + __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= GETREG(regs, R8, from, r8); + err |= GETREG(regs, R9, from, r9); + err |= GETREG(regs, R10, from, r10); + err |= GETREG(regs, R11, from, r11); + err |= GETREG(regs, R12, from, r12); + err |= GETREG(regs, R13, from, r13); + err |= GETREG(regs, R14, from, r14); + err |= GETREG(regs, R15, from, r15); + err |= GETREG(regs, RDI, from, rdi); + err |= GETREG(regs, RSI, from, rsi); + err |= GETREG(regs, RBP, from, rbp); + err |= GETREG(regs, RBX, from, rbx); + err |= GETREG(regs, RDX, from, rdx); + err |= GETREG(regs, RAX, from, rax); + err |= GETREG(regs, RCX, from, rcx); + err |= GETREG(regs, RSP, from, rsp); + err |= GETREG(regs, RIP, from, rip); + err |= GETREG(regs, EFLAGS, from, eflags); + err |= GETREG(regs, CS, from, cs); #undef GETREG - err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct)); - if (err) - return 1; - - err = restore_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fp_registers failed, errno = %d\n", - -err); - return 1; - } - - return 0; + return err; } -static int copy_sc_to_user(struct sigcontext __user *to, - struct _fpstate __user *to_fp, struct pt_regs *regs, - unsigned long mask, unsigned long sp) +int copy_sc_to_user_skas(struct sigcontext __user *to, + struct _fpstate __user *to_fp, + struct pt_regs *regs, unsigned long mask, + unsigned long sp) { - struct faultinfo * fi = ¤t->thread.arch.faultinfo; - struct user_i387_struct fp; + struct faultinfo * fi = ¤t->thread.arch.faultinfo; int err = 0; err |= __put_user(0, &to->gs); err |= __put_user(0, &to->fs); -#define PUTREG(regs, regno, sc, regname) \ - __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) +#define PUTREG(regs, regno, sc, regname) \ + __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) err |= PUTREG(regs, RDI, to, rdi); err |= PUTREG(regs, RSI, to, rsi); err |= PUTREG(regs, RBP, to, rbp); - /* - * Must use orignal RSP, which is passed in, rather than what's in - * the pt_regs, because that's already been updated to point at the - * signal frame. - */ + /* Must use orignal RSP, which is passed in, rather than what's in + * the pt_regs, because that's already been updated to point at the + * signal frame. + */ err |= __put_user(sp, &to->rsp); err |= PUTREG(regs, RBX, to, rbx); err |= PUTREG(regs, RDX, to, rdx); @@ -131,38 +121,91 @@ static int copy_sc_to_user(struct sigcontext __user *to, err |= PUTREG(regs, R15, to, r15); err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ - err |= __put_user(fi->cr2, &to->cr2); - err |= __put_user(fi->error_code, &to->err); - err |= __put_user(fi->trap_no, &to->trapno); + err |= __put_user(fi->cr2, &to->cr2); + err |= __put_user(fi->error_code, &to->err); + err |= __put_user(fi->trap_no, &to->trapno); err |= PUTREG(regs, RIP, to, rip); err |= PUTREG(regs, EFLAGS, to, eflags); #undef PUTREG err |= __put_user(mask, &to->oldmask); - if (err) - return 1; - - err = save_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " - "failed, errno = %d\n", -err); - return 1; - } - if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) - return 1; + return(err); +} + +#endif +#ifdef CONFIG_MODE_TT +int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, + int fpsize) +{ + struct _fpstate *to_fp; + struct _fpstate __user *from_fp; + unsigned long sigs; + int err; + + to_fp = to->fpstate; + sigs = to->oldmask; + err = copy_from_user(to, from, sizeof(*to)); + from_fp = to->fpstate; + to->fpstate = to_fp; + to->oldmask = sigs; + if(to_fp != NULL) + err |= copy_from_user(to_fp, from_fp, fpsize); + return(err); +} + +int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, + struct sigcontext *from, int fpsize, unsigned long sp) +{ + struct _fpstate __user *to_fp; + struct _fpstate *from_fp; + int err; + + to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); + from_fp = from->fpstate; + err = copy_to_user(to, from, sizeof(*to)); + /* The SP in the sigcontext is the updated one for the signal + * delivery. The sp passed in is the original, and this needs + * to be restored, so we stick it in separately. + */ + err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); + + if(from_fp != NULL){ + err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); + err |= copy_to_user(to_fp, from_fp, fpsize); + } return err; } +#endif + +static int copy_sc_from_user(struct pt_regs *to, void __user *from) +{ + int ret; + + ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, + sizeof(struct _fpstate)), + copy_sc_from_user_skas(to, from)); + return(ret); +} + +static int copy_sc_to_user(struct sigcontext __user *to, + struct _fpstate __user *fp, + struct pt_regs *from, unsigned long mask, + unsigned long sp) +{ + return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), + sizeof(*fp), sp), + copy_sc_to_user_skas(to, fp, from, mask, sp))); +} + struct rt_sigframe { - char __user *pretcode; - struct ucontext uc; - struct siginfo info; - struct _fpstate fpstate; + char __user *pretcode; + struct ucontext uc; + struct siginfo info; }; #define round_down(m, n) (((m) / (n)) * (n)) @@ -172,6 +215,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, siginfo_t *info, sigset_t *set) { struct rt_sigframe __user *frame; + struct _fpstate __user *fp = NULL; unsigned long save_sp = PT_REGS_RSP(regs); int err = 0; struct task_struct *me = current; @@ -179,8 +223,15 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, frame = (struct rt_sigframe __user *) round_down(stack_top - sizeof(struct rt_sigframe), 16); /* Subtract 128 for a red zone and 8 for proper alignment */ - frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); + frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); + + if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) + goto out; +#if 0 /* XXX */ + if (save_i387(fp) < 0) + err |= -1; +#endif if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto out; @@ -190,8 +241,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, goto out; } - /* - * Update SP now because the page fault handler refuses to extend + /* Update SP now because the page fault handler refuses to extend * the stack if the faulting address is too far below the current * SP, which frame now certainly is. If there's an error, the original * value is restored on the way out. @@ -208,9 +258,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __put_user(sas_ss_flags(save_sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, - set->sig[0], save_sp); - err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); + err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0], + save_sp); + err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); @@ -219,10 +269,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - /* - * Set up to return from userspace. If provided, use a stub - * already in userspace. - */ + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ /* x86-64 should always use SA_RESTORER. */ if (ka->sa.sa_flags & SA_RESTORER) err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); @@ -244,10 +292,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, /* In case the signal handler was declared without prototypes */ PT_REGS_RAX(regs) = 0; - /* - * This also works for non SA_SIGINFO handlers because they expect the - * next argument after the signal number on the stack. - */ + /* This also works for non SA_SIGINFO handlers because they expect the + next argument after the signal number on the stack. */ PT_REGS_RSI(regs) = (unsigned long) &frame->info; PT_REGS_RDX(regs) = (unsigned long) &frame->uc; PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; @@ -267,7 +313,7 @@ long sys_rt_sigreturn(struct pt_regs *regs) struct ucontext __user *uc = &frame->uc; sigset_t set; - if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -277,15 +323,24 @@ long sys_rt_sigreturn(struct pt_regs *regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, - &frame->fpstate)) + if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) goto segfault; /* Avoid ERESTART handling */ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; - return PT_REGS_SYSCALL_RET(¤t->thread.regs); + return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); segfault: force_sig(SIGSEGV, current); return 0; } +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/sys-x86_64/stub.S b/trunk/arch/um/sys-x86_64/stub.S index 4afe204a6af7..03c279735784 100644 --- a/trunk/arch/um/sys-x86_64/stub.S +++ b/trunk/arch/um/sys-x86_64/stub.S @@ -1,5 +1,4 @@ #include "uml-config.h" -#include "as-layout.h" .globl syscall_stub .section .__syscall_stub, "x" @@ -8,18 +7,18 @@ syscall_stub: /* We don't have 64-bit constants, so this constructs the address * we need. */ - movq $(ASM_STUB_DATA >> 32), %rbx + movq $(UML_CONFIG_STUB_DATA >> 32), %rbx salq $32, %rbx - movq $(ASM_STUB_DATA & 0xffffffff), %rcx + movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx or %rcx, %rbx movq %rax, (%rbx) int3 .globl batch_syscall_stub batch_syscall_stub: - mov $(ASM_STUB_DATA >> 32), %rbx + mov $(UML_CONFIG_STUB_DATA >> 32), %rbx sal $32, %rbx - mov $(ASM_STUB_DATA & 0xffffffff), %rax + mov $(UML_CONFIG_STUB_DATA & 0xffffffff), %rax or %rax, %rbx /* load pointer to first operation */ mov %rbx, %rsp diff --git a/trunk/arch/um/sys-x86_64/stub_segv.c b/trunk/arch/um/sys-x86_64/stub_segv.c index 3afb590f0072..652fa34c2cd3 100644 --- a/trunk/arch/um/sys-x86_64/stub_segv.c +++ b/trunk/arch/um/sys-x86_64/stub_segv.c @@ -6,7 +6,6 @@ #include #include #include -#include "as-layout.h" #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" @@ -34,7 +33,7 @@ stub_segv_handler(int sig) int pid; __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), &uc->uc_mcontext); pid = stub_syscall0(__NR_getpid); diff --git a/trunk/arch/um/sys-x86_64/syscalls.c b/trunk/arch/um/sys-x86_64/syscalls.c index 86f6b18410ee..b3f6350cac44 100644 --- a/trunk/arch/um/sys-x86_64/syscalls.c +++ b/trunk/arch/um/sys-x86_64/syscalls.c @@ -1,36 +1,70 @@ /* - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright 2003 PathScale, Inc. * * Licensed under the GPL */ #include "linux/linkage.h" -#include "linux/personality.h" +#include "linux/slab.h" +#include "linux/shm.h" #include "linux/utsname.h" -#include "asm/prctl.h" /* XXX This should get the constants from libc */ +#include "linux/personality.h" #include "asm/uaccess.h" +#define __FRAME_OFFSETS +#include "asm/ptrace.h" +#include "asm/unistd.h" +#include "asm/prctl.h" /* XXX This should get the constants from libc */ +#include "choose-mode.h" +#include "kern.h" #include "os.h" asmlinkage long sys_uname64(struct new_utsname __user * name) { int err; - down_read(&uts_sem); err = copy_to_user(name, utsname(), sizeof (*name)); up_read(&uts_sem); - if (personality(current->personality) == PER_LINUX32) err |= copy_to_user(&name->machine, "i686", 5); - return err ? -EFAULT : 0; } -long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) +#ifdef CONFIG_MODE_TT +extern long arch_prctl(int code, unsigned long addr); + +static long arch_prctl_tt(int code, unsigned long addr) +{ + unsigned long tmp; + long ret; + + switch(code){ + case ARCH_SET_GS: + case ARCH_SET_FS: + ret = arch_prctl(code, addr); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + ret = arch_prctl(code, (unsigned long) &tmp); + if(!ret) + ret = put_user(tmp, (long __user *)addr); + break; + default: + ret = -EINVAL; + break; + } + + return(ret); +} +#endif + +#ifdef CONFIG_MODE_SKAS + +long arch_prctl_skas(struct task_struct *task, int code, + unsigned long __user *addr) { - unsigned long *ptr = addr, tmp; + unsigned long *ptr = addr, tmp; long ret; - int pid = task->mm->context.id.u.pid; + int pid = task->mm->context.skas.id.u.pid; /* * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to @@ -45,50 +79,52 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) * arch_prctl is run on the host, then the registers are read * back. */ - switch (code) { + switch(code){ case ARCH_SET_FS: case ARCH_SET_GS: - restore_registers(pid, ¤t->thread.regs.regs); - break; - case ARCH_GET_FS: - case ARCH_GET_GS: - /* - * With these two, we read to a local pointer and - * put_user it to the userspace pointer that we were - * given. If addr isn't valid (because it hasn't been - * faulted in or is just bogus), we want put_user to - * fault it in (or return -EFAULT) instead of having - * the host return -EFAULT. - */ - ptr = &tmp; - } + restore_registers(pid, ¤t->thread.regs.regs); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + /* + * With these two, we read to a local pointer and + * put_user it to the userspace pointer that we were + * given. If addr isn't valid (because it hasn't been + * faulted in or is just bogus), we want put_user to + * fault it in (or return -EFAULT) instead of having + * the host return -EFAULT. + */ + ptr = &tmp; + } - ret = os_arch_prctl(pid, code, ptr); - if (ret) - return ret; + ret = os_arch_prctl(pid, code, ptr); + if(ret) + return ret; - switch (code) { + switch(code){ case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_SET_GS: - save_registers(pid, ¤t->thread.regs.regs); + save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: ret = put_user(tmp, addr); - break; + break; case ARCH_GET_GS: ret = put_user(tmp, addr); - break; + break; } return ret; } +#endif long sys_arch_prctl(int code, unsigned long addr) { - return arch_prctl(current, code, (unsigned long __user *) addr); + return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code, + (unsigned long __user *) addr); } long sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -105,10 +141,10 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, return ret; } -void arch_switch_to(struct task_struct *from, struct task_struct *to) +void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) { - if ((to->thread.arch.fs == 0) || (to->mm == NULL)) - return; + if((to->thread.arch.fs == 0) || (to->mm == NULL)) + return; - arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); + arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); } diff --git a/trunk/arch/um/sys-x86_64/tls.c b/trunk/arch/um/sys-x86_64/tls.c index f7ba46200ecd..febbc94be25f 100644 --- a/trunk/arch/um/sys-x86_64/tls.c +++ b/trunk/arch/um/sys-x86_64/tls.c @@ -11,7 +11,7 @@ int arch_copy_tls(struct task_struct *t) * (which is argument 5, child_tid, of clone) so it can be set * during context switches. */ - t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; + t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)]; - return 0; + return 0; } diff --git a/trunk/arch/um/sys-x86_64/unmap.c b/trunk/arch/um/sys-x86_64/unmap.c new file mode 100644 index 000000000000..f4a4bffd8a18 --- /dev/null +++ b/trunk/arch/um/sys-x86_64/unmap.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include + +static int errno; + +static inline _syscall2(int,munmap,void *,start,size_t,len) +static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) +int switcheroo(int fd, int prot, void *from, void *to, int size) +{ + if(munmap(to, size) < 0){ + return(-1); + } + if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ + return(-1); + } + if(munmap(from, size) < 0){ + return(-1); + } + return(0); +} diff --git a/trunk/arch/um/sys-x86_64/user-offsets.c b/trunk/arch/um/sys-x86_64/user-offsets.c index f1ef2a8dfbc6..0d5fd764c21f 100644 --- a/trunk/arch/um/sys-x86_64/user-offsets.c +++ b/trunk/arch/um/sys-x86_64/user-offsets.c @@ -3,10 +3,17 @@ #include #include #include -#include #define __FRAME_OFFSETS #include #include +/* For some reason, x86_64 defines u64 and u32 only in , which I + * refuse to include here, even though they're used throughout the headers. + * These are used in asm/user.h, and that include can't be avoided because of + * the sizeof(struct user_regs_struct) below. + */ +typedef __u64 u64; +typedef __u32 u32; +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) diff --git a/trunk/arch/v850/Makefile b/trunk/arch/v850/Makefile index 8b629df0029a..8be9aacb20a7 100644 --- a/trunk/arch/v850/Makefile +++ b/trunk/arch/v850/Makefile @@ -16,11 +16,11 @@ arch_dir = arch/v850 -KBUILD_CFLAGS += -mv850e +CFLAGS += -mv850e # r16 is a fixed pointer to the current task -KBUILD_CFLAGS += -ffixed-r16 -mno-prolog-function -KBUILD_CFLAGS += -fno-builtin -KBUILD_CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\" +CFLAGS += -ffixed-r16 -mno-prolog-function +CFLAGS += -fno-builtin +CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\" # By default, build a kernel that runs on the gdb v850 simulator. KBUILD_DEFCONFIG := sim_defconfig diff --git a/trunk/arch/v850/kernel/fpga85e2c.c b/trunk/arch/v850/kernel/fpga85e2c.c index ab9cf16a85c8..5c4923558a75 100644 --- a/trunk/arch/v850/kernel/fpga85e2c.c +++ b/trunk/arch/v850/kernel/fpga85e2c.c @@ -160,8 +160,5 @@ static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs) static int reg_snap_dev_id; static struct irqaction reg_snap_action = { - .handler = make_reg_snap, - .mask = CPU_MASK_NONE, - .name = "reg_snap", - .dev_id = ®_snap_dev_id, + make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", ®_snap_dev_id, 0 }; diff --git a/trunk/arch/v850/kernel/time.c b/trunk/arch/v850/kernel/time.c index d810c93fe665..f0905b03523b 100644 --- a/trunk/arch/v850/kernel/time.c +++ b/trunk/arch/v850/kernel/time.c @@ -92,11 +92,12 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs) static int timer_dev_id; static struct irqaction timer_irqaction = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "timer", - .dev_id = &timer_dev_id, + timer_interrupt, + IRQF_DISABLED, + CPU_MASK_NONE, + "timer", + &timer_dev_id, + NULL }; void time_init (void) diff --git a/trunk/arch/x86/boot/Makefile b/trunk/arch/x86/boot/Makefile index e8756e5f6b29..cb1035f2b7e9 100644 --- a/trunk/arch/x86/boot/Makefile +++ b/trunk/arch/x86/boot/Makefile @@ -50,7 +50,7 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE) # that way we can complain to the user if the CPU is insufficient. cflags-i386 := cflags-x86_64 := -m32 -KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ +CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ $(cflags-$(ARCH)) \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ @@ -61,13 +61,13 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ $(call cc-option, -fno-unit-at-a-time)) \ $(call cc-option, -fno-stack-protector) \ $(call cc-option, -mpreferred-stack-boundary=2) -KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ $(obj)/zImage: IMAGE_OFFSET := 0x1000 -$(obj)/zImage: asflags-y := $(SVGA_MODE) $(RAMDISK) +$(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) $(obj)/bzImage: IMAGE_OFFSET := 0x100000 -$(obj)/bzImage: ccflags-y := -D__BIG_KERNEL__ -$(obj)/bzImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__ +$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: BUILDFLAGS := -b quiet_cmd_image = BUILD $@ diff --git a/trunk/arch/x86/boot/compressed/Makefile_32 b/trunk/arch/x86/boot/compressed/Makefile_32 index e43ff7c56e6e..22613c652d22 100644 --- a/trunk/arch/x86/boot/compressed/Makefile_32 +++ b/trunk/arch/x86/boot/compressed/Makefile_32 @@ -11,7 +11,7 @@ EXTRA_AFLAGS := -traditional LDFLAGS_vmlinux := -T hostprogs-y := relocs -KBUILD_CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ +CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ -fno-strict-aliasing -fPIC \ $(call cc-option,-ffreestanding) \ $(call cc-option,-fno-stack-protector) diff --git a/trunk/arch/x86/boot/compressed/Makefile_64 b/trunk/arch/x86/boot/compressed/Makefile_64 index 7801e8dd90b2..dc6b3380cc45 100644 --- a/trunk/arch/x86/boot/compressed/Makefile_64 +++ b/trunk/arch/x86/boot/compressed/Makefile_64 @@ -6,11 +6,11 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz head_64.o misc_64.o piggy.o -KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \ +CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \ -fno-strict-aliasing -fPIC -mcmodel=small \ $(call cc-option, -ffreestanding) \ $(call cc-option, -fno-stack-protector) -KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ LDFLAGS := -m elf_x86_64 LDFLAGS_vmlinux := -T diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/trunk/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 2ca43ba32bc0..ffd01e5dcb52 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -595,7 +595,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) dmi_check_system(sw_any_bug_dmi_table); if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) { policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; - policy->cpus = per_cpu(cpu_core_map, cpu); + policy->cpus = cpu_core_map[cpu]; } #endif diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/trunk/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 793eae854f4f..8eb414b906d2 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -200,7 +200,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) unsigned int i; #ifdef CONFIG_SMP - policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); + policy->cpus = cpu_sibling_map[policy->cpu]; #endif /* Errata workaround */ diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/trunk/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index c06ac680c9ca..b273b69cfddf 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -57,7 +57,7 @@ static struct powernow_k8_data *powernow_data[NR_CPUS]; static int cpu_family = CPU_OPTERON; #ifndef CONFIG_SMP -DEFINE_PER_CPU(cpumask_t, cpu_core_map); +static cpumask_t cpu_core_map[1]; #endif /* Return a frequency in MHz, given an input fid */ @@ -667,7 +667,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); data->powernow_table = powernow_table; - if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) + if (first_cpu(cpu_core_map[data->cpu]) == data->cpu) print_basics(data); for (j = 0; j < data->numps; j++) @@ -821,7 +821,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* fill in data */ data->numps = data->acpi_data.state_count; - if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) + if (first_cpu(cpu_core_map[data->cpu]) == data->cpu) print_basics(data); powernow_k8_acpi_pst_values(data, 0); @@ -1214,7 +1214,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) if (cpu_family == CPU_HW_PSTATE) pol->cpus = cpumask_of_cpu(pol->cpu); else - pol->cpus = per_cpu(cpu_core_map, pol->cpu); + pol->cpus = cpu_core_map[pol->cpu]; data->available_cores = &(pol->cpus); /* Take a crude guess here. @@ -1281,7 +1281,7 @@ static unsigned int powernowk8_get (unsigned int cpu) cpumask_t oldmask = current->cpus_allowed; unsigned int khz = 0; - data = powernow_data[first_cpu(per_cpu(cpu_core_map, cpu))]; + data = powernow_data[first_cpu(cpu_core_map[cpu])]; if (!data) return -EINVAL; diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 14d68aa301ee..36685e8f7be1 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c @@ -322,7 +322,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* only run on CPU to be set, or on its sibling */ #ifdef CONFIG_SMP - policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); + policy->cpus = cpu_sibling_map[policy->cpu]; #endif cpus_allowed = current->cpus_allowed; diff --git a/trunk/arch/x86/kernel/cpu/proc.c b/trunk/arch/x86/kernel/cpu/proc.c index 879a0f789b1e..1e31b6caffb1 100644 --- a/trunk/arch/x86/kernel/cpu/proc.c +++ b/trunk/arch/x86/kernel/cpu/proc.c @@ -122,8 +122,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_X86_HT if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); - seq_printf(m, "siblings\t: %d\n", - cpus_weight(per_cpu(cpu_core_map, n))); + seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } diff --git a/trunk/arch/x86/kernel/io_apic_32.c b/trunk/arch/x86/kernel/io_apic_32.c index 4ee1e5ee9b57..e2f4a1c68547 100644 --- a/trunk/arch/x86/kernel/io_apic_32.c +++ b/trunk/arch/x86/kernel/io_apic_32.c @@ -378,7 +378,7 @@ static struct irq_cpu_info { #define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask) -#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i))) +#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) static cpumask_t balance_irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL @@ -598,7 +598,7 @@ static void do_irq_balance(void) * (A+B)/2 vs B */ load = CPU_IRQ(min_loaded) >> 1; - for_each_cpu_mask(j, per_cpu(cpu_sibling_map, min_loaded)) { + for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) { if (load > CPU_IRQ(j)) { /* This won't change cpu_sibling_map[min_loaded] */ load = CPU_IRQ(j); diff --git a/trunk/arch/x86/kernel/kprobes_32.c b/trunk/arch/x86/kernel/kprobes_32.c index 90f778c04b3f..e7d0d3c2ef64 100644 --- a/trunk/arch/x86/kernel/kprobes_32.c +++ b/trunk/arch/x86/kernel/kprobes_32.c @@ -41,13 +41,6 @@ void jprobe_return_end(void); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = { - {"__switch_to", }, /* This function switches only current task, but - doesn't switch kernel stack.*/ - {NULL, NULL} /* Terminator */ -}; -const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); - /* insert a jmp code */ static __always_inline void set_jmp_op(void *from, void *to) { @@ -591,7 +584,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) return 1; } -int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -673,6 +666,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_GPF: + case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ preempt_disable(); if (kprobe_running() && diff --git a/trunk/arch/x86/kernel/kprobes_64.c b/trunk/arch/x86/kernel/kprobes_64.c index 681b801c5e26..62e28e52d784 100644 --- a/trunk/arch/x86/kernel/kprobes_64.c +++ b/trunk/arch/x86/kernel/kprobes_64.c @@ -48,13 +48,6 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -struct kretprobe_blackpoint kretprobe_blacklist[] = { - {"__switch_to", }, /* This function switches only current task, but - doesn't switch kernel stack.*/ - {NULL, NULL} /* Terminator */ -}; -const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); - /* * returns non-zero if opcode modifies the interrupt flag. */ @@ -664,6 +657,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_GPF: + case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ preempt_disable(); if (kprobe_running() && diff --git a/trunk/arch/x86/kernel/mce_amd_64.c b/trunk/arch/x86/kernel/mce_amd_64.c index 805b62b1e0df..2f8a7f18b0fe 100644 --- a/trunk/arch/x86/kernel/mce_amd_64.c +++ b/trunk/arch/x86/kernel/mce_amd_64.c @@ -472,7 +472,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifdef CONFIG_SMP if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) { /* symlink */ - i = first_cpu(per_cpu(cpu_core_map, cpu)); + i = first_cpu(cpu_core_map[cpu]); /* first core not up yet */ if (cpu_data[i].cpu_core_id) @@ -492,7 +492,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out; - b->cpus = per_cpu(cpu_core_map, cpu); + b->cpus = cpu_core_map[cpu]; per_cpu(threshold_banks, cpu)[bank] = b; goto out; } @@ -509,7 +509,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifndef CONFIG_SMP b->cpus = CPU_MASK_ALL; #else - b->cpus = per_cpu(cpu_core_map, cpu); + b->cpus = cpu_core_map[cpu]; #endif err = kobject_register(&b->kobj); if (err) diff --git a/trunk/arch/x86/kernel/pci-calgary_64.c b/trunk/arch/x86/kernel/pci-calgary_64.c index a50b787b3bfa..71da01e73f03 100644 --- a/trunk/arch/x86/kernel/pci-calgary_64.c +++ b/trunk/arch/x86/kernel/pci-calgary_64.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -385,32 +384,31 @@ static void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems, int direction) { struct iommu_table *tbl = find_iommu_table(dev); - struct scatterlist *s; - int i; if (!translate_phb(to_pci_dev(dev))) return; - for_each_sg(sglist, s, nelems, i) { + while (nelems--) { unsigned int npages; - dma_addr_t dma = s->dma_address; - unsigned int dmalen = s->dma_length; + dma_addr_t dma = sglist->dma_address; + unsigned int dmalen = sglist->dma_length; if (dmalen == 0) break; npages = num_dma_pages(dma, dmalen); iommu_free(tbl, dma, npages); + sglist++; } } static int calgary_nontranslate_map_sg(struct device* dev, struct scatterlist *sg, int nelems, int direction) { - struct scatterlist *s; int i; - for_each_sg(sg, s, nelems, i) { + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; BUG_ON(!s->page); s->dma_address = virt_to_bus(page_address(s->page) +s->offset); s->dma_length = s->length; @@ -422,7 +420,6 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg, int nelems, int direction) { struct iommu_table *tbl = find_iommu_table(dev); - struct scatterlist *s; unsigned long vaddr; unsigned int npages; unsigned long entry; @@ -431,7 +428,8 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg, if (!translate_phb(to_pci_dev(dev))) return calgary_nontranslate_map_sg(dev, sg, nelems, direction); - for_each_sg(sg, s, nelems, i) { + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; BUG_ON(!s->page); vaddr = (unsigned long)page_address(s->page) + s->offset; @@ -456,9 +454,9 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg, return nelems; error: calgary_unmap_sg(dev, sg, nelems, direction); - for_each_sg(sg, s, nelems, i) { - sg->dma_address = bad_dma_address; - sg->dma_length = 0; + for (i = 0; i < nelems; i++) { + sg[i].dma_address = bad_dma_address; + sg[i].dma_length = 0; } return 0; } diff --git a/trunk/arch/x86/kernel/pci-gart_64.c b/trunk/arch/x86/kernel/pci-gart_64.c index cfcc84e6c350..4918c575d582 100644 --- a/trunk/arch/x86/kernel/pci-gart_64.c +++ b/trunk/arch/x86/kernel/pci-gart_64.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -279,10 +278,10 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, */ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { - struct scatterlist *s; int i; - for_each_sg(sg, s, nents, i) { + for (i = 0; i < nents; i++) { + struct scatterlist *s = &sg[i]; if (!s->dma_length || !s->length) break; gart_unmap_single(dev, s->dma_address, s->dma_length, dir); @@ -293,14 +292,14 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, int nents, int dir) { - struct scatterlist *s; int i; #ifdef CONFIG_IOMMU_DEBUG printk(KERN_DEBUG "dma_map_sg overflow\n"); #endif - for_each_sg(sg, s, nents, i) { + for (i = 0; i < nents; i++ ) { + struct scatterlist *s = &sg[i]; unsigned long addr = page_to_phys(s->page) + s->offset; if (nonforced_iommu(dev, addr, s->length)) { addr = dma_map_area(dev, addr, s->length, dir); @@ -320,23 +319,23 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, } /* Map multiple scatterlist entries continuous into the first. */ -static int __dma_map_cont(struct scatterlist *start, int nelems, +static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages) { unsigned long iommu_start = alloc_iommu(pages); unsigned long iommu_page = iommu_start; - struct scatterlist *s; int i; if (iommu_start == -1) return -1; - - for_each_sg(start, s, nelems, i) { + + for (i = start; i < stopat; i++) { + struct scatterlist *s = &sg[i]; unsigned long pages, addr; unsigned long phys_addr = s->dma_address; - BUG_ON(s != start && s->offset); - if (s == start) { + BUG_ON(i > start && s->offset); + if (i == start) { *sout = *s; sout->dma_address = iommu_bus_base; sout->dma_address += iommu_page*PAGE_SIZE + s->offset; @@ -358,17 +357,17 @@ static int __dma_map_cont(struct scatterlist *start, int nelems, return 0; } -static inline int dma_map_cont(struct scatterlist *start, int nelems, +static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages, int need) { - if (!need) { - BUG_ON(nelems != 1); - *sout = *start; - sout->dma_length = start->length; + if (!need) { + BUG_ON(stopat - start != 1); + *sout = sg[start]; + sout->dma_length = sg[start].length; return 0; - } - return __dma_map_cont(start, nelems, sout, pages); + } + return __dma_map_cont(sg, start, stopat, sout, pages); } /* @@ -382,7 +381,6 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) int start; unsigned long pages = 0; int need = 0, nextneed; - struct scatterlist *s, *ps, *start_sg, *sgmap; if (nents == 0) return 0; @@ -392,9 +390,8 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) out = 0; start = 0; - start_sg = sgmap = sg; - ps = NULL; /* shut up gcc */ - for_each_sg(sg, s, nents, i) { + for (i = 0; i < nents; i++) { + struct scatterlist *s = &sg[i]; dma_addr_t addr = page_to_phys(s->page) + s->offset; s->dma_address = addr; BUG_ON(s->length == 0); @@ -403,33 +400,29 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) /* Handle the previous not yet processed entries */ if (i > start) { + struct scatterlist *ps = &sg[i-1]; /* Can only merge when the last chunk ends on a page boundary and the new one doesn't have an offset. */ if (!iommu_merge || !nextneed || !need || s->offset || - (ps->offset + ps->length) % PAGE_SIZE) { - if (dma_map_cont(start_sg, i - start, sgmap, - pages, need) < 0) + (ps->offset + ps->length) % PAGE_SIZE) { + if (dma_map_cont(sg, start, i, sg+out, pages, + need) < 0) goto error; out++; - sgmap = sg_next(sgmap); pages = 0; - start = i; - start_sg = s; + start = i; } } need = nextneed; pages += to_pages(s->offset, s->length); - ps = s; } - if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0) + if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; flush_gart(); - if (out < nents) { - sgmap = sg_next(sgmap); - sgmap->dma_length = 0; - } + if (out < nents) + sg[out].dma_length = 0; return out; error: @@ -444,8 +437,8 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) if (panic_on_overflow) panic("dma_map_sg: overflow on %lu pages\n", pages); iommu_full(dev, pages << PAGE_SHIFT, dir); - for_each_sg(sg, s, nents, i) - s->dma_address = bad_dma_address; + for (i = 0; i < nents; i++) + sg[i].dma_address = bad_dma_address; return 0; } diff --git a/trunk/arch/x86/kernel/pci-nommu_64.c b/trunk/arch/x86/kernel/pci-nommu_64.c index e85d4360360c..2a34c6c025a9 100644 --- a/trunk/arch/x86/kernel/pci-nommu_64.c +++ b/trunk/arch/x86/kernel/pci-nommu_64.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -58,10 +57,10 @@ static void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size, static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction) { - struct scatterlist *s; int i; - for_each_sg(sg, s, nents, i) { + for (i = 0; i < nents; i++ ) { + struct scatterlist *s = &sg[i]; BUG_ON(!s->page); s->dma_address = virt_to_bus(page_address(s->page) +s->offset); if (!check_addr("map_sg", hwdev, s->dma_address, s->length)) diff --git a/trunk/arch/x86/kernel/process_64.c b/trunk/arch/x86/kernel/process_64.c index 6309b275cb9c..7352d4b377e6 100644 --- a/trunk/arch/x86/kernel/process_64.c +++ b/trunk/arch/x86/kernel/process_64.c @@ -581,7 +581,7 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, * * Kprobes not supported here. Set the probe on schedule instead. */ -struct task_struct * +__kprobes struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, diff --git a/trunk/arch/x86/kernel/ptrace_32.c b/trunk/arch/x86/kernel/ptrace_32.c index 8622b9cd3e38..0cecd7513c97 100644 --- a/trunk/arch/x86/kernel/ptrace_32.c +++ b/trunk/arch/x86/kernel/ptrace_32.c @@ -524,6 +524,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; + case PTRACE_DETACH: + /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, datap, FRAME_SIZE*sizeof(long))) { ret = -EIO; diff --git a/trunk/arch/x86/kernel/ptrace_64.c b/trunk/arch/x86/kernel/ptrace_64.c index 86321ee6da93..c0cac42df3b6 100644 --- a/trunk/arch/x86/kernel/ptrace_64.c +++ b/trunk/arch/x86/kernel/ptrace_64.c @@ -500,6 +500,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; + case PTRACE_DETACH: + /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, sizeof(struct user_regs_struct))) { diff --git a/trunk/arch/x86/kernel/setup_64.c b/trunk/arch/x86/kernel/setup_64.c index 85b5b6310acc..b7da90e79c78 100644 --- a/trunk/arch/x86/kernel/setup_64.c +++ b/trunk/arch/x86/kernel/setup_64.c @@ -1070,8 +1070,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (smp_num_siblings * c->x86_max_cores > 1) { int cpu = c - cpu_data; seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); - seq_printf(m, "siblings\t: %d\n", - cpus_weight(per_cpu(cpu_core_map, cpu))); + seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu])); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } diff --git a/trunk/arch/x86/kernel/smpboot_32.c b/trunk/arch/x86/kernel/smpboot_32.c index 31fc08bd15ef..e4f61d1c6248 100644 --- a/trunk/arch/x86/kernel/smpboot_32.c +++ b/trunk/arch/x86/kernel/smpboot_32.c @@ -70,12 +70,12 @@ EXPORT_SYMBOL(smp_num_siblings); int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; /* representing HT siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); -EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_core_map); -EXPORT_PER_CPU_SYMBOL(cpu_core_map); +cpumask_t cpu_core_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_core_map); /* bitmap of online cpus */ cpumask_t cpu_online_map __read_mostly; @@ -300,7 +300,7 @@ cpumask_t cpu_coregroup_map(int cpu) * And for power savings, we return cpu_core_map */ if (sched_mc_power_savings || sched_smt_power_savings) - return per_cpu(cpu_core_map, cpu); + return cpu_core_map[cpu]; else return c->llc_shared_map; } @@ -319,22 +319,22 @@ void __cpuinit set_cpu_sibling_map(int cpu) for_each_cpu_mask(i, cpu_sibling_setup_map) { if (c[cpu].phys_proc_id == c[i].phys_proc_id && c[cpu].cpu_core_id == c[i].cpu_core_id) { - cpu_set(i, per_cpu(cpu_sibling_map, cpu)); - cpu_set(cpu, per_cpu(cpu_sibling_map, i)); - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); + cpu_set(i, cpu_core_map[cpu]); + cpu_set(cpu, cpu_core_map[i]); cpu_set(i, c[cpu].llc_shared_map); cpu_set(cpu, c[i].llc_shared_map); } } } else { - cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, cpu_sibling_map[cpu]); } cpu_set(cpu, c[cpu].llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { - per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); + cpu_core_map[cpu] = cpu_sibling_map[cpu]; c[cpu].booted_cores = 1; return; } @@ -346,17 +346,17 @@ void __cpuinit set_cpu_sibling_map(int cpu) cpu_set(cpu, c[i].llc_shared_map); } if (c[cpu].phys_proc_id == c[i].phys_proc_id) { - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); + cpu_set(i, cpu_core_map[cpu]); + cpu_set(cpu, cpu_core_map[i]); /* * Does this new cpu bringup a new core? */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) { + if (cpus_weight(cpu_sibling_map[cpu]) == 1) { /* * for each core in package, increment * the booted_cores for this new cpu */ - if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) + if (first_cpu(cpu_sibling_map[i]) == i) c[cpu].booted_cores++; /* * increment the core count for all @@ -983,8 +983,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); map_cpu_to_logical_apicid(); - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); return; } @@ -1008,8 +1008,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); return; } @@ -1023,8 +1023,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); return; } @@ -1102,16 +1102,16 @@ static void __init smp_boot_cpus(unsigned int max_cpus) Dprintk("Boot done.\n"); /* - * construct cpu_sibling_map, so that we can tell sibling CPUs + * construct cpu_sibling_map[], so that we can tell sibling CPUs * efficiently. */ for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - cpus_clear(per_cpu(cpu_core_map, cpu)); + cpus_clear(cpu_sibling_map[cpu]); + cpus_clear(cpu_core_map[cpu]); } - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); smpboot_setup_io_apic(); @@ -1148,19 +1148,19 @@ void remove_siblinginfo(int cpu) int sibling; struct cpuinfo_x86 *c = cpu_data; - for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { - cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); - /*/ + for_each_cpu_mask(sibling, cpu_core_map[cpu]) { + cpu_clear(cpu, cpu_core_map[sibling]); + /* * last thread sibling in this cpu core going down */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) + if (cpus_weight(cpu_sibling_map[cpu]) == 1) c[sibling].booted_cores--; } - for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) - cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - cpus_clear(per_cpu(cpu_core_map, cpu)); + for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) + cpu_clear(cpu, cpu_sibling_map[sibling]); + cpus_clear(cpu_sibling_map[cpu]); + cpus_clear(cpu_core_map[cpu]); c[cpu].phys_proc_id = 0; c[cpu].cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); diff --git a/trunk/arch/x86/kernel/smpboot_64.c b/trunk/arch/x86/kernel/smpboot_64.c index 0faa0a0af272..720a7d1f8862 100644 --- a/trunk/arch/x86/kernel/smpboot_64.c +++ b/trunk/arch/x86/kernel/smpboot_64.c @@ -91,12 +91,12 @@ EXPORT_SYMBOL(cpu_data); int smp_threads_ready; /* representing HT siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); -EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_core_map); -EXPORT_PER_CPU_SYMBOL(cpu_core_map); +cpumask_t cpu_core_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_core_map); /* * Trampoline 80x86 program as an array. @@ -243,7 +243,7 @@ cpumask_t cpu_coregroup_map(int cpu) * And for power savings, we return cpu_core_map */ if (sched_mc_power_savings || sched_smt_power_savings) - return per_cpu(cpu_core_map, cpu); + return cpu_core_map[cpu]; else return c->llc_shared_map; } @@ -262,22 +262,22 @@ static inline void set_cpu_sibling_map(int cpu) for_each_cpu_mask(i, cpu_sibling_setup_map) { if (c[cpu].phys_proc_id == c[i].phys_proc_id && c[cpu].cpu_core_id == c[i].cpu_core_id) { - cpu_set(i, per_cpu(cpu_sibling_map, cpu)); - cpu_set(cpu, per_cpu(cpu_sibling_map, i)); - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); + cpu_set(i, cpu_core_map[cpu]); + cpu_set(cpu, cpu_core_map[i]); cpu_set(i, c[cpu].llc_shared_map); cpu_set(cpu, c[i].llc_shared_map); } } } else { - cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, cpu_sibling_map[cpu]); } cpu_set(cpu, c[cpu].llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { - per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); + cpu_core_map[cpu] = cpu_sibling_map[cpu]; c[cpu].booted_cores = 1; return; } @@ -289,17 +289,17 @@ static inline void set_cpu_sibling_map(int cpu) cpu_set(cpu, c[i].llc_shared_map); } if (c[cpu].phys_proc_id == c[i].phys_proc_id) { - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); + cpu_set(i, cpu_core_map[cpu]); + cpu_set(cpu, cpu_core_map[i]); /* * Does this new cpu bringup a new core? */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) { + if (cpus_weight(cpu_sibling_map[cpu]) == 1) { /* * for each core in package, increment * the booted_cores for this new cpu */ - if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) + if (first_cpu(cpu_sibling_map[i]) == i) c[cpu].booted_cores++; /* * increment the core count for all @@ -735,8 +735,8 @@ static __init void disable_smp(void) phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); else phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); } #ifdef CONFIG_HOTPLUG_CPU @@ -971,19 +971,19 @@ static void remove_siblinginfo(int cpu) int sibling; struct cpuinfo_x86 *c = cpu_data; - for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { - cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); + for_each_cpu_mask(sibling, cpu_core_map[cpu]) { + cpu_clear(cpu, cpu_core_map[sibling]); /* * last thread sibling in this cpu core going down */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) + if (cpus_weight(cpu_sibling_map[cpu]) == 1) c[sibling].booted_cores--; } - for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) - cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - cpus_clear(per_cpu(cpu_core_map, cpu)); + for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) + cpu_clear(cpu, cpu_sibling_map[sibling]); + cpus_clear(cpu_sibling_map[cpu]); + cpus_clear(cpu_core_map[cpu]); c[cpu].phys_proc_id = 0; c[cpu].cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); diff --git a/trunk/arch/x86/math-emu/Makefile b/trunk/arch/x86/math-emu/Makefile index 9b0c63b60302..9c943fa6ce6b 100644 --- a/trunk/arch/x86/math-emu/Makefile +++ b/trunk/arch/x86/math-emu/Makefile @@ -5,7 +5,8 @@ #DEBUG = -DDEBUGGING DEBUG = PARANOID = -DPARANOID -EXTRA_CFLAGS := $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION) +CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION) + EXTRA_AFLAGS := $(PARANOID) # From 'C' language sources: diff --git a/trunk/arch/x86/mm/fault_32.c b/trunk/arch/x86/mm/fault_32.c index c686ae20fd6b..fcb38e7f3543 100644 --- a/trunk/arch/x86/mm/fault_32.c +++ b/trunk/arch/x86/mm/fault_32.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -33,27 +32,33 @@ extern void die(const char *,struct pt_regs *,long); -#ifdef CONFIG_KPROBES -static inline int notify_page_fault(struct pt_regs *regs) +static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +int register_page_fault_notifier(struct notifier_block *nb) { - int ret = 0; - - /* kprobe_running() needs smp_processor_id() */ - if (!user_mode_vm(regs)) { - preempt_disable(); - if (kprobe_running() && kprobe_fault_handler(regs, 14)) - ret = 1; - preempt_enable(); - } + vmalloc_sync_all(); + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} +EXPORT_SYMBOL_GPL(register_page_fault_notifier); - return ret; +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); } -#else -static inline int notify_page_fault(struct pt_regs *regs) +EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); + +static inline int notify_page_fault(struct pt_regs *regs, long err) { - return 0; + struct die_args args = { + .regs = regs, + .str = "page fault", + .err = err, + .trapnr = 14, + .signr = SIGSEGV + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, + DIE_PAGE_FAULT, &args); } -#endif /* * Return EIP plus the CS segment base. The segment limit is also @@ -326,7 +331,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, if (unlikely(address >= TASK_SIZE)) { if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) return; - if (notify_page_fault(regs)) + if (notify_page_fault(regs, error_code) == NOTIFY_STOP) return; /* * Don't take the mm semaphore here. If we fixup a prefetch @@ -335,7 +340,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area_nosemaphore; } - if (notify_page_fault(regs)) + if (notify_page_fault(regs, error_code) == NOTIFY_STOP) return; /* It's safe to allow irq's after cr2 has been saved and the vmalloc @@ -593,7 +598,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, } printk("VM: killing process %s\n", tsk->comm); if (error_code & 4) - do_group_exit(SIGKILL); + do_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/trunk/arch/x86/mm/fault_64.c b/trunk/arch/x86/mm/fault_64.c index 5e0e54906c48..54816adb8e93 100644 --- a/trunk/arch/x86/mm/fault_64.c +++ b/trunk/arch/x86/mm/fault_64.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -41,27 +40,34 @@ #define PF_RSVD (1<<3) #define PF_INSTR (1<<4) -#ifdef CONFIG_KPROBES -static inline int notify_page_fault(struct pt_regs *regs) +static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) { - int ret = 0; - - /* kprobe_running() needs smp_processor_id() */ - if (!user_mode(regs)) { - preempt_disable(); - if (kprobe_running() && kprobe_fault_handler(regs, 14)) - ret = 1; - preempt_enable(); - } + vmalloc_sync_all(); + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} +EXPORT_SYMBOL_GPL(register_page_fault_notifier); - return ret; +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); } -#else -static inline int notify_page_fault(struct pt_regs *regs) +EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); + +static inline int notify_page_fault(struct pt_regs *regs, long err) { - return 0; + struct die_args args = { + .regs = regs, + .str = "page fault", + .err = err, + .trapnr = 14, + .signr = SIGSEGV + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, + DIE_PAGE_FAULT, &args); } -#endif /* Sometimes the CPU reports invalid exceptions on prefetch. Check that here and ignore. @@ -339,7 +345,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, if (vmalloc_fault(address) >= 0) return; } - if (notify_page_fault(regs)) + if (notify_page_fault(regs, error_code) == NOTIFY_STOP) return; /* * Don't take the mm semaphore here. If we fixup a prefetch @@ -348,7 +354,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area_nosemaphore; } - if (notify_page_fault(regs)) + if (notify_page_fault(regs, error_code) == NOTIFY_STOP) return; if (likely(regs->eflags & X86_EFLAGS_IF)) diff --git a/trunk/arch/x86/mm/init_32.c b/trunk/arch/x86/mm/init_32.c index dda4e83649a0..730a5b177b1f 100644 --- a/trunk/arch/x86/mm/init_32.c +++ b/trunk/arch/x86/mm/init_32.c @@ -735,6 +735,11 @@ int arch_add_memory(int nid, u64 start, u64 size) return __add_pages(zone, start_pfn, nr_pages); } +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); #endif struct kmem_cache *pmd_cache; diff --git a/trunk/arch/x86/mm/init_64.c b/trunk/arch/x86/mm/init_64.c index 1e3862e41065..458893b376f8 100644 --- a/trunk/arch/x86/mm/init_64.c +++ b/trunk/arch/x86/mm/init_64.c @@ -474,6 +474,12 @@ int arch_add_memory(int nid, u64 start, u64 size) } EXPORT_SYMBOL_GPL(arch_add_memory); +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); + #if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA) int memory_add_physaddr_to_nid(u64 start) { @@ -742,48 +748,3 @@ const char *arch_vma_name(struct vm_area_struct *vma) return "[vsyscall]"; return NULL; } - -#ifdef CONFIG_SPARSEMEM_VMEMMAP -/* - * Initialise the sparsemem vmemmap using huge-pages at the PMD level. - */ -int __meminit vmemmap_populate(struct page *start_page, - unsigned long size, int node) -{ - unsigned long addr = (unsigned long)start_page; - unsigned long end = (unsigned long)(start_page + size); - unsigned long next; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - - for (; addr < end; addr = next) { - next = pmd_addr_end(addr, end); - - pgd = vmemmap_pgd_populate(addr, node); - if (!pgd) - return -ENOMEM; - pud = vmemmap_pud_populate(pgd, addr, node); - if (!pud) - return -ENOMEM; - - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) { - pte_t entry; - void *p = vmemmap_alloc_block(PMD_SIZE, node); - if (!p) - return -ENOMEM; - - entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL); - mk_pte_huge(entry); - set_pmd(pmd, __pmd(pte_val(entry))); - - printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n", - addr, addr + PMD_SIZE - 1, p, node); - } else - vmemmap_verify((pte_t *)pmd, node, addr, next); - } - - return 0; -} -#endif diff --git a/trunk/arch/x86/oprofile/op_model_p4.c b/trunk/arch/x86/oprofile/op_model_p4.c index 56b4757a1f47..47925927b12f 100644 --- a/trunk/arch/x86/oprofile/op_model_p4.c +++ b/trunk/arch/x86/oprofile/op_model_p4.c @@ -379,7 +379,7 @@ static unsigned int get_stagger(void) { #ifdef CONFIG_SMP int cpu = smp_processor_id(); - return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); + return (cpu != first_cpu(cpu_sibling_map[cpu])); #endif return 0; } diff --git a/trunk/arch/x86/vdso/Makefile b/trunk/arch/x86/vdso/Makefile index dcd6bb9e0bb3..8d03de029d9b 100644 --- a/trunk/arch/x86/vdso/Makefile +++ b/trunk/arch/x86/vdso/Makefile @@ -34,8 +34,8 @@ $(obj)/vdso.so: $(src)/vdso.lds $(vobjs) FORCE CFL := $(PROFILING) -mcmodel=small -fPIC -g0 -O2 -fasynchronous-unwind-tables -m64 -$(obj)/vclock_gettime.o: KBUILD_CFLAGS = $(CFL) -$(obj)/vgetcpu.o: KBUILD_CFLAGS = $(CFL) +$(obj)/vclock_gettime.o: CFLAGS = $(CFL) +$(obj)/vgetcpu.o: CFLAGS = $(CFL) # We also create a special relocatable object that should mirror the symbol # table and layout of the linked DSO. With ld -R we can then refer to diff --git a/trunk/arch/x86/xen/smp.c b/trunk/arch/x86/xen/smp.c index 4fa33c27ccb6..557b8e24706a 100644 --- a/trunk/arch/x86/xen/smp.c +++ b/trunk/arch/x86/xen/smp.c @@ -147,13 +147,8 @@ void __init xen_smp_prepare_boot_cpu(void) make_lowmem_page_readwrite(&per_cpu__gdt_page); for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - /* - * cpu_core_map lives in a per cpu area that is cleared - * when the per cpu array is allocated. - * - * cpus_clear(per_cpu(cpu_core_map, cpu)); - */ + cpus_clear(cpu_sibling_map[cpu]); + cpus_clear(cpu_core_map[cpu]); } xen_setup_vcpu_info_placement(); @@ -164,13 +159,8 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus) unsigned cpu; for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - /* - * cpu_core_ map will be zeroed when the per - * cpu area is allocated. - * - * cpus_clear(per_cpu(cpu_core_map, cpu)); - */ + cpus_clear(cpu_sibling_map[cpu]); + cpus_clear(cpu_core_map[cpu]); } smp_store_cpu_info(0); diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index 8c83dbe4c4d0..cf013cb85ea4 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -409,7 +409,6 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y depends on (NUMA || EXPERIMENTAL) - select SPARSEMEM_VMEMMAP_ENABLE config ARCH_MEMORY_PROBE def_bool y diff --git a/trunk/arch/x86_64/Makefile b/trunk/arch/x86_64/Makefile index 9daa32d1d2a1..8bffb94c71b5 100644 --- a/trunk/arch/x86_64/Makefile +++ b/trunk/arch/x86_64/Makefile @@ -61,18 +61,18 @@ cflags-y += -maccumulate-outgoing-args # do binutils support CFI? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) -KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector ) cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector-all ) -KBUILD_CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) CFLAGS_KERNEL += $(cflags-kernel-y) -KBUILD_AFLAGS += -m64 +AFLAGS += -m64 head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task_64.o diff --git a/trunk/arch/xtensa/Makefile b/trunk/arch/xtensa/Makefile index 56685a883347..acf05be24929 100644 --- a/trunk/arch/xtensa/Makefile +++ b/trunk/arch/xtensa/Makefile @@ -28,9 +28,11 @@ PLATFORM = $(platform-y) export PLATFORM # temporarily until string.h is fixed -KBUILD_CFLAGS += -ffreestanding +cflags-y += -ffreestanding -KBUILD_CFLAGS += -pipe -mlongcalls +cflags-y += -pipe -mlongcalls + +CFLAGS += $(cflags-y) KBUILD_DEFCONFIG := iss_defconfig @@ -54,7 +56,7 @@ endif # -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) head-y := arch/xtensa/kernel/head.o core-y += arch/xtensa/kernel/ arch/xtensa/mm/ diff --git a/trunk/arch/xtensa/boot/Makefile b/trunk/arch/xtensa/boot/Makefile index 9c5185f605b6..820b31d10ae4 100644 --- a/trunk/arch/xtensa/boot/Makefile +++ b/trunk/arch/xtensa/boot/Makefile @@ -8,12 +8,13 @@ # -EXTRA_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include +CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include HOSTFLAGS += -Iarch/$(ARCH)/boot/include BIG_ENDIAN := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#") -export EXTRA_CFLAGS +export CFLAGS +export AFLAGS export BIG_ENDIAN subdir-y := lib diff --git a/trunk/arch/xtensa/boot/boot-redboot/Makefile b/trunk/arch/xtensa/boot/boot-redboot/Makefile index 74d15d08077b..f53262c2e1f3 100644 --- a/trunk/arch/xtensa/boot/boot-redboot/Makefile +++ b/trunk/arch/xtensa/boot/boot-redboot/Makefile @@ -19,7 +19,7 @@ boot-y := bootstrap.o OBJS := $(addprefix $(obj)/,$(boot-y)) LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) zImage: vmlinux $(OBJS) $(LIBS) $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \ diff --git a/trunk/arch/xtensa/kernel/ptrace.c b/trunk/arch/xtensa/kernel/ptrace.c index 5533c7850d53..06a13d9b69db 100644 --- a/trunk/arch/xtensa/kernel/ptrace.c +++ b/trunk/arch/xtensa/kernel/ptrace.c @@ -304,6 +304,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data); break; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + default: ret = ptrace_request(child, request, addr, data); goto out; diff --git a/trunk/arch/xtensa/mm/fault.c b/trunk/arch/xtensa/mm/fault.c index 2f842859948f..45d28f217c03 100644 --- a/trunk/arch/xtensa/mm/fault.c +++ b/trunk/arch/xtensa/mm/fault.c @@ -152,7 +152,7 @@ void do_page_fault(struct pt_regs *regs) } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); bad_page_fault(regs, address, SIGKILL); return; diff --git a/trunk/block/blktrace.c b/trunk/block/blktrace.c index d00ac3993c18..775471ef84a5 100644 --- a/trunk/block/blktrace.c +++ b/trunk/block/blktrace.c @@ -550,7 +550,7 @@ static void blk_trace_set_ht_offsets(void) for_each_online_cpu(cpu) { unsigned long long *cpu_off, *sibling_off; - for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) { + for_each_cpu_mask(i, cpu_sibling_map[cpu]) { if (i == cpu) continue; diff --git a/trunk/block/bsg.c b/trunk/block/bsg.c index 8e181ab3afb9..b8ddfc66f210 100644 --- a/trunk/block/bsg.c +++ b/trunk/block/bsg.c @@ -908,7 +908,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } -static const struct file_operations bsg_fops = { +static struct file_operations bsg_fops = { .read = bsg_read, .write = bsg_write, .poll = bsg_poll, diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 952aee04a68a..b9c518afe1f8 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -712,14 +712,6 @@ struct request *elv_next_request(struct request_queue *q) int ret; while ((rq = __elv_next_request(q)) != NULL) { - /* - * Kill the empty barrier place holder, the driver must - * not ever see it. - */ - if (blk_empty_barrier(rq)) { - end_queued_request(rq, 1); - continue; - } if (!(rq->cmd_flags & REQ_STARTED)) { /* * This is the first time the device driver @@ -759,8 +751,15 @@ struct request *elv_next_request(struct request_queue *q) rq = NULL; break; } else if (ret == BLKPREP_KILL) { + int nr_bytes = rq->hard_nr_sectors << 9; + + if (!nr_bytes) + nr_bytes = rq->data_len; + + blkdev_dequeue_request(rq); rq->cmd_flags |= REQ_QUIET; - end_queued_request(rq, 0); + end_that_request_chunk(rq, 0, nr_bytes); + end_that_request_last(rq, 0); } else { printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__, ret); diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 9eabac95fbe0..d875673e76cd 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -30,7 +30,6 @@ #include #include #include -#include /* * for max sense size @@ -305,6 +304,23 @@ int blk_queue_ordered(struct request_queue *q, unsigned ordered, EXPORT_SYMBOL(blk_queue_ordered); +/** + * blk_queue_issue_flush_fn - set function for issuing a flush + * @q: the request queue + * @iff: the function to be called issuing the flush + * + * Description: + * If a driver supports issuing a flush command, the support is notified + * to the block layer by defining it through this call. + * + **/ +void blk_queue_issue_flush_fn(struct request_queue *q, issue_flush_fn *iff) +{ + q->issue_flush_fn = iff; +} + +EXPORT_SYMBOL(blk_queue_issue_flush_fn); + /* * Cache flushing for ordered writes handling */ @@ -361,12 +377,10 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) /* * Okay, sequence complete. */ - uptodate = 1; - if (q->orderr) - uptodate = q->orderr; + rq = q->orig_bar_rq; + uptodate = q->orderr ? q->orderr : 1; q->ordseq = 0; - rq = q->orig_bar_rq; end_that_request_first(rq, uptodate, rq->hard_nr_sectors); end_that_request_last(rq, uptodate); @@ -431,8 +445,7 @@ static inline struct request *start_ordered(struct request_queue *q, rq_init(q, rq); if (bio_data_dir(q->orig_bar_rq->bio) == WRITE) rq->cmd_flags |= REQ_RW; - if (q->ordered & QUEUE_ORDERED_FUA) - rq->cmd_flags |= REQ_FUA; + rq->cmd_flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0; rq->elevator_private = NULL; rq->elevator_private2 = NULL; init_request_from_bio(rq, q->orig_bar_rq->bio); @@ -442,12 +455,9 @@ static inline struct request *start_ordered(struct request_queue *q, * Queue ordered sequence. As we stack them at the head, we * need to queue in reverse order. Note that we rely on that * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs - * request gets inbetween ordered sequence. If this request is - * an empty barrier, we don't need to do a postflush ever since - * there will be no data written between the pre and post flush. - * Hence a single flush will suffice. + * request gets inbetween ordered sequence. */ - if ((q->ordered & QUEUE_ORDERED_POSTFLUSH) && !blk_empty_barrier(rq)) + if (q->ordered & QUEUE_ORDERED_POSTFLUSH) queue_flush(q, QUEUE_ORDERED_POSTFLUSH); else q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH; @@ -471,7 +481,7 @@ static inline struct request *start_ordered(struct request_queue *q, int blk_do_ordered(struct request_queue *q, struct request **rqp) { struct request *rq = *rqp; - const int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); + int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); if (!q->ordseq) { if (!is_barrier) @@ -1319,10 +1329,9 @@ static int blk_hw_contig_segment(struct request_queue *q, struct bio *bio, * must make sure sg can hold rq->nr_phys_segments entries */ int blk_rq_map_sg(struct request_queue *q, struct request *rq, - struct scatterlist *sglist) + struct scatterlist *sg) { struct bio_vec *bvec, *bvprv; - struct scatterlist *next_sg, *sg; struct req_iterator iter; int nsegs, cluster; @@ -1333,12 +1342,11 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, * for each bio in rq */ bvprv = NULL; - sg = next_sg = &sglist[0]; rq_for_each_segment(bvec, rq, iter) { int nbytes = bvec->bv_len; if (bvprv && cluster) { - if (sg->length + nbytes > q->max_segment_size) + if (sg[nsegs - 1].length + nbytes > q->max_segment_size) goto new_segment; if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) @@ -1346,15 +1354,14 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) goto new_segment; - sg->length += nbytes; + sg[nsegs - 1].length += nbytes; } else { new_segment: - sg = next_sg; - next_sg = sg_next(sg); + memset(&sg[nsegs],0,sizeof(struct scatterlist)); + sg[nsegs].page = bvec->bv_page; + sg[nsegs].length = nbytes; + sg[nsegs].offset = bvec->bv_offset; - sg->page = bvec->bv_page; - sg->length = nbytes; - sg->offset = bvec->bv_offset; nsegs++; } bvprv = bvec; @@ -2653,14 +2660,6 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, EXPORT_SYMBOL(blk_execute_rq); -static void bio_end_empty_barrier(struct bio *bio, int err) -{ - if (err) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - - complete(bio->bi_private); -} - /** * blkdev_issue_flush - queue a flush * @bdev: blockdev to issue flush for @@ -2673,10 +2672,7 @@ static void bio_end_empty_barrier(struct bio *bio, int err) */ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) { - DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q; - struct bio *bio; - int ret; if (bdev->bd_disk == NULL) return -ENXIO; @@ -2684,32 +2680,10 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) q = bdev_get_queue(bdev); if (!q) return -ENXIO; + if (!q->issue_flush_fn) + return -EOPNOTSUPP; - bio = bio_alloc(GFP_KERNEL, 0); - if (!bio) - return -ENOMEM; - - bio->bi_end_io = bio_end_empty_barrier; - bio->bi_private = &wait; - bio->bi_bdev = bdev; - submit_bio(1 << BIO_RW_BARRIER, bio); - - wait_for_completion(&wait); - - /* - * The driver must store the error location in ->bi_sector, if - * it supports it. For non-stacked drivers, this should be copied - * from rq->sector. - */ - if (error_sector) - *error_sector = bio->bi_sector; - - ret = 0; - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - - bio_put(bio); - return ret; + return q->issue_flush_fn(q, bdev->bd_disk, error_sector); } EXPORT_SYMBOL(blkdev_issue_flush); @@ -3077,7 +3051,7 @@ static inline void blk_partition_remap(struct bio *bio) { struct block_device *bdev = bio->bi_bdev; - if (bio_sectors(bio) && bdev != bdev->bd_contains) { + if (bdev != bdev->bd_contains) { struct hd_struct *p = bdev->bd_part; const int rw = bio_data_dir(bio); @@ -3143,35 +3117,6 @@ static inline int should_fail_request(struct bio *bio) #endif /* CONFIG_FAIL_MAKE_REQUEST */ -/* - * Check whether this bio extends beyond the end of the device. - */ -static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) -{ - sector_t maxsector; - - if (!nr_sectors) - return 0; - - /* Test device or partition size, when known. */ - maxsector = bio->bi_bdev->bd_inode->i_size >> 9; - if (maxsector) { - sector_t sector = bio->bi_sector; - - if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { - /* - * This may well happen - the kernel calls bread() - * without checking the size of the device, e.g., when - * mounting a device. - */ - handle_bad_sector(bio); - return 1; - } - } - - return 0; -} - /** * generic_make_request: hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. @@ -3199,14 +3144,27 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) static inline void __generic_make_request(struct bio *bio) { struct request_queue *q; + sector_t maxsector; sector_t old_sector; int ret, nr_sectors = bio_sectors(bio); dev_t old_dev; might_sleep(); + /* Test device or partition size, when known. */ + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; - if (bio_check_eod(bio, nr_sectors)) - goto end_io; + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - the kernel calls bread() + * without checking the size of the device, e.g., when + * mounting a device. + */ + handle_bad_sector(bio); + goto end_io; + } + } /* * Resolve the mapping until finished. (drivers are @@ -3233,7 +3191,7 @@ static inline void __generic_make_request(struct bio *bio) break; } - if (unlikely(nr_sectors > q->max_hw_sectors)) { + if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) { printk("bio too big device %s (%u > %u)\n", bdevname(bio->bi_bdev, b), bio_sectors(bio), @@ -3254,7 +3212,7 @@ static inline void __generic_make_request(struct bio *bio) blk_partition_remap(bio); if (old_sector != -1) - blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, + blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, old_sector); blk_add_trace_bio(q, bio, BLK_TA_QUEUE); @@ -3262,8 +3220,21 @@ static inline void __generic_make_request(struct bio *bio) old_sector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev; - if (bio_check_eod(bio, nr_sectors)) - goto end_io; + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; + + if (maxsector < nr_sectors || + maxsector - nr_sectors < sector) { + /* + * This may well happen - partitions are not + * checked to make sure they are within the size + * of the whole device. + */ + handle_bad_sector(bio); + goto end_io; + } + } ret = q->make_request_fn(q, bio); } while (ret); @@ -3336,32 +3307,23 @@ void submit_bio(int rw, struct bio *bio) { int count = bio_sectors(bio); + BIO_BUG_ON(!bio->bi_size); + BIO_BUG_ON(!bio->bi_io_vec); bio->bi_rw |= rw; + if (rw & WRITE) { + count_vm_events(PGPGOUT, count); + } else { + task_io_account_read(bio->bi_size); + count_vm_events(PGPGIN, count); + } - /* - * If it's a regular read/write or a barrier with data attached, - * go through the normal accounting stuff before submission. - */ - if (!bio_empty_barrier(bio)) { - - BIO_BUG_ON(!bio->bi_size); - BIO_BUG_ON(!bio->bi_io_vec); - - if (rw & WRITE) { - count_vm_events(PGPGOUT, count); - } else { - task_io_account_read(bio->bi_size); - count_vm_events(PGPGIN, count); - } - - if (unlikely(block_dump)) { - char b[BDEVNAME_SIZE]; - printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", - current->comm, current->pid, - (rw & WRITE) ? "WRITE" : "READ", - (unsigned long long)bio->bi_sector, - bdevname(bio->bi_bdev,b)); - } + if (unlikely(block_dump)) { + char b[BDEVNAME_SIZE]; + printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", + current->comm, current->pid, + (rw & WRITE) ? "WRITE" : "READ", + (unsigned long long)bio->bi_sector, + bdevname(bio->bi_bdev,b)); } generic_make_request(bio); @@ -3437,14 +3399,6 @@ static int __end_that_request_first(struct request *req, int uptodate, while ((bio = req->bio) != NULL) { int nbytes; - /* - * For an empty barrier request, the low level driver must - * store a potential error location in ->sector. We pass - * that back up in ->bi_sector. - */ - if (blk_empty_barrier(req)) - bio->bi_sector = req->sector; - if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; @@ -3610,7 +3564,7 @@ static struct notifier_block blk_cpu_notifier __cpuinitdata = { * Description: * Ends all I/O on a request. It does not handle partial completions, * unless the driver actually implements this in its completion callback - * through requeueing. The actual completion happens out-of-order, + * through requeueing. Theh actual completion happens out-of-order, * through a softirq handler. The user must have registered a completion * callback through blk_queue_softirq_done(). **/ @@ -3673,83 +3627,15 @@ void end_that_request_last(struct request *req, int uptodate) EXPORT_SYMBOL(end_that_request_last); -static inline void __end_request(struct request *rq, int uptodate, - unsigned int nr_bytes, int dequeue) +void end_request(struct request *req, int uptodate) { - if (!end_that_request_chunk(rq, uptodate, nr_bytes)) { - if (dequeue) - blkdev_dequeue_request(rq); - add_disk_randomness(rq->rq_disk); - end_that_request_last(rq, uptodate); + if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) { + add_disk_randomness(req->rq_disk); + blkdev_dequeue_request(req); + end_that_request_last(req, uptodate); } } -static unsigned int rq_byte_size(struct request *rq) -{ - if (blk_fs_request(rq)) - return rq->hard_nr_sectors << 9; - - return rq->data_len; -} - -/** - * end_queued_request - end all I/O on a queued request - * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag - * - * Description: - * Ends all I/O on a request, and removes it from the block layer queues. - * Not suitable for normal IO completion, unless the driver still has - * the request attached to the block layer. - * - **/ -void end_queued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, rq_byte_size(rq), 1); -} -EXPORT_SYMBOL(end_queued_request); - -/** - * end_dequeued_request - end all I/O on a dequeued request - * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag - * - * Description: - * Ends all I/O on a request. The request must already have been - * dequeued using blkdev_dequeue_request(), as is normally the case - * for most drivers. - * - **/ -void end_dequeued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, rq_byte_size(rq), 0); -} -EXPORT_SYMBOL(end_dequeued_request); - - -/** - * end_request - end I/O on the current segment of the request - * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag - * - * Description: - * Ends I/O on the current segment of a request. If that is the only - * remaining segment, the request is also completed and freed. - * - * This is a remnant of how older block drivers handled IO completions. - * Modern drivers typically end IO on the full request in one go, unless - * they have a residual value to account for. For that case this function - * isn't really useful, unless the residual just happens to be the - * full current segment. In other words, don't use this function in new - * code. Either use end_request_completely(), or the - * end_that_request_chunk() (along with end_that_request_last()) for - * partial completions. - * - **/ -void end_request(struct request *req, int uptodate) -{ - __end_request(req, uptodate, req->hard_cur_sectors << 9, 1); -} EXPORT_SYMBOL(end_request); static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, @@ -4042,6 +3928,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) max_hw_sectors_kb = q->max_hw_sectors >> 1, page_kb = 1 << (PAGE_CACHE_SHIFT - 10); ssize_t ret = queue_var_store(&max_sectors_kb, page, count); + int ra_kb; if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb) return -EINVAL; @@ -4050,6 +3937,14 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) * values synchronously: */ spin_lock_irq(q->queue_lock); + /* + * Trim readahead window as well, if necessary: + */ + ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); + if (ra_kb > max_sectors_kb) + q->backing_dev_info.ra_pages = + max_sectors_kb >> (PAGE_CACHE_SHIFT - 10); + q->max_sectors = max_sectors_kb << 1; spin_unlock_irq(q->queue_lock); @@ -4063,23 +3958,7 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) return queue_var_show(max_hw_sectors_kb, (page)); } -static ssize_t queue_max_segments_show(struct request_queue *q, char *page) -{ - return queue_var_show(q->max_phys_segments, page); -} - -static ssize_t queue_max_segments_store(struct request_queue *q, - const char *page, size_t count) -{ - unsigned long segments; - ssize_t ret = queue_var_store(&segments, page, count); - - spin_lock_irq(q->queue_lock); - q->max_phys_segments = segments; - spin_unlock_irq(q->queue_lock); - return ret; -} static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, .show = queue_requests_show, @@ -4103,12 +3982,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = { .show = queue_max_hw_sectors_show, }; -static struct queue_sysfs_entry queue_max_segments_entry = { - .attr = {.name = "max_segments", .mode = S_IRUGO | S_IWUSR }, - .show = queue_max_segments_show, - .store = queue_max_segments_store, -}; - static struct queue_sysfs_entry queue_iosched_entry = { .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, .show = elv_iosched_show, @@ -4120,7 +3993,6 @@ static struct attribute *default_attrs[] = { &queue_ra_entry.attr, &queue_max_hw_sectors_entry.attr, &queue_max_sectors_entry.attr, - &queue_max_segments_entry.attr, &queue_iosched_entry.attr, NULL, }; diff --git a/trunk/crypto/digest.c b/trunk/crypto/digest.c index e56de6748b15..1bf7414aeb9e 100644 --- a/trunk/crypto/digest.c +++ b/trunk/crypto/digest.c @@ -77,7 +77,7 @@ static int update2(struct hash_desc *desc, if (!nbytes) break; - sg = scatterwalk_sg_next(sg); + sg = sg_next(sg); } return 0; diff --git a/trunk/crypto/scatterwalk.c b/trunk/crypto/scatterwalk.c index d6852c33cfb7..3052f6507f53 100644 --- a/trunk/crypto/scatterwalk.c +++ b/trunk/crypto/scatterwalk.c @@ -62,7 +62,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out, walk->offset += PAGE_SIZE - 1; walk->offset &= PAGE_MASK; if (walk->offset >= walk->sg->offset + walk->sg->length) - scatterwalk_start(walk, scatterwalk_sg_next(walk->sg)); + scatterwalk_start(walk, sg_next(walk->sg)); } } diff --git a/trunk/crypto/scatterwalk.h b/trunk/crypto/scatterwalk.h index 9c73e37a42ce..500a220ad908 100644 --- a/trunk/crypto/scatterwalk.h +++ b/trunk/crypto/scatterwalk.h @@ -20,7 +20,7 @@ #include "internal.h" -static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg) +static inline struct scatterlist *sg_next(struct scatterlist *sg) { return (++sg)->length ? sg : (void *)sg->page; } diff --git a/trunk/drivers/Kconfig b/trunk/drivers/Kconfig index 4fb134d50da7..7bdae47d6b91 100644 --- a/trunk/drivers/Kconfig +++ b/trunk/drivers/Kconfig @@ -84,8 +84,6 @@ source "drivers/rtc/Kconfig" source "drivers/dma/Kconfig" -source "drivers/dca/Kconfig" - source "drivers/auxdisplay/Kconfig" source "drivers/kvm/Kconfig" diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index 174c27eb4430..a168eacdcd9c 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ -obj-$(CONFIG_DCA) += dca/ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index bbaa545ea999..68699b3e7998 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -1410,7 +1410,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc) */ unsigned ata_exec_internal_sg(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, - int dma_dir, struct scatterlist *sgl, + int dma_dir, struct scatterlist *sg, unsigned int n_elem, unsigned long timeout) { struct ata_link *link = dev->link; @@ -1472,12 +1472,11 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { unsigned int i, buflen = 0; - struct scatterlist *sg; - for_each_sg(sgl, sg, n_elem, i) - buflen += sg->length; + for (i = 0; i < n_elem; i++) + buflen += sg[i].length; - ata_sg_init(qc, sgl, n_elem); + ata_sg_init(qc, sg, n_elem); qc->nbytes = buflen; } @@ -4293,7 +4292,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) if (qc->n_elem) dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); /* restore last sg */ - sg_last(sg, qc->orig_n_elem)->length += qc->pad_len; + sg[qc->orig_n_elem - 1].length += qc->pad_len; if (pad_buf) { struct scatterlist *psg = &qc->pad_sgent; void *addr = kmap_atomic(psg->page, KM_IRQ0); @@ -4548,7 +4547,6 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) qc->orig_n_elem = 1; qc->buf_virt = buf; qc->nbytes = buflen; - qc->cursg = qc->__sg; sg_init_one(&qc->sgent, buf, buflen); } @@ -4574,7 +4572,6 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, qc->__sg = sg; qc->n_elem = n_elem; qc->orig_n_elem = n_elem; - qc->cursg = qc->__sg; } /** @@ -4664,7 +4661,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg = qc->__sg; - struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem); + struct scatterlist *lsg = &sg[qc->n_elem - 1]; int n_elem, pre_n_elem, dir, trim_sg = 0; VPRINTK("ENTER, ata%u\n", ap->print_id); @@ -4828,6 +4825,7 @@ void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, static void ata_pio_sector(struct ata_queued_cmd *qc) { int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + struct scatterlist *sg = qc->__sg; struct ata_port *ap = qc->ap; struct page *page; unsigned int offset; @@ -4836,8 +4834,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) if (qc->curbytes == qc->nbytes - qc->sect_size) ap->hsm_task_state = HSM_ST_LAST; - page = qc->cursg->page; - offset = qc->cursg->offset + qc->cursg_ofs; + page = sg[qc->cursg].page; + offset = sg[qc->cursg].offset + qc->cursg_ofs; /* get the current page and offset */ page = nth_page(page, (offset >> PAGE_SHIFT)); @@ -4865,8 +4863,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) qc->curbytes += qc->sect_size; qc->cursg_ofs += qc->sect_size; - if (qc->cursg_ofs == qc->cursg->length) { - qc->cursg = sg_next(qc->cursg); + if (qc->cursg_ofs == (&sg[qc->cursg])->length) { + qc->cursg++; qc->cursg_ofs = 0; } } @@ -4952,18 +4950,16 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) { int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); struct scatterlist *sg = qc->__sg; - struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem); struct ata_port *ap = qc->ap; struct page *page; unsigned char *buf; unsigned int offset, count; - int no_more_sg = 0; if (qc->curbytes + bytes >= qc->nbytes) ap->hsm_task_state = HSM_ST_LAST; next_sg: - if (unlikely(no_more_sg)) { + if (unlikely(qc->cursg >= qc->n_elem)) { /* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg @@ -4986,7 +4982,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) return; } - sg = qc->cursg; + sg = &qc->__sg[qc->cursg]; page = sg->page; offset = sg->offset + qc->cursg_ofs; @@ -5025,10 +5021,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) qc->cursg_ofs += count; if (qc->cursg_ofs == sg->length) { - if (qc->cursg == lsg) - no_more_sg = 1; - - qc->cursg = sg_next(qc->cursg); + qc->cursg++; qc->cursg_ofs = 0; } diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index 9fbb39cd0f58..d63c81ed084f 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -801,6 +801,8 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ata_scsi_sdev_config(sdev); + blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); + sdev->manage_start_stop = 1; if (dev) @@ -3238,7 +3240,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) /** * ata_scsi_media_change_notify - send media change event - * @dev: Pointer to the disk device with media change event + * @atadev: Pointer to the disk device with media change event * * Tell the block layer to send a media change notification * event. diff --git a/trunk/drivers/atm/Makefile b/trunk/drivers/atm/Makefile index e4fa99658699..1b16f8166b09 100644 --- a/trunk/drivers/atm/Makefile +++ b/trunk/drivers/atm/Makefile @@ -41,7 +41,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y) # guess the target endianess to choose the right PCA-200E firmware image ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y) byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h - CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(KBUILD_CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2) + CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2) endif endif diff --git a/trunk/drivers/base/memory.c b/trunk/drivers/base/memory.c index c41d0728efe2..7a1390cd6aad 100644 --- a/trunk/drivers/base/memory.c +++ b/trunk/drivers/base/memory.c @@ -238,7 +238,7 @@ store_mem_state(struct sys_device *dev, const char *buf, size_t count) mem = container_of(dev, struct memory_block, sysdev); phys_section_nr = mem->phys_index; - if (!present_section_nr(phys_section_nr)) + if (!valid_section_nr(phys_section_nr)) goto out; if (!strncmp(buf, "online", min((int)count, 6))) @@ -418,7 +418,7 @@ int register_new_memory(struct mem_section *section) int unregister_memory_section(struct mem_section *section) { - if (!present_section(section)) + if (!valid_section(section)) return -EINVAL; return remove_memory_block(0, section, 0); @@ -443,7 +443,7 @@ int __init memory_dev_init(void) * during boot and have been initialized */ for (i = 0; i < NR_MEM_SECTIONS; i++) { - if (!present_section_nr(i)) + if (!valid_section_nr(i)) continue; err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); if (!ret) diff --git a/trunk/drivers/base/node.c b/trunk/drivers/base/node.c index 88eeed72b5d6..cae346ef1b20 100644 --- a/trunk/drivers/base/node.c +++ b/trunk/drivers/base/node.c @@ -12,7 +12,6 @@ #include #include #include -#include static struct sysdev_class node_class = { set_kset_name("node"), @@ -233,96 +232,8 @@ void unregister_one_node(int nid) unregister_node(&node_devices[nid]); } -/* - * node states attributes - */ - -static ssize_t print_nodes_state(enum node_states state, char *buf) -{ - int n; - - n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]); - if (n > 0 && PAGE_SIZE > n + 1) { - *(buf + n++) = '\n'; - *(buf + n++) = '\0'; - } - return n; -} - -static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf) -{ - return print_nodes_state(N_POSSIBLE, buf); -} - -static ssize_t print_nodes_online(struct sysdev_class *class, char *buf) -{ - return print_nodes_state(N_ONLINE, buf); -} - -static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class, - char *buf) -{ - return print_nodes_state(N_NORMAL_MEMORY, buf); -} - -static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf) -{ - return print_nodes_state(N_CPU, buf); -} - -static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL); -static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL); -static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory, - NULL); -static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL); - -#ifdef CONFIG_HIGHMEM -static ssize_t print_nodes_has_high_memory(struct sysdev_class *class, - char *buf) -{ - return print_nodes_state(N_HIGH_MEMORY, buf); -} - -static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory, - NULL); -#endif - -struct sysdev_class_attribute *node_state_attr[] = { - &attr_possible, - &attr_online, - &attr_has_normal_memory, -#ifdef CONFIG_HIGHMEM - &attr_has_high_memory, -#endif - &attr_has_cpu, -}; - -static int node_states_init(void) -{ - int i; - int err = 0; - - for (i = 0; i < NR_NODE_STATES; i++) { - int ret; - ret = sysdev_class_create_file(&node_class, node_state_attr[i]); - if (!err) - err = ret; - } - return err; -} - static int __init register_node_type(void) { - int ret; - - ret = sysdev_class_register(&node_class); - if (!ret) - ret = node_states_init(); - - /* - * Note: we're not going to unregister the node class if we fail - * to register the node state class attribute files. - */ - return ret; + return sysdev_class_register(&node_class); } postcore_initcall(register_node_type); diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 3fb7e8bc436d..55c3237fb1bc 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -1191,6 +1191,7 @@ static inline void complete_buffers(struct bio *bio, int status) { while (bio) { struct bio *xbh = bio->bi_next; + int nr_sectors = bio_sectors(bio); bio->bi_next = NULL; bio_endio(bio, status ? 0 : -EIO); @@ -2569,7 +2570,6 @@ static void do_cciss_request(struct request_queue *q) (int)creq->nr_sectors); #endif /* CCISS_DEBUG */ - memset(tmp_sg, 0, sizeof(tmp_sg)); seg = blk_rq_map_sg(q, creq, tmp_sg); /* get the DMA records for the setup */ diff --git a/trunk/drivers/block/cpqarray.c b/trunk/drivers/block/cpqarray.c index 568603d3043e..3853c9a38d6a 100644 --- a/trunk/drivers/block/cpqarray.c +++ b/trunk/drivers/block/cpqarray.c @@ -981,8 +981,9 @@ static void start_io(ctlr_info_t *h) static inline void complete_buffers(struct bio *bio, int ok) { struct bio *xbh; + while(bio) { + int nr_sectors = bio_sectors(bio); - while (bio) { xbh = bio->bi_next; bio->bi_next = NULL; diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index e5a051577a5e..b9233a06934c 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -204,13 +204,14 @@ lo_do_transfer(struct loop_device *lo, int cmd, * do_lo_send_aops - helper for writing data to a loop device * * This is the fast version for backing filesystems which implement the address - * space operations write_begin and write_end. + * space operations prepare_write and commit_write. */ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, - int bsize, loff_t pos, struct page *unused) + int bsize, loff_t pos, struct page *page) { struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */ struct address_space *mapping = file->f_mapping; + const struct address_space_operations *aops = mapping->a_ops; pgoff_t index; unsigned offset, bv_offs; int len, ret; @@ -222,45 +223,63 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, len = bvec->bv_len; while (len > 0) { sector_t IV; - unsigned size, copied; + unsigned size; int transfer_result; - struct page *page; - void *fsdata; IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9); size = PAGE_CACHE_SIZE - offset; if (size > len) size = len; - - ret = pagecache_write_begin(file, mapping, pos, size, 0, - &page, &fsdata); - if (ret) + page = grab_cache_page(mapping, index); + if (unlikely(!page)) goto fail; - + ret = aops->prepare_write(file, page, offset, + offset + size); + if (unlikely(ret)) { + if (ret == AOP_TRUNCATED_PAGE) { + page_cache_release(page); + continue; + } + goto unlock; + } transfer_result = lo_do_transfer(lo, WRITE, page, offset, bvec->bv_page, bv_offs, size, IV); - copied = size; - if (unlikely(transfer_result)) - copied = 0; - - ret = pagecache_write_end(file, mapping, pos, size, copied, - page, fsdata); - if (ret < 0 || ret != copied) - goto fail; - + if (unlikely(transfer_result)) { + /* + * The transfer failed, but we still write the data to + * keep prepare/commit calls balanced. + */ + printk(KERN_ERR "loop: transfer error block %llu\n", + (unsigned long long)index); + zero_user_page(page, offset, size, KM_USER0); + } + flush_dcache_page(page); + ret = aops->commit_write(file, page, offset, + offset + size); + if (unlikely(ret)) { + if (ret == AOP_TRUNCATED_PAGE) { + page_cache_release(page); + continue; + } + goto unlock; + } if (unlikely(transfer_result)) - goto fail; - - bv_offs += copied; - len -= copied; + goto unlock; + bv_offs += size; + len -= size; offset = 0; index++; - pos += copied; + pos += size; + unlock_page(page); + page_cache_release(page); } ret = 0; out: mutex_unlock(&mapping->host->i_mutex); return ret; +unlock: + unlock_page(page); + page_cache_release(page); fail: ret = -1; goto out; @@ -294,7 +313,7 @@ static int __do_lo_send_write(struct file *file, * do_lo_send_direct_write - helper for writing data to a loop device * * This is the fast, non-transforming version for backing filesystems which do - * not implement the address space operations write_begin and write_end. + * not implement the address space operations prepare_write and commit_write. * It uses the write file operation which should be present on all writeable * filesystems. */ @@ -313,7 +332,7 @@ static int do_lo_send_direct_write(struct loop_device *lo, * do_lo_send_write - helper for writing data to a loop device * * This is the slow, transforming version for filesystems which do not - * implement the address space operations write_begin and write_end. It + * implement the address space operations prepare_write and commit_write. It * uses the write file operation which should be present on all writeable * filesystems. * @@ -761,7 +780,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, */ if (!file->f_op->splice_read) goto out_putf; - if (aops->prepare_write || aops->write_begin) + if (aops->prepare_write && aops->commit_write) lo_flags |= LO_FLAGS_USE_AOPS; if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write) lo_flags |= LO_FLAGS_READ_ONLY; diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index a8130a4ad6d4..540bf3676985 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -1133,21 +1133,16 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) * Schedule reads for missing parts of the packet. */ for (f = 0; f < pkt->frames; f++) { - struct bio_vec *vec; - int p, offset; if (written[f]) continue; bio = pkt->r_bios[f]; - vec = bio->bi_io_vec; bio_init(bio); bio->bi_max_vecs = 1; bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9); bio->bi_bdev = pd->bdev; bio->bi_end_io = pkt_end_io_read; bio->bi_private = pkt; - bio->bi_io_vec = vec; - bio->bi_destructor = pkt_bio_destructor; p = (f * CD_FRAMESIZE) / PAGE_SIZE; offset = (f * CD_FRAMESIZE) % PAGE_SIZE; @@ -1444,8 +1439,6 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) pkt->w_bio->bi_bdev = pd->bdev; pkt->w_bio->bi_end_io = pkt_end_io_packet_write; pkt->w_bio->bi_private = pkt; - pkt->w_bio->bi_io_vec = bvec; - pkt->w_bio->bi_destructor = pkt_bio_destructor; for (f = 0; f < pkt->frames; f++) if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset)) BUG(); diff --git a/trunk/drivers/block/ps3disk.c b/trunk/drivers/block/ps3disk.c index e354bfc070e1..06d0552cf49c 100644 --- a/trunk/drivers/block/ps3disk.c +++ b/trunk/drivers/block/ps3disk.c @@ -414,6 +414,26 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req) req->cmd_type = REQ_TYPE_FLUSH; } +static int ps3disk_issue_flush(struct request_queue *q, struct gendisk *gendisk, + sector_t *sector) +{ + struct ps3_storage_device *dev = q->queuedata; + struct request *req; + int res; + + dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); + + req = blk_get_request(q, WRITE, __GFP_WAIT); + ps3disk_prepare_flush(q, req); + res = blk_execute_rq(q, gendisk, req, 0); + if (res) + dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n", + __func__, __LINE__, res); + blk_put_request(req); + return res; +} + + static unsigned long ps3disk_mask; static DEFINE_MUTEX(ps3disk_mask_mutex); @@ -486,6 +506,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev) blk_queue_dma_alignment(queue, dev->blk_size-1); blk_queue_hardsect_size(queue, dev->blk_size); + blk_queue_issue_flush_fn(queue, ps3disk_issue_flush); blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, ps3disk_prepare_flush); diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index f6f8c03047fa..b391776e5bf3 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -896,6 +896,10 @@ config GPIO_TB0219 depends on TANBAC_TB022X select GPIO_VR41XX +source "drivers/char/agp/Kconfig" + +source "drivers/char/drm/Kconfig" + source "drivers/char/pcmcia/Kconfig" config MWAVE diff --git a/trunk/drivers/char/agp/Kconfig b/trunk/drivers/char/agp/Kconfig index f22c253bc09f..713533d8a86e 100644 --- a/trunk/drivers/char/agp/Kconfig +++ b/trunk/drivers/char/agp/Kconfig @@ -1,4 +1,4 @@ -menuconfig AGP +config AGP tristate "/dev/agpgart (AGP Support)" depends on ALPHA || IA64 || PARISC || PPC || X86 depends on PCI diff --git a/trunk/drivers/char/drm/Kconfig b/trunk/drivers/char/drm/Kconfig index ba3058dd39a7..0b7ffa5191c6 100644 --- a/trunk/drivers/char/drm/Kconfig +++ b/trunk/drivers/char/drm/Kconfig @@ -4,7 +4,7 @@ # This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. # -menuconfig DRM +config DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG help diff --git a/trunk/drivers/char/drm/radeon_irq.c b/trunk/drivers/char/drm/radeon_irq.c index 2b2407ee490e..f89e57665b64 100644 --- a/trunk/drivers/char/drm/radeon_irq.c +++ b/trunk/drivers/char/drm/radeon_irq.c @@ -144,8 +144,8 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) return ret; } -static int radeon_driver_vblank_do_wait(struct drm_device * dev, - unsigned int *sequence, int crtc) +int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence, + int crtc) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; diff --git a/trunk/drivers/char/mem.c b/trunk/drivers/char/mem.c index 64551ab6be03..bbee97ff355f 100644 --- a/trunk/drivers/char/mem.c +++ b/trunk/drivers/char/mem.c @@ -625,10 +625,65 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); } +#ifdef CONFIG_MMU +/* + * For fun, we are using the MMU for this. + */ +static inline size_t read_zero_pagealigned(char __user * buf, size_t size) +{ + struct mm_struct *mm; + struct vm_area_struct * vma; + unsigned long addr=(unsigned long)buf; + + mm = current->mm; + /* Oops, this was forgotten before. -ben */ + down_read(&mm->mmap_sem); + + /* For private mappings, just map in zero pages. */ + for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { + unsigned long count; + + if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) + goto out_up; + if (vma->vm_flags & (VM_SHARED | VM_HUGETLB)) + break; + count = vma->vm_end - addr; + if (count > size) + count = size; + + zap_page_range(vma, addr, count, NULL); + if (zeromap_page_range(vma, addr, count, PAGE_COPY)) + break; + + size -= count; + buf += count; + addr += count; + if (size == 0) + goto out_up; + } + + up_read(&mm->mmap_sem); + + /* The shared case is hard. Let's do the conventional zeroing. */ + do { + unsigned long unwritten = clear_user(buf, PAGE_SIZE); + if (unwritten) + return size + unwritten - PAGE_SIZE; + cond_resched(); + buf += PAGE_SIZE; + size -= PAGE_SIZE; + } while (size); + + return size; +out_up: + up_read(&mm->mmap_sem); + return size; +} + static ssize_t read_zero(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - size_t written; + unsigned long left, unwritten, written = 0; if (!count) return 0; @@ -636,33 +691,69 @@ static ssize_t read_zero(struct file * file, char __user * buf, if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; - written = 0; - while (count) { - unsigned long unwritten; - size_t chunk = count; + left = count; + + /* do we want to be clever? Arbitrary cut-off */ + if (count >= PAGE_SIZE*4) { + unsigned long partial; - if (chunk > PAGE_SIZE) - chunk = PAGE_SIZE; /* Just for latency reasons */ - unwritten = clear_user(buf, chunk); - written += chunk - unwritten; + /* How much left of the page? */ + partial = (PAGE_SIZE-1) & -(unsigned long) buf; + unwritten = clear_user(buf, partial); + written = partial - unwritten; if (unwritten) - break; - buf += chunk; - count -= chunk; - cond_resched(); + goto out; + left -= partial; + buf += partial; + unwritten = read_zero_pagealigned(buf, left & PAGE_MASK); + written += (left & PAGE_MASK) - unwritten; + if (unwritten) + goto out; + buf += left & PAGE_MASK; + left &= ~PAGE_MASK; } + unwritten = clear_user(buf, left); + written += left - unwritten; +out: return written ? written : -EFAULT; } static int mmap_zero(struct file * file, struct vm_area_struct * vma) { -#ifndef CONFIG_MMU - return -ENOSYS; -#endif + int err; + if (vma->vm_flags & VM_SHARED) return shmem_zero_setup(vma); - return 0; + err = zeromap_page_range(vma, vma->vm_start, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + BUG_ON(err == -EEXIST); + return err; +} +#else /* CONFIG_MMU */ +static ssize_t read_zero(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + size_t todo = count; + + while (todo) { + size_t chunk = todo; + + if (chunk > 4096) + chunk = 4096; /* Just for latency reasons */ + if (clear_user(buf, chunk)) + return -EFAULT; + buf += chunk; + todo -= chunk; + cond_resched(); + } + return count; +} + +static int mmap_zero(struct file * file, struct vm_area_struct * vma) +{ + return -ENOSYS; } +#endif /* CONFIG_MMU */ static ssize_t write_full(struct file * file, const char __user * buf, size_t count, loff_t *ppos) diff --git a/trunk/drivers/char/mspec.c b/trunk/drivers/char/mspec.c index 82f2e27dca7d..04ac155d3a07 100644 --- a/trunk/drivers/char/mspec.c +++ b/trunk/drivers/char/mspec.c @@ -362,7 +362,7 @@ mspec_init(void) is_sn2 = 1; if (is_shub2()) { ret = -ENOMEM; - for_each_node_state(nid, N_ONLINE) { + for_each_online_node(nid) { int actual_nid; int nasid; unsigned long phys; diff --git a/trunk/drivers/char/vt.c b/trunk/drivers/char/vt.c index 0d56f8fc105c..edb7002a3216 100644 --- a/trunk/drivers/char/vt.c +++ b/trunk/drivers/char/vt.c @@ -750,15 +750,13 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ return 0; } -static inline int resize_screen(struct vc_data *vc, int width, int height, - int user) +static inline int resize_screen(struct vc_data *vc, int width, int height) { /* Resizes the resolution of the display adapater */ int err = 0; if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize) - err = vc->vc_sw->con_resize(vc, width, height, user); - + err = vc->vc_sw->con_resize(vc, width, height); return err; } @@ -774,7 +772,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned int old_cols, old_rows, old_row_size, old_screen_size; unsigned int new_cols, new_rows, new_row_size, new_screen_size; - unsigned int end, user; + unsigned int end; unsigned short *newscreen; WARN_CONSOLE_UNLOCKED(); @@ -782,9 +780,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) if (!vc) return -ENXIO; - user = vc->vc_resize_user; - vc->vc_resize_user = 0; - if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW) return -EINVAL; @@ -805,7 +800,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) old_row_size = vc->vc_size_row; old_screen_size = vc->vc_screenbuf_size; - err = resize_screen(vc, new_cols, new_rows, user); + err = resize_screen(vc, new_cols, new_rows); if (err) { kfree(newscreen); return err; diff --git a/trunk/drivers/char/vt_ioctl.c b/trunk/drivers/char/vt_ioctl.c index f69a8258095c..7a61a2a9aafe 100644 --- a/trunk/drivers/char/vt_ioctl.c +++ b/trunk/drivers/char/vt_ioctl.c @@ -847,24 +847,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case VT_RESIZE: { struct vt_sizes __user *vtsizes = up; - struct vc_data *vc; - ushort ll,cc; if (!perm) return -EPERM; if (get_user(ll, &vtsizes->v_rows) || get_user(cc, &vtsizes->v_cols)) return -EFAULT; - - for (i = 0; i < MAX_NR_CONSOLES; i++) { - vc = vc_cons[i].d; - - if (vc) { - vc->vc_resize_user = 1; - vc_lock_resize(vc_cons[i].d, cc, ll); - } - } - + for (i = 0; i < MAX_NR_CONSOLES; i++) + vc_lock_resize(vc_cons[i].d, cc, ll); return 0; } @@ -910,7 +900,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, vc_cons[i].d->vc_scan_lines = vlin; if (clin) vc_cons[i].d->vc_font.height = clin; - vc_cons[i].d->vc_resize_user = 1; vc_resize(vc_cons[i].d, cc, ll); release_console_sem(); } diff --git a/trunk/drivers/dca/Kconfig b/trunk/drivers/dca/Kconfig deleted file mode 100644 index 94f0364a0efb..000000000000 --- a/trunk/drivers/dca/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -# -# DCA server configuration -# - -config DCA - tristate - diff --git a/trunk/drivers/dca/Makefile b/trunk/drivers/dca/Makefile deleted file mode 100644 index b2db56bb9dde..000000000000 --- a/trunk/drivers/dca/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_DCA) += dca.o -dca-objs := dca-core.o dca-sysfs.o diff --git a/trunk/drivers/dca/dca-core.c b/trunk/drivers/dca/dca-core.c deleted file mode 100644 index bf5b92f86df7..000000000000 --- a/trunk/drivers/dca/dca-core.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright(c) 2007 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This 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., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -/* - * This driver supports an interface for DCA clients and providers to meet. - */ - -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); - -/* For now we're assuming a single, global, DCA provider for the system. */ - -static DEFINE_SPINLOCK(dca_lock); - -static struct dca_provider *global_dca = NULL; - -/** - * dca_add_requester - add a dca client to the list - * @dev - the device that wants dca service - */ -int dca_add_requester(struct device *dev) -{ - int err, slot; - - if (!global_dca) - return -ENODEV; - - spin_lock(&dca_lock); - slot = global_dca->ops->add_requester(global_dca, dev); - spin_unlock(&dca_lock); - if (slot < 0) - return slot; - - err = dca_sysfs_add_req(global_dca, dev, slot); - if (err) { - spin_lock(&dca_lock); - global_dca->ops->remove_requester(global_dca, dev); - spin_unlock(&dca_lock); - return err; - } - - return 0; -} -EXPORT_SYMBOL_GPL(dca_add_requester); - -/** - * dca_remove_requester - remove a dca client from the list - * @dev - the device that wants dca service - */ -int dca_remove_requester(struct device *dev) -{ - int slot; - if (!global_dca) - return -ENODEV; - - spin_lock(&dca_lock); - slot = global_dca->ops->remove_requester(global_dca, dev); - spin_unlock(&dca_lock); - if (slot < 0) - return slot; - - dca_sysfs_remove_req(global_dca, slot); - return 0; -} -EXPORT_SYMBOL_GPL(dca_remove_requester); - -/** - * dca_get_tag - return the dca tag for the given cpu - * @cpu - the cpuid as returned by get_cpu() - */ -u8 dca_get_tag(int cpu) -{ - if (!global_dca) - return -ENODEV; - return global_dca->ops->get_tag(global_dca, cpu); -} -EXPORT_SYMBOL_GPL(dca_get_tag); - -/** - * alloc_dca_provider - get data struct for describing a dca provider - * @ops - pointer to struct of dca operation function pointers - * @priv_size - size of extra mem to be added for provider's needs - */ -struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size) -{ - struct dca_provider *dca; - int alloc_size; - - alloc_size = (sizeof(*dca) + priv_size); - dca = kzalloc(alloc_size, GFP_KERNEL); - if (!dca) - return NULL; - dca->ops = ops; - - return dca; -} -EXPORT_SYMBOL_GPL(alloc_dca_provider); - -/** - * free_dca_provider - release the dca provider data struct - * @ops - pointer to struct of dca operation function pointers - * @priv_size - size of extra mem to be added for provider's needs - */ -void free_dca_provider(struct dca_provider *dca) -{ - kfree(dca); -} -EXPORT_SYMBOL_GPL(free_dca_provider); - -static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); - -/** - * register_dca_provider - register a dca provider - * @dca - struct created by alloc_dca_provider() - * @dev - device providing dca services - */ -int register_dca_provider(struct dca_provider *dca, struct device *dev) -{ - int err; - - if (global_dca) - return -EEXIST; - err = dca_sysfs_add_provider(dca, dev); - if (err) - return err; - global_dca = dca; - blocking_notifier_call_chain(&dca_provider_chain, - DCA_PROVIDER_ADD, NULL); - return 0; -} -EXPORT_SYMBOL_GPL(register_dca_provider); - -/** - * unregister_dca_provider - remove a dca provider - * @dca - struct created by alloc_dca_provider() - */ -void unregister_dca_provider(struct dca_provider *dca) -{ - if (!global_dca) - return; - blocking_notifier_call_chain(&dca_provider_chain, - DCA_PROVIDER_REMOVE, NULL); - global_dca = NULL; - dca_sysfs_remove_provider(dca); -} -EXPORT_SYMBOL_GPL(unregister_dca_provider); - -/** - * dca_register_notify - register a client's notifier callback - */ -void dca_register_notify(struct notifier_block *nb) -{ - blocking_notifier_chain_register(&dca_provider_chain, nb); -} -EXPORT_SYMBOL_GPL(dca_register_notify); - -/** - * dca_unregister_notify - remove a client's notifier callback - */ -void dca_unregister_notify(struct notifier_block *nb) -{ - blocking_notifier_chain_unregister(&dca_provider_chain, nb); -} -EXPORT_SYMBOL_GPL(dca_unregister_notify); - -static int __init dca_init(void) -{ - return dca_sysfs_init(); -} - -static void __exit dca_exit(void) -{ - dca_sysfs_exit(); -} - -module_init(dca_init); -module_exit(dca_exit); - diff --git a/trunk/drivers/dca/dca-sysfs.c b/trunk/drivers/dca/dca-sysfs.c deleted file mode 100644 index 24a263b6844c..000000000000 --- a/trunk/drivers/dca/dca-sysfs.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static struct class *dca_class; -static struct idr dca_idr; -static spinlock_t dca_idr_lock; - -int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot) -{ - struct class_device *cd; - - cd = class_device_create(dca_class, dca->cd, MKDEV(0, slot + 1), - dev, "requester%d", slot); - if (IS_ERR(cd)) - return PTR_ERR(cd); - return 0; -} - -void dca_sysfs_remove_req(struct dca_provider *dca, int slot) -{ - class_device_destroy(dca_class, MKDEV(0, slot + 1)); -} - -int dca_sysfs_add_provider(struct dca_provider *dca, struct device *dev) -{ - struct class_device *cd; - int err = 0; - -idr_try_again: - if (!idr_pre_get(&dca_idr, GFP_KERNEL)) - return -ENOMEM; - spin_lock(&dca_idr_lock); - err = idr_get_new(&dca_idr, dca, &dca->id); - spin_unlock(&dca_idr_lock); - switch (err) { - case 0: - break; - case -EAGAIN: - goto idr_try_again; - default: - return err; - } - - cd = class_device_create(dca_class, NULL, MKDEV(0, 0), - dev, "dca%d", dca->id); - if (IS_ERR(cd)) { - spin_lock(&dca_idr_lock); - idr_remove(&dca_idr, dca->id); - spin_unlock(&dca_idr_lock); - return PTR_ERR(cd); - } - dca->cd = cd; - return 0; -} - -void dca_sysfs_remove_provider(struct dca_provider *dca) -{ - class_device_unregister(dca->cd); - dca->cd = NULL; - spin_lock(&dca_idr_lock); - idr_remove(&dca_idr, dca->id); - spin_unlock(&dca_idr_lock); -} - -int __init dca_sysfs_init(void) -{ - idr_init(&dca_idr); - spin_lock_init(&dca_idr_lock); - - dca_class = class_create(THIS_MODULE, "dca"); - if (IS_ERR(dca_class)) { - idr_destroy(&dca_idr); - return PTR_ERR(dca_class); - } - return 0; -} - -void __exit dca_sysfs_exit(void) -{ - class_destroy(dca_class); - idr_destroy(&dca_idr); -} - diff --git a/trunk/drivers/dma/Kconfig b/trunk/drivers/dma/Kconfig index 9c91b0fd134f..8f670dae53bb 100644 --- a/trunk/drivers/dma/Kconfig +++ b/trunk/drivers/dma/Kconfig @@ -2,52 +2,42 @@ # DMA engine configuration # -menuconfig DMADEVICES - bool "DMA Offload Engine support" - depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX - help - Intel(R) offload engines enable offloading memory copies in the - network stack and RAID operations in the MD driver. - -if DMADEVICES - -comment "DMA Devices" - -config INTEL_IOATDMA - tristate "Intel I/OAT DMA support" - depends on PCI && X86 - select DMA_ENGINE - select DCA - help - Enable support for the Intel(R) I/OAT DMA engine present - in recent Intel Xeon chipsets. - - Say Y here if you have such a chipset. - - If unsure, say N. - -config INTEL_IOP_ADMA - tristate "Intel IOP ADMA support" - depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX - select ASYNC_CORE - select DMA_ENGINE - help - Enable support for the Intel(R) IOP Series RAID engines. +menu "DMA Engine support" + depends on HAS_DMA config DMA_ENGINE - bool + bool "Support for DMA engines" + ---help--- + DMA engines offload bulk memory operations from the CPU to dedicated + hardware, allowing the operations to happen asynchronously. comment "DMA Clients" - depends on DMA_ENGINE config NET_DMA bool "Network: TCP receive copy offload" depends on DMA_ENGINE && NET default y - help + ---help--- This enables the use of DMA engines in the network stack to offload receive copy-to-user operations, freeing CPU cycles. Since this is the main user of the DMA engine, it should be enabled; say Y here. -endif +comment "DMA Devices" + +config INTEL_IOATDMA + tristate "Intel I/OAT DMA support" + depends on DMA_ENGINE && PCI + default m + ---help--- + Enable support for the Intel(R) I/OAT DMA engine. + +config INTEL_IOP_ADMA + tristate "Intel IOP ADMA support" + depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX) + select ASYNC_CORE + default m + ---help--- + Enable support for the Intel(R) IOP Series RAID engines. + +endmenu diff --git a/trunk/drivers/dma/Makefile b/trunk/drivers/dma/Makefile index b152cd84e123..b3839b687ae0 100644 --- a/trunk/drivers/dma/Makefile +++ b/trunk/drivers/dma/Makefile @@ -1,5 +1,4 @@ obj-$(CONFIG_DMA_ENGINE) += dmaengine.o obj-$(CONFIG_NET_DMA) += iovlock.o obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o -ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o diff --git a/trunk/drivers/dma/ioat.c b/trunk/drivers/dma/ioat.c deleted file mode 100644 index f7276bf2fe7e..000000000000 --- a/trunk/drivers/dma/ioat.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - */ - -/* - * This driver supports an Intel I/OAT DMA engine, which does asynchronous - * copy operations. - */ - -#include -#include -#include -#include -#include -#include "ioatdma.h" -#include "ioatdma_registers.h" -#include "ioatdma_hw.h" - -MODULE_VERSION("1.24"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Intel Corporation"); - -static struct pci_device_id ioat_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) }, - { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, - { 0, } -}; - -struct ioat_device { - struct pci_dev *pdev; - void __iomem *iobase; - struct ioatdma_device *dma; - struct dca_provider *dca; -}; - -static int __devinit ioat_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -#ifdef IOAT_DMA_REMOVE -static void __devexit ioat_remove(struct pci_dev *pdev); -#endif - -static int ioat_dca_enabled = 1; -module_param(ioat_dca_enabled, int, 0644); -MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); - -static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) -{ - struct ioat_device *device = pci_get_drvdata(pdev); - u8 version; - int err = 0; - - version = readb(iobase + IOAT_VER_OFFSET); - switch (version) { - case IOAT_VER_1_2: - device->dma = ioat_dma_probe(pdev, iobase); - if (ioat_dca_enabled) - device->dca = ioat_dca_init(pdev, iobase); - break; - default: - err = -ENODEV; - break; - } - return err; -} - -static void ioat_shutdown_functionality(struct pci_dev *pdev) -{ - struct ioat_device *device = pci_get_drvdata(pdev); - - if (device->dma) { - ioat_dma_remove(device->dma); - device->dma = NULL; - } - - if (device->dca) { - unregister_dca_provider(device->dca); - free_dca_provider(device->dca); - device->dca = NULL; - } - -} - -static struct pci_driver ioat_pci_drv = { - .name = "ioatdma", - .id_table = ioat_pci_tbl, - .probe = ioat_probe, - .shutdown = ioat_shutdown_functionality, -#ifdef IOAT_DMA_REMOVE - .remove = __devexit_p(ioat_remove), -#endif -}; - -static int __devinit ioat_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *iobase; - struct ioat_device *device; - unsigned long mmio_start, mmio_len; - int err; - - err = pci_enable_device(pdev); - if (err) - goto err_enable_device; - - err = pci_request_regions(pdev, ioat_pci_drv.name); - if (err) - goto err_request_regions; - - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (err) - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) - goto err_set_dma_mask; - - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err) - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (err) - goto err_set_dma_mask; - - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - iobase = ioremap(mmio_start, mmio_len); - if (!iobase) { - err = -ENOMEM; - goto err_ioremap; - } - - device = kzalloc(sizeof(*device), GFP_KERNEL); - if (!device) { - err = -ENOMEM; - goto err_kzalloc; - } - device->pdev = pdev; - pci_set_drvdata(pdev, device); - device->iobase = iobase; - - pci_set_master(pdev); - - err = ioat_setup_functionality(pdev, iobase); - if (err) - goto err_version; - - return 0; - -err_version: - kfree(device); -err_kzalloc: - iounmap(iobase); -err_ioremap: -err_set_dma_mask: - pci_release_regions(pdev); - pci_disable_device(pdev); -err_request_regions: -err_enable_device: - return err; -} - -#ifdef IOAT_DMA_REMOVE -/* - * It is unsafe to remove this module: if removed while a requested - * dma is outstanding, esp. from tcp, it is possible to hang while - * waiting for something that will never finish, thus hanging at - * least one cpu. However, if you're feeling lucky and need to do - * some testing, this usually works just fine. - */ -static void __devexit ioat_remove(struct pci_dev *pdev) -{ - struct ioat_device *device = pci_get_drvdata(pdev); - - ioat_shutdown_functionality(pdev); - - kfree(device); - - iounmap(device->iobase); - pci_release_regions(pdev); - pci_disable_device(pdev); -} -#endif - -static int __init ioat_init_module(void) -{ - return pci_register_driver(&ioat_pci_drv); -} -module_init(ioat_init_module); - -static void __exit ioat_exit_module(void) -{ - pci_unregister_driver(&ioat_pci_drv); -} -module_exit(ioat_exit_module); diff --git a/trunk/drivers/dma/ioat_dca.c b/trunk/drivers/dma/ioat_dca.c deleted file mode 100644 index 2ae04c30edeb..000000000000 --- a/trunk/drivers/dma/ioat_dca.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - */ - -#include -#include -#include -#include -#include - -/* either a kernel change is needed, or we need something like this in kernel */ -#ifndef CONFIG_SMP -#include -#undef cpu_physical_id -#define cpu_physical_id(cpu) (cpuid_ebx(1) >> 24) -#endif - -#include "ioatdma.h" -#include "ioatdma_registers.h" - -/* - * Bit 16 of a tag map entry is the "valid" bit, if it is set then bits 0:15 - * contain the bit number of the APIC ID to map into the DCA tag. If the valid - * bit is not set, then the value must be 0 or 1 and defines the bit in the tag. - */ -#define DCA_TAG_MAP_VALID 0x80 - -/* - * "Legacy" DCA systems do not implement the DCA register set in the - * I/OAT device. Software needs direct support for their tag mappings. - */ - -#define APICID_BIT(x) (DCA_TAG_MAP_VALID | (x)) -#define IOAT_TAG_MAP_LEN 8 - -static u8 ioat_tag_map_BNB[IOAT_TAG_MAP_LEN] = { - 1, APICID_BIT(1), APICID_BIT(2), APICID_BIT(2), }; -static u8 ioat_tag_map_SCNB[IOAT_TAG_MAP_LEN] = { - 1, APICID_BIT(1), APICID_BIT(2), APICID_BIT(2), }; -static u8 ioat_tag_map_CNB[IOAT_TAG_MAP_LEN] = { - 1, APICID_BIT(1), APICID_BIT(3), APICID_BIT(4), APICID_BIT(2), }; -static u8 ioat_tag_map_UNISYS[IOAT_TAG_MAP_LEN] = { 0 }; - -/* pack PCI B/D/F into a u16 */ -static inline u16 dcaid_from_pcidev(struct pci_dev *pci) -{ - return (pci->bus->number << 8) | pci->devfn; -} - -static int dca_enabled_in_bios(void) -{ - /* CPUID level 9 returns DCA configuration */ - /* Bit 0 indicates DCA enabled by the BIOS */ - unsigned long cpuid_level_9; - int res; - - cpuid_level_9 = cpuid_eax(9); - res = test_bit(0, &cpuid_level_9); - if (!res) - printk(KERN_ERR "ioat dma: DCA is disabled in BIOS\n"); - - return res; -} - -static int system_has_dca_enabled(void) -{ - if (boot_cpu_has(X86_FEATURE_DCA)) - return dca_enabled_in_bios(); - - printk(KERN_ERR "ioat dma: boot cpu doesn't have X86_FEATURE_DCA\n"); - return 0; -} - -struct ioat_dca_slot { - struct pci_dev *pdev; /* requester device */ - u16 rid; /* requester id, as used by IOAT */ -}; - -#define IOAT_DCA_MAX_REQ 6 - -struct ioat_dca_priv { - void __iomem *iobase; - void *dca_base; - int max_requesters; - int requester_count; - u8 tag_map[IOAT_TAG_MAP_LEN]; - struct ioat_dca_slot req_slots[0]; -}; - -/* 5000 series chipset DCA Port Requester ID Table Entry Format - * [15:8] PCI-Express Bus Number - * [7:3] PCI-Express Device Number - * [2:0] PCI-Express Function Number - * - * 5000 series chipset DCA control register format - * [7:1] Reserved (0) - * [0] Ignore Function Number - */ - -static int ioat_dca_add_requester(struct dca_provider *dca, struct device *dev) -{ - struct ioat_dca_priv *ioatdca = dca_priv(dca); - struct pci_dev *pdev; - int i; - u16 id; - - /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) - return -ENODEV; - pdev = to_pci_dev(dev); - id = dcaid_from_pcidev(pdev); - - if (ioatdca->requester_count == ioatdca->max_requesters) - return -ENODEV; - - for (i = 0; i < ioatdca->max_requesters; i++) { - if (ioatdca->req_slots[i].pdev == NULL) { - /* found an empty slot */ - ioatdca->requester_count++; - ioatdca->req_slots[i].pdev = pdev; - ioatdca->req_slots[i].rid = id; - writew(id, ioatdca->dca_base + (i * 4)); - /* make sure the ignore function bit is off */ - writeb(0, ioatdca->dca_base + (i * 4) + 2); - return i; - } - } - /* Error, ioatdma->requester_count is out of whack */ - return -EFAULT; -} - -static int ioat_dca_remove_requester(struct dca_provider *dca, - struct device *dev) -{ - struct ioat_dca_priv *ioatdca = dca_priv(dca); - struct pci_dev *pdev; - int i; - - /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) - return -ENODEV; - pdev = to_pci_dev(dev); - - for (i = 0; i < ioatdca->max_requesters; i++) { - if (ioatdca->req_slots[i].pdev == pdev) { - writew(0, ioatdca->dca_base + (i * 4)); - ioatdca->req_slots[i].pdev = NULL; - ioatdca->req_slots[i].rid = 0; - ioatdca->requester_count--; - return i; - } - } - return -ENODEV; -} - -static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu) -{ - struct ioat_dca_priv *ioatdca = dca_priv(dca); - int i, apic_id, bit, value; - u8 entry, tag; - - tag = 0; - apic_id = cpu_physical_id(cpu); - - for (i = 0; i < IOAT_TAG_MAP_LEN; i++) { - entry = ioatdca->tag_map[i]; - if (entry & DCA_TAG_MAP_VALID) { - bit = entry & ~DCA_TAG_MAP_VALID; - value = (apic_id & (1 << bit)) ? 1 : 0; - } else { - value = entry ? 1 : 0; - } - tag |= (value << i); - } - return tag; -} - -static struct dca_ops ioat_dca_ops = { - .add_requester = ioat_dca_add_requester, - .remove_requester = ioat_dca_remove_requester, - .get_tag = ioat_dca_get_tag, -}; - - -struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase) -{ - struct dca_provider *dca; - struct ioat_dca_priv *ioatdca; - u8 *tag_map = NULL; - int i; - int err; - - if (!system_has_dca_enabled()) - return NULL; - - /* I/OAT v1 systems must have a known tag_map to support DCA */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_INTEL: - switch (pdev->device) { - case PCI_DEVICE_ID_INTEL_IOAT: - tag_map = ioat_tag_map_BNB; - break; - case PCI_DEVICE_ID_INTEL_IOAT_CNB: - tag_map = ioat_tag_map_CNB; - break; - case PCI_DEVICE_ID_INTEL_IOAT_SCNB: - tag_map = ioat_tag_map_SCNB; - break; - } - break; - case PCI_VENDOR_ID_UNISYS: - switch (pdev->device) { - case PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR: - tag_map = ioat_tag_map_UNISYS; - break; - } - break; - } - if (tag_map == NULL) - return NULL; - - dca = alloc_dca_provider(&ioat_dca_ops, - sizeof(*ioatdca) + - (sizeof(struct ioat_dca_slot) * IOAT_DCA_MAX_REQ)); - if (!dca) - return NULL; - - ioatdca = dca_priv(dca); - ioatdca->max_requesters = IOAT_DCA_MAX_REQ; - - ioatdca->dca_base = iobase + 0x54; - - /* copy over the APIC ID to DCA tag mapping */ - for (i = 0; i < IOAT_TAG_MAP_LEN; i++) - ioatdca->tag_map[i] = tag_map[i]; - - err = register_dca_provider(dca, &pdev->dev); - if (err) { - free_dca_provider(dca); - return NULL; - } - - return dca; -} - diff --git a/trunk/drivers/dma/ioat_dma.c b/trunk/drivers/dma/ioatdma.c similarity index 55% rename from trunk/drivers/dma/ioat_dma.c rename to trunk/drivers/dma/ioatdma.c index 66c5bb53211b..41b18c5a3141 100644 --- a/trunk/drivers/dma/ioat_dma.c +++ b/trunk/drivers/dma/ioatdma.c @@ -1,10 +1,10 @@ /* - * Intel I/OAT DMA Linux driver - * Copyright(c) 2004 - 2007 Intel Corporation. + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. + * 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 @@ -12,12 +12,11 @@ * 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. */ /* @@ -36,77 +35,17 @@ #include "ioatdma_registers.h" #include "ioatdma_hw.h" -#define INITIAL_IOAT_DESC_COUNT 128 - #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) -#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common) +#define to_ioat_device(dev) container_of(dev, struct ioat_device, common) #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx) /* internal functions */ -static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan); -static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); +static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +static void ioat_shutdown(struct pci_dev *pdev); +static void __devexit ioat_remove(struct pci_dev *pdev); -static struct ioat_dma_chan *ioat_lookup_chan_by_index(struct ioatdma_device *device, - int index) -{ - return device->idx[index]; -} - -/** - * ioat_dma_do_interrupt - handler used for single vector interrupt mode - * @irq: interrupt id - * @data: interrupt data - */ -static irqreturn_t ioat_dma_do_interrupt(int irq, void *data) -{ - struct ioatdma_device *instance = data; - struct ioat_dma_chan *ioat_chan; - unsigned long attnstatus; - int bit; - u8 intrctrl; - - intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET); - - if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN)) - return IRQ_NONE; - - if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) { - writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET); - return IRQ_NONE; - } - - attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET); - for_each_bit(bit, &attnstatus, BITS_PER_LONG) { - ioat_chan = ioat_lookup_chan_by_index(instance, bit); - tasklet_schedule(&ioat_chan->cleanup_task); - } - - writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET); - return IRQ_HANDLED; -} - -/** - * ioat_dma_do_interrupt_msix - handler used for vector-per-channel interrupt mode - * @irq: interrupt id - * @data: interrupt data - */ -static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data) -{ - struct ioat_dma_chan *ioat_chan = data; - - tasklet_schedule(&ioat_chan->cleanup_task); - - return IRQ_HANDLED; -} - -static void ioat_dma_cleanup_tasklet(unsigned long data); - -/** - * ioat_dma_enumerate_channels - find and initialize the device's channels - * @device: the device to be enumerated - */ -static int ioat_dma_enumerate_channels(struct ioatdma_device *device) +static int enumerate_dma_channels(struct ioat_device *device) { u8 xfercap_scale; u32 xfercap; @@ -134,19 +73,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) /* This should be made common somewhere in dmaengine.c */ ioat_chan->common.device = &device->common; list_add_tail(&ioat_chan->common.device_node, - &device->common.channels); - device->idx[i] = ioat_chan; - tasklet_init(&ioat_chan->cleanup_task, - ioat_dma_cleanup_tasklet, - (unsigned long) ioat_chan); - tasklet_disable(&ioat_chan->cleanup_task); + &device->common.channels); } return device->common.chancnt; } -static void ioat_set_src(dma_addr_t addr, - struct dma_async_tx_descriptor *tx, - int index) +static void +ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index) { struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx); struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); @@ -160,9 +93,8 @@ static void ioat_set_src(dma_addr_t addr, } -static void ioat_set_dest(dma_addr_t addr, - struct dma_async_tx_descriptor *tx, - int index) +static void +ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index) { struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx); struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); @@ -175,7 +107,8 @@ static void ioat_set_dest(dma_addr_t addr, } } -static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) +static dma_cookie_t +ioat_tx_submit(struct dma_async_tx_descriptor *tx) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); struct ioat_desc_sw *desc = tx_to_ioat_desc(tx); @@ -208,27 +141,27 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) if (append) writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); - + return cookie; } static struct ioat_desc_sw *ioat_dma_alloc_descriptor( - struct ioat_dma_chan *ioat_chan, - gfp_t flags) + struct ioat_dma_chan *ioat_chan, + gfp_t flags) { struct ioat_dma_descriptor *desc; struct ioat_desc_sw *desc_sw; - struct ioatdma_device *ioatdma_device; + struct ioat_device *ioat_device; dma_addr_t phys; - ioatdma_device = to_ioatdma_device(ioat_chan->common.device); - desc = pci_pool_alloc(ioatdma_device->dma_pool, flags, &phys); + ioat_device = to_ioat_device(ioat_chan->common.device); + desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys); if (unlikely(!desc)) return NULL; desc_sw = kzalloc(sizeof(*desc_sw), flags); if (unlikely(!desc_sw)) { - pci_pool_free(ioatdma_device->dma_pool, desc, phys); + pci_pool_free(ioat_device->dma_pool, desc, phys); return NULL; } @@ -244,6 +177,10 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( return desc_sw; } +#define INITIAL_IOAT_DESC_COUNT 128 + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan); + /* returns the actual number of allocated descriptors */ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) { @@ -258,16 +195,15 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) if (!list_empty(&ioat_chan->free_desc)) return INITIAL_IOAT_DESC_COUNT; - /* Setup register to interrupt and write completion status on error */ + /* Setup register to interrupt and write completion status on error */ chanctrl = IOAT_CHANCTRL_ERR_INT_EN | IOAT_CHANCTRL_ANY_ERR_ABORT_EN | IOAT_CHANCTRL_ERR_COMPLETION_EN; - writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET); + writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET); chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); if (chanerr) { - dev_err(&ioat_chan->device->pdev->dev, - "ioatdma: CHANERR = %x, clearing\n", chanerr); + printk("IOAT: CHANERR = %x, clearing\n", chanerr); writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET); } @@ -275,8 +211,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) { desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); if (!desc) { - dev_err(&ioat_chan->device->pdev->dev, - "ioatdma: Only %d initial descriptors\n", i); + printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i); break; } list_add_tail(&desc->node, &tmp_list); @@ -289,8 +224,8 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ ioat_chan->completion_virt = pci_pool_alloc(ioat_chan->device->completion_pool, - GFP_KERNEL, - &ioat_chan->completion_addr); + GFP_KERNEL, + &ioat_chan->completion_addr); memset(ioat_chan->completion_virt, 0, sizeof(*ioat_chan->completion_virt)); writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF, @@ -298,88 +233,54 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) writel(((u64) ioat_chan->completion_addr) >> 32, ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH); - tasklet_enable(&ioat_chan->cleanup_task); - ioat_dma_start_null_desc(ioat_chan); + ioat_start_null_desc(ioat_chan); return i; } +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); + static void ioat_dma_free_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); - struct ioatdma_device *ioatdma_device = to_ioatdma_device(chan->device); + struct ioat_device *ioat_device = to_ioat_device(chan->device); struct ioat_desc_sw *desc, *_desc; + u16 chanctrl; int in_use_descs = 0; - tasklet_disable(&ioat_chan->cleanup_task); ioat_dma_memcpy_cleanup(ioat_chan); - /* Delay 100ms after reset to allow internal DMA logic to quiesce - * before removing DMA descriptor resources. - */ writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); - mdelay(100); spin_lock_bh(&ioat_chan->desc_lock); list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { in_use_descs++; list_del(&desc->node); - pci_pool_free(ioatdma_device->dma_pool, desc->hw, + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->async_tx.phys); kfree(desc); } list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { list_del(&desc->node); - pci_pool_free(ioatdma_device->dma_pool, desc->hw, + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->async_tx.phys); kfree(desc); } spin_unlock_bh(&ioat_chan->desc_lock); - pci_pool_free(ioatdma_device->completion_pool, - ioat_chan->completion_virt, - ioat_chan->completion_addr); + pci_pool_free(ioat_device->completion_pool, + ioat_chan->completion_virt, + ioat_chan->completion_addr); /* one is ok since we left it on there on purpose */ if (in_use_descs > 1) - dev_err(&ioat_chan->device->pdev->dev, - "ioatdma: Freeing %d in use descriptors!\n", + printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n", in_use_descs - 1); ioat_chan->last_completion = ioat_chan->completion_addr = 0; - ioat_chan->pending = 0; -} -/** - * ioat_dma_get_next_descriptor - return the next available descriptor - * @ioat_chan: IOAT DMA channel handle - * - * Gets the next descriptor from the chain, and must be called with the - * channel's desc_lock held. Allocates more descriptors if the channel - * has run out. - */ -static struct ioat_desc_sw *ioat_dma_get_next_descriptor( - struct ioat_dma_chan *ioat_chan) -{ - struct ioat_desc_sw *new = NULL; - - if (!list_empty(&ioat_chan->free_desc)) { - new = to_ioat_desc(ioat_chan->free_desc.next); - list_del(&new->node); - } else { - /* try to get another desc */ - new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); - /* will this ever happen? */ - /* TODO add upper limit on these */ - BUG_ON(!new); - } - - prefetch(new->hw); - return new; } -static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( - struct dma_chan *chan, - size_t len, - int int_en) +static struct dma_async_tx_descriptor * +ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); struct ioat_desc_sw *first, *prev, *new; @@ -398,7 +299,17 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( spin_lock_bh(&ioat_chan->desc_lock); while (len) { - new = ioat_dma_get_next_descriptor(ioat_chan); + if (!list_empty(&ioat_chan->free_desc)) { + new = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&new->node); + } else { + /* try to get another desc */ + new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + /* will this ever happen? */ + /* TODO add upper limit on these */ + BUG_ON(!new); + } + copy = min((u32) len, ioat_chan->xfercap); new->hw->size = copy; @@ -432,11 +343,12 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( return new ? &new->async_tx : NULL; } + /** - * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended - * descriptors to hw + * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw * @chan: DMA channel handle */ + static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); @@ -448,23 +360,15 @@ static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) } } -static void ioat_dma_cleanup_tasklet(unsigned long data) -{ - struct ioat_dma_chan *chan = (void *)data; - ioat_dma_memcpy_cleanup(chan); - writew(IOAT_CHANCTRL_INT_DISABLE, - chan->reg_base + IOAT_CHANCTRL_OFFSET); -} - -static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) { unsigned long phys_complete; struct ioat_desc_sw *desc, *_desc; dma_cookie_t cookie = 0; - prefetch(ioat_chan->completion_virt); + prefetch(chan->completion_virt); - if (!spin_trylock(&ioat_chan->cleanup_lock)) + if (!spin_trylock(&chan->cleanup_lock)) return; /* The completion writeback can happen at any time, @@ -474,28 +378,26 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) #if (BITS_PER_LONG == 64) phys_complete = - ioat_chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; + chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; #else - phys_complete = ioat_chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK; + phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK; #endif - if ((ioat_chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) == - IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) { - dev_err(&ioat_chan->device->pdev->dev, - "ioatdma: Channel halted, chanerr = %x\n", - readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET)); + if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) == + IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) { + printk("IOAT: Channel halted, chanerr = %x\n", + readl(chan->reg_base + IOAT_CHANERR_OFFSET)); /* TODO do something to salvage the situation */ } - if (phys_complete == ioat_chan->last_completion) { - spin_unlock(&ioat_chan->cleanup_lock); + if (phys_complete == chan->last_completion) { + spin_unlock(&chan->cleanup_lock); return; } - cookie = 0; - spin_lock_bh(&ioat_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { + spin_lock_bh(&chan->desc_lock); + list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) { /* * Incoming DMA requests may use multiple descriptors, due to @@ -505,36 +407,31 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) if (desc->async_tx.cookie) { cookie = desc->async_tx.cookie; - /* - * yes we are unmapping both _page and _single alloc'd - * regions with unmap_page. Is this *really* that bad? - */ - pci_unmap_page(ioat_chan->device->pdev, + /* yes we are unmapping both _page and _single alloc'd + regions with unmap_page. Is this *really* that bad? + */ + pci_unmap_page(chan->device->pdev, pci_unmap_addr(desc, dst), pci_unmap_len(desc, len), PCI_DMA_FROMDEVICE); - pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_page(chan->device->pdev, pci_unmap_addr(desc, src), pci_unmap_len(desc, len), PCI_DMA_TODEVICE); } if (desc->async_tx.phys != phys_complete) { - /* - * a completed entry, but not the last, so cleanup + /* a completed entry, but not the last, so cleanup * if the client is done with the descriptor */ if (desc->async_tx.ack) { list_del(&desc->node); - list_add_tail(&desc->node, - &ioat_chan->free_desc); + list_add_tail(&desc->node, &chan->free_desc); } else desc->async_tx.cookie = 0; } else { - /* - * last used desc. Do not remove, so we can append from - * it, but don't look at it next time, either - */ + /* last used desc. Do not remove, so we can append from + it, but don't look at it next time, either */ desc->async_tx.cookie = 0; /* TODO check status bits? */ @@ -542,13 +439,13 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) } } - spin_unlock_bh(&ioat_chan->desc_lock); + spin_unlock_bh(&chan->desc_lock); - ioat_chan->last_completion = phys_complete; + chan->last_completion = phys_complete; if (cookie != 0) - ioat_chan->completed_cookie = cookie; + chan->completed_cookie = cookie; - spin_unlock(&ioat_chan->cleanup_lock); + spin_unlock(&chan->cleanup_lock); } static void ioat_dma_dependency_added(struct dma_chan *chan) @@ -569,10 +466,11 @@ static void ioat_dma_dependency_added(struct dma_chan *chan) * @done: if not %NULL, updated with last completed transaction * @used: if not %NULL, updated with last used transaction */ + static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, - dma_cookie_t cookie, - dma_cookie_t *done, - dma_cookie_t *used) + dma_cookie_t cookie, + dma_cookie_t *done, + dma_cookie_t *used) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); dma_cookie_t last_used; @@ -583,7 +481,7 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, last_complete = ioat_chan->completed_cookie; if (done) - *done = last_complete; + *done= last_complete; if (used) *used = last_used; @@ -597,7 +495,7 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, last_complete = ioat_chan->completed_cookie; if (done) - *done = last_complete; + *done= last_complete; if (used) *used = last_used; @@ -606,13 +504,63 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, /* PCI API */ -static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) +static struct pci_device_id ioat_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, + { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, + PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, + { 0, } +}; + +static struct pci_driver ioat_pci_driver = { + .name = "ioatdma", + .id_table = ioat_pci_tbl, + .probe = ioat_probe, + .shutdown = ioat_shutdown, + .remove = __devexit_p(ioat_remove), +}; + +static irqreturn_t ioat_do_interrupt(int irq, void *data) +{ + struct ioat_device *instance = data; + unsigned long attnstatus; + u8 intrctrl; + + intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET); + + if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN)) + return IRQ_NONE; + + if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) { + writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET); + return IRQ_NONE; + } + + attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET); + + printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus); + + writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET); + return IRQ_HANDLED; +} + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan) { struct ioat_desc_sw *desc; spin_lock_bh(&ioat_chan->desc_lock); - desc = ioat_dma_get_next_descriptor(ioat_chan); + if (!list_empty(&ioat_chan->free_desc)) { + desc = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&desc->node); + } else { + /* try to get another desc */ + spin_unlock_bh(&ioat_chan->desc_lock); + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); + spin_lock_bh(&ioat_chan->desc_lock); + /* will this ever happen? */ + BUG_ON(!desc); + } + desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; desc->hw->next = 0; desc->async_tx.ack = 1; @@ -633,11 +581,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) */ #define IOAT_TEST_SIZE 2000 -/** - * ioat_dma_self_test - Perform a IOAT transaction to verify the HW works. - * @device: device to be tested - */ -static int ioat_dma_self_test(struct ioatdma_device *device) +static int ioat_self_test(struct ioat_device *device) { int i; u8 *src; @@ -663,11 +607,9 @@ static int ioat_dma_self_test(struct ioatdma_device *device) /* Start copy, using first DMA channel */ dma_chan = container_of(device->common.channels.next, - struct dma_chan, - device_node); + struct dma_chan, + device_node); if (ioat_dma_alloc_chan_resources(dma_chan) < 1) { - dev_err(&device->pdev->dev, - "selftest cannot allocate chan resource\n"); err = -ENODEV; goto out; } @@ -685,14 +627,12 @@ static int ioat_dma_self_test(struct ioatdma_device *device) msleep(1); if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { - dev_err(&device->pdev->dev, - "ioatdma: Self-test copy timed out, disabling\n"); + printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n"); err = -ENODEV; goto free_resources; } if (memcmp(src, dest, IOAT_TEST_SIZE)) { - dev_err(&device->pdev->dev, - "ioatdma: Self-test copy failed compare, disabling\n"); + printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n"); err = -ENODEV; goto free_resources; } @@ -705,252 +645,147 @@ static int ioat_dma_self_test(struct ioatdma_device *device) return err; } -static char ioat_interrupt_style[32] = "msix"; -module_param_string(ioat_interrupt_style, ioat_interrupt_style, - sizeof(ioat_interrupt_style), 0644); -MODULE_PARM_DESC(ioat_interrupt_style, - "set ioat interrupt style: msix (default), " - "msix-single-vector, msi, intx)"); - -/** - * ioat_dma_setup_interrupts - setup interrupt handler - * @device: ioat device - */ -static int ioat_dma_setup_interrupts(struct ioatdma_device *device) +static int __devinit ioat_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct ioat_dma_chan *ioat_chan; - int err, i, j, msixcnt; - u8 intrctrl = 0; - - if (!strcmp(ioat_interrupt_style, "msix")) - goto msix; - if (!strcmp(ioat_interrupt_style, "msix-single-vector")) - goto msix_single_vector; - if (!strcmp(ioat_interrupt_style, "msi")) - goto msi; - if (!strcmp(ioat_interrupt_style, "intx")) - goto intx; - -msix: - /* The number of MSI-X vectors should equal the number of channels */ - msixcnt = device->common.chancnt; - for (i = 0; i < msixcnt; i++) - device->msix_entries[i].entry = i; - - err = pci_enable_msix(device->pdev, device->msix_entries, msixcnt); - if (err < 0) - goto msi; - if (err > 0) - goto msix_single_vector; - - for (i = 0; i < msixcnt; i++) { - ioat_chan = ioat_lookup_chan_by_index(device, i); - err = request_irq(device->msix_entries[i].vector, - ioat_dma_do_interrupt_msix, - 0, "ioat-msix", ioat_chan); - if (err) { - for (j = 0; j < i; j++) { - ioat_chan = - ioat_lookup_chan_by_index(device, j); - free_irq(device->msix_entries[j].vector, - ioat_chan); - } - goto msix_single_vector; - } - } - intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL; - device->irq_mode = msix_multi_vector; - goto done; + int err; + unsigned long mmio_start, mmio_len; + void __iomem *reg_base; + struct ioat_device *device; -msix_single_vector: - device->msix_entries[0].entry = 0; - err = pci_enable_msix(device->pdev, device->msix_entries, 1); + err = pci_enable_device(pdev); if (err) - goto msi; + goto err_enable_device; - err = request_irq(device->msix_entries[0].vector, ioat_dma_do_interrupt, - 0, "ioat-msix", device); - if (err) { - pci_disable_msix(device->pdev); - goto msi; - } - device->irq_mode = msix_single_vector; - goto done; - -msi: - err = pci_enable_msi(device->pdev); + err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); if (err) - goto intx; - - err = request_irq(device->pdev->irq, ioat_dma_do_interrupt, - 0, "ioat-msi", device); - if (err) { - pci_disable_msi(device->pdev); - goto intx; - } - /* - * CB 1.2 devices need a bit set in configuration space to enable MSI - */ - if (device->version == IOAT_VER_1_2) { - u32 dmactrl; - pci_read_config_dword(device->pdev, - IOAT_PCI_DMACTRL_OFFSET, &dmactrl); - dmactrl |= IOAT_PCI_DMACTRL_MSI_EN; - pci_write_config_dword(device->pdev, - IOAT_PCI_DMACTRL_OFFSET, dmactrl); - } - device->irq_mode = msi; - goto done; - -intx: - err = request_irq(device->pdev->irq, ioat_dma_do_interrupt, - IRQF_SHARED, "ioat-intx", device); + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) - goto err_no_irq; - device->irq_mode = intx; - -done: - intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN; - writeb(intrctrl, device->reg_base + IOAT_INTRCTRL_OFFSET); - return 0; - -err_no_irq: - /* Disable all interrupt generation */ - writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET); - dev_err(&device->pdev->dev, "no usable interrupts\n"); - device->irq_mode = none; - return -1; -} + goto err_set_dma_mask; -/** - * ioat_dma_remove_interrupts - remove whatever interrupts were set - * @device: ioat device - */ -static void ioat_dma_remove_interrupts(struct ioatdma_device *device) -{ - struct ioat_dma_chan *ioat_chan; - int i; + err = pci_request_regions(pdev, ioat_pci_driver.name); + if (err) + goto err_request_regions; - /* Disable all interrupt generation */ - writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET); + mmio_start = pci_resource_start(pdev, 0); + mmio_len = pci_resource_len(pdev, 0); - switch (device->irq_mode) { - case msix_multi_vector: - for (i = 0; i < device->common.chancnt; i++) { - ioat_chan = ioat_lookup_chan_by_index(device, i); - free_irq(device->msix_entries[i].vector, ioat_chan); - } - pci_disable_msix(device->pdev); - break; - case msix_single_vector: - free_irq(device->msix_entries[0].vector, device); - pci_disable_msix(device->pdev); - break; - case msi: - free_irq(device->pdev->irq, device); - pci_disable_msi(device->pdev); - break; - case intx: - free_irq(device->pdev->irq, device); - break; - case none: - dev_warn(&device->pdev->dev, - "call to %s without interrupts setup\n", __func__); + reg_base = ioremap(mmio_start, mmio_len); + if (!reg_base) { + err = -ENOMEM; + goto err_ioremap; } - device->irq_mode = none; -} - -struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, - void __iomem *iobase) -{ - int err; - struct ioatdma_device *device; device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) { err = -ENOMEM; goto err_kzalloc; } - device->pdev = pdev; - device->reg_base = iobase; - device->version = readb(device->reg_base + IOAT_VER_OFFSET); /* DMA coherent memory pool for DMA descriptor allocations */ device->dma_pool = pci_pool_create("dma_desc_pool", pdev, - sizeof(struct ioat_dma_descriptor), - 64, 0); + sizeof(struct ioat_dma_descriptor), 64, 0); if (!device->dma_pool) { err = -ENOMEM; goto err_dma_pool; } - device->completion_pool = pci_pool_create("completion_pool", pdev, - sizeof(u64), SMP_CACHE_BYTES, - SMP_CACHE_BYTES); + device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES); if (!device->completion_pool) { err = -ENOMEM; goto err_completion_pool; } + device->pdev = pdev; + pci_set_drvdata(pdev, device); +#ifdef CONFIG_PCI_MSI + if (pci_enable_msi(pdev) == 0) { + device->msi = 1; + } else { + device->msi = 0; + } +#endif + err = request_irq(pdev->irq, &ioat_do_interrupt, IRQF_SHARED, "ioat", + device); + if (err) + goto err_irq; + + device->reg_base = reg_base; + + writeb(IOAT_INTRCTRL_MASTER_INT_EN, device->reg_base + IOAT_INTRCTRL_OFFSET); + pci_set_master(pdev); + INIT_LIST_HEAD(&device->common.channels); - ioat_dma_enumerate_channels(device); + enumerate_dma_channels(device); dma_cap_set(DMA_MEMCPY, device->common.cap_mask); - device->common.device_alloc_chan_resources = - ioat_dma_alloc_chan_resources; - device->common.device_free_chan_resources = - ioat_dma_free_chan_resources; + device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; + device->common.device_free_chan_resources = ioat_dma_free_chan_resources; device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy; device->common.device_is_tx_complete = ioat_dma_is_complete; device->common.device_issue_pending = ioat_dma_memcpy_issue_pending; device->common.device_dependency_added = ioat_dma_dependency_added; device->common.dev = &pdev->dev; - dev_err(&device->pdev->dev, - "ioatdma: Intel(R) I/OAT DMA Engine found," - " %d channels, device version 0x%02x\n", - device->common.chancnt, device->version); + printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n", + device->common.chancnt); - err = ioat_dma_setup_interrupts(device); - if (err) - goto err_setup_interrupts; - - err = ioat_dma_self_test(device); + err = ioat_self_test(device); if (err) goto err_self_test; dma_async_device_register(&device->common); - return device; + return 0; err_self_test: - ioat_dma_remove_interrupts(device); -err_setup_interrupts: +err_irq: pci_pool_destroy(device->completion_pool); err_completion_pool: pci_pool_destroy(device->dma_pool); err_dma_pool: kfree(device); err_kzalloc: - iounmap(iobase); - dev_err(&device->pdev->dev, - "ioatdma: Intel(R) I/OAT DMA Engine initialization failed\n"); - return NULL; + iounmap(reg_base); +err_ioremap: + pci_release_regions(pdev); +err_request_regions: +err_set_dma_mask: + pci_disable_device(pdev); +err_enable_device: + + printk(KERN_ERR "Intel(R) I/OAT DMA Engine initialization failed\n"); + + return err; } -void ioat_dma_remove(struct ioatdma_device *device) +static void ioat_shutdown(struct pci_dev *pdev) { + struct ioat_device *device; + device = pci_get_drvdata(pdev); + + dma_async_device_unregister(&device->common); +} + +static void __devexit ioat_remove(struct pci_dev *pdev) +{ + struct ioat_device *device; struct dma_chan *chan, *_chan; struct ioat_dma_chan *ioat_chan; + device = pci_get_drvdata(pdev); dma_async_device_unregister(&device->common); - ioat_dma_remove_interrupts(device); - + free_irq(device->pdev->irq, device); +#ifdef CONFIG_PCI_MSI + if (device->msi) + pci_disable_msi(device->pdev); +#endif pci_pool_destroy(device->dma_pool); pci_pool_destroy(device->completion_pool); - - list_for_each_entry_safe(chan, _chan, - &device->common.channels, device_node) { + iounmap(device->reg_base); + pci_release_regions(pdev); + pci_disable_device(pdev); + list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) { ioat_chan = to_ioat_chan(chan); list_del(&chan->device_node); kfree(ioat_chan); @@ -958,3 +793,25 @@ void ioat_dma_remove(struct ioatdma_device *device) kfree(device); } +/* MODULE API */ +MODULE_VERSION("1.9"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Intel Corporation"); + +static int __init ioat_init_module(void) +{ + /* it's currently unsafe to unload this module */ + /* if forced, worst case is that rmmod hangs */ + __unsafe(THIS_MODULE); + + return pci_register_driver(&ioat_pci_driver); +} + +module_init(ioat_init_module); + +static void __exit ioat_exit_module(void) +{ + pci_unregister_driver(&ioat_pci_driver); +} + +module_exit(ioat_exit_module); diff --git a/trunk/drivers/dma/ioatdma.h b/trunk/drivers/dma/ioatdma.h index 2a319e124ece..bf4dad70e0f5 100644 --- a/trunk/drivers/dma/ioatdma.h +++ b/trunk/drivers/dma/ioatdma.h @@ -28,35 +28,25 @@ #include #include -enum ioat_interrupt { - none = 0, - msix_multi_vector = 1, - msix_single_vector = 2, - msi = 3, - intx = 4, -}; - #define IOAT_LOW_COMPLETION_MASK 0xffffffc0 /** - * struct ioatdma_device - internal representation of a IOAT device + * struct ioat_device - internal representation of a IOAT device * @pdev: PCI-Express device * @reg_base: MMIO register space base address * @dma_pool: for allocating DMA descriptors * @common: embedded struct dma_device - * @version: version of ioatdma device + * @msi: Message Signaled Interrupt number */ -struct ioatdma_device { +struct ioat_device { struct pci_dev *pdev; void __iomem *reg_base; struct pci_pool *dma_pool; struct pci_pool *completion_pool; + struct dma_device common; - u8 version; - enum ioat_interrupt irq_mode; - struct msix_entry msix_entries[4]; - struct ioat_dma_chan *idx[4]; + u8 msi; }; /** @@ -94,7 +84,7 @@ struct ioat_dma_chan { int pending; - struct ioatdma_device *device; + struct ioat_device *device; struct dma_chan common; dma_addr_t completion_addr; @@ -105,7 +95,6 @@ struct ioat_dma_chan { u32 high; }; } *completion_virt; - struct tasklet_struct cleanup_task; }; /* wrapper around hardware descriptor format + additional software fields */ @@ -128,16 +117,4 @@ struct ioat_desc_sw { struct dma_async_tx_descriptor async_tx; }; -#if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE) -struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, - void __iomem *iobase); -void ioat_dma_remove(struct ioatdma_device *device); -struct dca_provider *ioat_dca_init(struct pci_dev *pdev, - void __iomem *iobase); -#else -#define ioat_dma_probe(pdev, iobase) NULL -#define ioat_dma_remove(device) do { } while (0) -#define ioat_dca_init(pdev, iobase) NULL -#endif - #endif /* IOATDMA_H */ diff --git a/trunk/drivers/dma/ioatdma_hw.h b/trunk/drivers/dma/ioatdma_hw.h index 9e7434e1551f..4d7a12880be3 100644 --- a/trunk/drivers/dma/ioatdma_hw.h +++ b/trunk/drivers/dma/ioatdma_hw.h @@ -27,7 +27,7 @@ #define IOAT_PCI_RID 0x00 #define IOAT_PCI_SVID 0x8086 #define IOAT_PCI_SID 0x8086 -#define IOAT_VER_1_2 0x12 /* Version 1.2 */ +#define IOAT_VER 0x12 /* Version 1.2 */ struct ioat_dma_descriptor { uint32_t size; diff --git a/trunk/drivers/dma/ioatdma_registers.h b/trunk/drivers/dma/ioatdma_registers.h index baaab5ea146a..a30c7349075a 100644 --- a/trunk/drivers/dma/ioatdma_registers.h +++ b/trunk/drivers/dma/ioatdma_registers.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,9 +21,6 @@ #ifndef _IOAT_REGISTERS_H_ #define _IOAT_REGISTERS_H_ -#define IOAT_PCI_DMACTRL_OFFSET 0x48 -#define IOAT_PCI_DMACTRL_DMA_EN 0x00000001 -#define IOAT_PCI_DMACTRL_MSI_EN 0x00000002 /* MMIO Device Registers */ #define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */ @@ -42,7 +39,6 @@ #define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */ #define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */ #define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */ -#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */ #define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */ diff --git a/trunk/drivers/firewire/fw-cdev.c b/trunk/drivers/firewire/fw-cdev.c index 60f1a8924a95..06471302200f 100644 --- a/trunk/drivers/firewire/fw-cdev.c +++ b/trunk/drivers/firewire/fw-cdev.c @@ -25,14 +25,11 @@ #include #include #include -#include -#include #include #include #include #include #include -#include #include #include "fw-transaction.h" #include "fw-topology.h" @@ -143,10 +140,11 @@ static void queue_event(struct client *client, struct event *event, event->v[1].size = size1; spin_lock_irqsave(&client->lock, flags); - list_add_tail(&event->link, &client->event_list); - spin_unlock_irqrestore(&client->lock, flags); + list_add_tail(&event->link, &client->event_list); wake_up_interruptible(&client->wait); + + spin_unlock_irqrestore(&client->lock, flags); } static int @@ -623,19 +621,20 @@ iso_callback(struct fw_iso_context *context, u32 cycle, size_t header_length, void *header, void *data) { struct client *client = data; - struct iso_interrupt *irq; + struct iso_interrupt *interrupt; - irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC); - if (irq == NULL) + interrupt = kzalloc(sizeof(*interrupt) + header_length, GFP_ATOMIC); + if (interrupt == NULL) return; - irq->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; - irq->interrupt.closure = client->iso_closure; - irq->interrupt.cycle = cycle; - irq->interrupt.header_length = header_length; - memcpy(irq->interrupt.header, header, header_length); - queue_event(client, &irq->event, &irq->interrupt, - sizeof(irq->interrupt) + header_length, NULL, 0); + interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; + interrupt->interrupt.closure = client->iso_closure; + interrupt->interrupt.cycle = cycle; + interrupt->interrupt.header_length = header_length; + memcpy(interrupt->interrupt.header, header, header_length); + queue_event(client, &interrupt->event, + &interrupt->interrupt, + sizeof(interrupt->interrupt) + header_length, NULL, 0); } static int ioctl_create_iso_context(struct client *client, void *buffer) @@ -813,28 +812,6 @@ static int ioctl_stop_iso(struct client *client, void *buffer) return fw_iso_context_stop(client->iso_context); } -static int ioctl_get_cycle_timer(struct client *client, void *buffer) -{ - struct fw_cdev_get_cycle_timer *request = buffer; - struct fw_card *card = client->device->card; - unsigned long long bus_time; - struct timeval tv; - unsigned long flags; - - preempt_disable(); - local_irq_save(flags); - - bus_time = card->driver->get_bus_time(card); - do_gettimeofday(&tv); - - local_irq_restore(flags); - preempt_enable(); - - request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; - request->cycle_timer = bus_time & 0xffffffff; - return 0; -} - static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -848,7 +825,6 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_queue_iso, ioctl_start_iso, ioctl_stop_iso, - ioctl_get_cycle_timer, }; static int diff --git a/trunk/drivers/firewire/fw-device.h b/trunk/drivers/firewire/fw-device.h index 894d4a92a18e..d13e6a69707f 100644 --- a/trunk/drivers/firewire/fw-device.h +++ b/trunk/drivers/firewire/fw-device.h @@ -102,6 +102,11 @@ fw_unit(struct device *dev) #define CSR_INSTANCE 0x18 #define CSR_DIRECTORY_ID 0x20 +#define SBP2_COMMAND_SET_SPECIFIER 0x38 +#define SBP2_COMMAND_SET 0x39 +#define SBP2_COMMAND_SET_REVISION 0x3b +#define SBP2_FIRMWARE_REVISION 0x3c + struct fw_csr_iterator { u32 *p; u32 *end; diff --git a/trunk/drivers/firewire/fw-ohci.c b/trunk/drivers/firewire/fw-ohci.c index 2f307c4df335..e14c1ca7813e 100644 --- a/trunk/drivers/firewire/fw-ohci.c +++ b/trunk/drivers/firewire/fw-ohci.c @@ -18,23 +18,21 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#include -#include -#include -#include #include -#include #include +#include +#include #include -#include +#include +#include +#include +#include -#include -#include +#include +#include -#include "fw-ohci.h" #include "fw-transaction.h" +#include "fw-ohci.h" #define DESCRIPTOR_OUTPUT_MORE 0 #define DESCRIPTOR_OUTPUT_LAST (1 << 12) @@ -680,9 +678,6 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) /* FIXME: Document how the locking works. */ if (ohci->generation != packet->generation) { - if (packet->payload_length > 0) - dma_unmap_single(ohci->card.device, payload_bus, - packet->payload_length, DMA_TO_DEVICE); packet->ack = RCODE_GENERATION; return -1; } @@ -917,15 +912,10 @@ static void bus_reset_tasklet(unsigned long data) reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { - fw_notify("node ID not valid, new bus reset in progress\n"); + fw_error("node ID not valid, new bus reset in progress\n"); return; } - if ((reg & OHCI1394_NodeID_nodeNumber) == 63) { - fw_notify("malconfigured bus\n"); - return; - } - ohci->node_id = reg & (OHCI1394_NodeID_busNumber | - OHCI1394_NodeID_nodeNumber); + ohci->node_id = reg & 0xffff; /* * The count in the SelfIDCount register is the number of @@ -936,14 +926,12 @@ static void bus_reset_tasklet(unsigned long data) self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; - rmb(); for (i = 1, j = 0; j < self_id_count; i += 2, j++) { if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) fw_error("inconsistent self IDs\n"); ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]); } - rmb(); /* * Check the consistency of the self IDs we just read. The @@ -1058,9 +1046,6 @@ static irqreturn_t irq_handler(int irq, void *data) iso_event &= ~(1 << i); } - if (unlikely(event & OHCI1394_postedWriteErr)) - fw_error("PCI posted write error\n"); - if (event & OHCI1394_cycle64Seconds) { cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); if ((cycle_time & 0x80000000) == 0) @@ -1134,8 +1119,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) OHCI1394_RQPkt | OHCI1394_RSPkt | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | - OHCI1394_postedWriteErr | OHCI1394_cycle64Seconds | - OHCI1394_masterIntEnable); + OHCI1394_masterIntEnable | + OHCI1394_cycle64Seconds); /* Activate link_on bit and contender bit in our self ID packets.*/ if (ohci_update_phy_reg(card, 4, 0, diff --git a/trunk/drivers/firewire/fw-ohci.h b/trunk/drivers/firewire/fw-ohci.h index dec4f04e6b24..fa15706397d7 100644 --- a/trunk/drivers/firewire/fw-ohci.h +++ b/trunk/drivers/firewire/fw-ohci.h @@ -59,8 +59,6 @@ #define OHCI1394_LinkControl_cycleSource (1 << 22) #define OHCI1394_NodeID 0x0E8 #define OHCI1394_NodeID_idValid 0x80000000 -#define OHCI1394_NodeID_nodeNumber 0x0000003f -#define OHCI1394_NodeID_busNumber 0x0000ffc0 #define OHCI1394_PhyControl 0x0EC #define OHCI1394_PhyControl_Read(addr) (((addr) << 8) | 0x00008000) #define OHCI1394_PhyControl_ReadDone 0x80000000 diff --git a/trunk/drivers/firewire/fw-sbp2.c b/trunk/drivers/firewire/fw-sbp2.c index 5596df65c8ed..238730f75db1 100644 --- a/trunk/drivers/firewire/fw-sbp2.c +++ b/trunk/drivers/firewire/fw-sbp2.c @@ -37,12 +37,11 @@ #include #include #include -#include #include -#include #include #include +#include #include #include @@ -62,92 +61,34 @@ module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644); MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " "(default = Y, use N for concurrent initiators)"); -/* - * Flags for firmware oddities - * - * - 128kB max transfer - * Limit transfer size. Necessary for some old bridges. - * - * - 36 byte inquiry - * When scsi_mod probes the device, let the inquiry command look like that - * from MS Windows. - * - * - skip mode page 8 - * Suppress sending of mode_sense for mode page 8 if the device pretends to - * support the SCSI Primary Block commands instead of Reduced Block Commands. - * - * - fix capacity - * Tell sd_mod to correct the last sector number reported by read_capacity. - * Avoids access beyond actual disk limits on devices with an off-by-one bug. - * Don't use this with devices which don't have this bug. - * - * - override internal blacklist - * Instead of adding to the built-in blacklist, use only the workarounds - * specified in the module load parameter. - * Useful if a blacklist entry interfered with a non-broken device. - */ -#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 -#define SBP2_WORKAROUND_INQUIRY_36 0x2 -#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 -#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_OVERRIDE 0x100 - -static int sbp2_param_workarounds; -module_param_named(workarounds, sbp2_param_workarounds, int, 0644); -MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" - ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) - ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) - ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) - ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) - ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) - ", or a combination)"); - /* I don't know why the SCSI stack doesn't define something like this... */ typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); static const char sbp2_driver_name[] = "sbp2"; -/* - * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry - * and one struct scsi_device per sbp2_logical_unit. - */ -struct sbp2_logical_unit { - struct sbp2_target *tgt; - struct list_head link; - struct scsi_device *sdev; +struct sbp2_device { + struct kref kref; + struct fw_unit *unit; struct fw_address_handler address_handler; struct list_head orb_list; - + u64 management_agent_address; u64 command_block_agent_address; - u16 lun; + u32 workarounds; int login_id; /* - * The generation is updated once we've logged in or reconnected - * to the logical unit. Thus, I/O to the device will automatically - * fail and get retried if it happens in a window where the device - * is not ready, e.g. after a bus reset but before we reconnect. + * We cache these addresses and only update them once we've + * logged in or reconnected to the sbp2 device. That way, any + * IO to the device will automatically fail and get retried if + * it happens in a window where the device is not ready to + * handle it (e.g. after a bus reset but before we reconnect). */ - int generation; - int retries; - struct delayed_work work; -}; - -/* - * We create one struct sbp2_target per IEEE 1212 Unit Directory - * and one struct Scsi_Host per sbp2_target. - */ -struct sbp2_target { - struct kref kref; - struct fw_unit *unit; - - u64 management_agent_address; - int directory_id; int node_id; int address_high; + int generation; - unsigned workarounds; - struct list_head lu_list; + int retries; + struct delayed_work work; }; #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 @@ -160,9 +101,17 @@ struct sbp2_target { #define SBP2_DIRECTION_FROM_MEDIA 0x1 /* Unit directory keys */ -#define SBP2_CSR_FIRMWARE_REVISION 0x3c -#define SBP2_CSR_LOGICAL_UNIT_NUMBER 0x14 -#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY 0xd4 +#define SBP2_COMMAND_SET_SPECIFIER 0x38 +#define SBP2_COMMAND_SET 0x39 +#define SBP2_COMMAND_SET_REVISION 0x3b +#define SBP2_FIRMWARE_REVISION 0x3c + +/* Flags for detected oddities and brokeness */ +#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 +#define SBP2_WORKAROUND_INQUIRY_36 0x2 +#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 +#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 +#define SBP2_WORKAROUND_OVERRIDE 0x100 /* Management orb opcodes */ #define SBP2_LOGIN_REQUEST 0x0 @@ -270,7 +219,7 @@ struct sbp2_command_orb { } request; struct scsi_cmnd *cmd; scsi_done_fn_t done; - struct sbp2_logical_unit *lu; + struct fw_unit *unit; struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8))); dma_addr_t page_table_bus; @@ -346,7 +295,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, unsigned long long offset, void *payload, size_t length, void *callback_data) { - struct sbp2_logical_unit *lu = callback_data; + struct sbp2_device *sd = callback_data; struct sbp2_orb *orb; struct sbp2_status status; size_t header_size; @@ -370,7 +319,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, /* Lookup the orb corresponding to this status write. */ spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(orb, &lu->orb_list, link) { + list_for_each_entry(orb, &sd->orb_list, link) { if (STATUS_GET_ORB_HIGH(status) == 0 && STATUS_GET_ORB_LOW(status) == orb->request_bus) { orb->rcode = RCODE_COMPLETE; @@ -380,7 +329,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, } spin_unlock_irqrestore(&card->lock, flags); - if (&orb->link != &lu->orb_list) + if (&orb->link != &sd->orb_list) orb->callback(orb, &status); else fw_error("status write for unknown orb\n"); @@ -412,20 +361,20 @@ complete_transaction(struct fw_card *card, int rcode, orb->rcode = rcode; if (orb->rcode != RCODE_COMPLETE) { list_del(&orb->link); - spin_unlock_irqrestore(&card->lock, flags); orb->callback(orb, NULL); - } else { - spin_unlock_irqrestore(&card->lock, flags); } + spin_unlock_irqrestore(&card->lock, flags); + kref_put(&orb->kref, free_orb); } static void -sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, +sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, int node_id, int generation, u64 offset) { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd = unit->device.driver_data; unsigned long flags; orb->pointer.high = 0; @@ -433,7 +382,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); spin_lock_irqsave(&device->card->lock, flags); - list_add_tail(&orb->link, &lu->orb_list); + list_add_tail(&orb->link, &sd->orb_list); spin_unlock_irqrestore(&device->card->lock, flags); /* Take a ref for the orb list and for the transaction callback. */ @@ -446,9 +395,10 @@ sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, complete_transaction, orb); } -static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) +static int sbp2_cancel_orbs(struct fw_unit *unit) { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd = unit->device.driver_data; struct sbp2_orb *orb, *next; struct list_head list; unsigned long flags; @@ -456,7 +406,7 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) INIT_LIST_HEAD(&list); spin_lock_irqsave(&device->card->lock, flags); - list_splice_init(&lu->orb_list, &list); + list_splice_init(&sd->orb_list, &list); spin_unlock_irqrestore(&device->card->lock, flags); list_for_each_entry_safe(orb, next, &list, link) { @@ -483,11 +433,11 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) } static int -sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, - int generation, int function, int lun_or_login_id, - void *response) +sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, + int function, int lun, void *response) { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd = unit->device.driver_data; struct sbp2_management_orb *orb; int retval = -ENOMEM; @@ -508,12 +458,12 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, orb->request.misc = MANAGEMENT_ORB_NOTIFY | MANAGEMENT_ORB_FUNCTION(function) | - MANAGEMENT_ORB_LUN(lun_or_login_id); + MANAGEMENT_ORB_LUN(lun); orb->request.length = MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); - orb->request.status_fifo.high = lu->address_handler.offset >> 32; - orb->request.status_fifo.low = lu->address_handler.offset; + orb->request.status_fifo.high = sd->address_handler.offset >> 32; + orb->request.status_fifo.low = sd->address_handler.offset; if (function == SBP2_LOGIN_REQUEST) { orb->request.misc |= @@ -532,14 +482,14 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, if (dma_mapping_error(orb->base.request_bus)) goto fail_mapping_request; - sbp2_send_orb(&orb->base, lu, node_id, generation, - lu->tgt->management_agent_address); + sbp2_send_orb(&orb->base, unit, + node_id, generation, sd->management_agent_address); wait_for_completion_timeout(&orb->done, msecs_to_jiffies(SBP2_ORB_TIMEOUT)); retval = -EIO; - if (sbp2_cancel_orbs(lu) == 0) { + if (sbp2_cancel_orbs(unit) == 0) { fw_error("orb reply timed out, rcode=0x%02x\n", orb->base.rcode); goto out; @@ -584,9 +534,10 @@ complete_agent_reset_write(struct fw_card *card, int rcode, kfree(t); } -static int sbp2_agent_reset(struct sbp2_logical_unit *lu) +static int sbp2_agent_reset(struct fw_unit *unit) { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd = unit->device.driver_data; struct fw_transaction *t; static u32 zero; @@ -595,272 +546,181 @@ static int sbp2_agent_reset(struct sbp2_logical_unit *lu) return -ENOMEM; fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - lu->command_block_agent_address + SBP2_AGENT_RESET, + sd->node_id, sd->generation, device->max_speed, + sd->command_block_agent_address + SBP2_AGENT_RESET, &zero, sizeof(zero), complete_agent_reset_write, t); return 0; } -static void sbp2_release_target(struct kref *kref) -{ - struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref); - struct sbp2_logical_unit *lu, *next; - struct Scsi_Host *shost = - container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - - list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { - if (lu->sdev) - scsi_remove_device(lu->sdev); - - sbp2_send_management_orb(lu, tgt->node_id, lu->generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); - fw_core_remove_address_handler(&lu->address_handler); - list_del(&lu->link); - kfree(lu); - } - scsi_remove_host(shost); - fw_notify("released %s\n", tgt->unit->device.bus_id); +static void sbp2_reconnect(struct work_struct *work); +static struct scsi_host_template scsi_driver_template; - put_device(&tgt->unit->device); - scsi_host_put(shost); +static void release_sbp2_device(struct kref *kref) +{ + struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); + struct Scsi_Host *host = + container_of((void *)sd, struct Scsi_Host, hostdata[0]); + + scsi_remove_host(host); + sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, + SBP2_LOGOUT_REQUEST, sd->login_id, NULL); + fw_core_remove_address_handler(&sd->address_handler); + fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); + put_device(&sd->unit->device); + scsi_host_put(host); } -static struct workqueue_struct *sbp2_wq; - -static void sbp2_reconnect(struct work_struct *work); - static void sbp2_login(struct work_struct *work) { - struct sbp2_logical_unit *lu = - container_of(work, struct sbp2_logical_unit, work.work); - struct Scsi_Host *shost = - container_of((void *)lu->tgt, struct Scsi_Host, hostdata[0]); - struct scsi_device *sdev; - struct scsi_lun eight_bytes_lun; - struct fw_unit *unit = lu->tgt->unit; + struct sbp2_device *sd = + container_of(work, struct sbp2_device, work.work); + struct Scsi_Host *host = + container_of((void *)sd, struct Scsi_Host, hostdata[0]); + struct fw_unit *unit = sd->unit; struct fw_device *device = fw_device(unit->device.parent); struct sbp2_login_response response; - int generation, node_id, local_node_id; + int generation, node_id, local_node_id, lun, retval; + + /* FIXME: Make this work for multi-lun devices. */ + lun = 0; generation = device->card->generation; node_id = device->node->node_id; local_node_id = device->card->local_node->node_id; - if (sbp2_send_management_orb(lu, node_id, generation, - SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { - if (lu->retries++ < 5) { - queue_delayed_work(sbp2_wq, &lu->work, - DIV_ROUND_UP(HZ, 5)); + if (sbp2_send_management_orb(unit, node_id, generation, + SBP2_LOGIN_REQUEST, lun, &response) < 0) { + if (sd->retries++ < 5) { + schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); } else { - fw_error("failed to login to %s LUN %04x\n", - unit->device.bus_id, lu->lun); - kref_put(&lu->tgt->kref, sbp2_release_target); + fw_error("failed to login to %s\n", + unit->device.bus_id); + kref_put(&sd->kref, release_sbp2_device); } return; } - lu->generation = generation; - lu->tgt->node_id = node_id; - lu->tgt->address_high = local_node_id << 16; + sd->generation = generation; + sd->node_id = node_id; + sd->address_high = local_node_id << 16; /* Get command block agent offset and login id. */ - lu->command_block_agent_address = + sd->command_block_agent_address = ((u64) (response.command_block_agent.high & 0xffff) << 32) | response.command_block_agent.low; - lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); + sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); - fw_notify("logged in to %s LUN %04x (%d retries)\n", - unit->device.bus_id, lu->lun, lu->retries); + fw_notify("logged in to sbp2 unit %s (%d retries)\n", + unit->device.bus_id, sd->retries); + fw_notify(" - management_agent_address: 0x%012llx\n", + (unsigned long long) sd->management_agent_address); + fw_notify(" - command_block_agent_address: 0x%012llx\n", + (unsigned long long) sd->command_block_agent_address); + fw_notify(" - status write address: 0x%012llx\n", + (unsigned long long) sd->address_handler.offset); #if 0 /* FIXME: The linux1394 sbp2 does this last step. */ sbp2_set_busy_timeout(scsi_id); #endif - PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect); - sbp2_agent_reset(lu); - - memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); - eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff; - eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff; + PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect); + sbp2_agent_reset(unit); - sdev = __scsi_add_device(shost, 0, 0, - scsilun_to_int(&eight_bytes_lun), lu); - if (IS_ERR(sdev)) { - sbp2_send_management_orb(lu, node_id, generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); + /* FIXME: Loop over luns here. */ + lun = 0; + retval = scsi_add_device(host, 0, 0, lun); + if (retval < 0) { + sbp2_send_management_orb(unit, sd->node_id, sd->generation, + SBP2_LOGOUT_REQUEST, sd->login_id, + NULL); /* * Set this back to sbp2_login so we fall back and * retry login on bus reset. */ - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); - } else { - lu->sdev = sdev; - scsi_device_put(sdev); + PREPARE_DELAYED_WORK(&sd->work, sbp2_login); } - kref_put(&lu->tgt->kref, sbp2_release_target); + kref_put(&sd->kref, release_sbp2_device); } -static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) +static int sbp2_probe(struct device *dev) { - struct sbp2_logical_unit *lu; - - lu = kmalloc(sizeof(*lu), GFP_KERNEL); - if (!lu) - return -ENOMEM; + struct fw_unit *unit = fw_unit(dev); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd; + struct fw_csr_iterator ci; + struct Scsi_Host *host; + int i, key, value, err; + u32 model, firmware_revision; - lu->address_handler.length = 0x100; - lu->address_handler.address_callback = sbp2_status_write; - lu->address_handler.callback_data = lu; + err = -ENOMEM; + host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd)); + if (host == NULL) + goto fail; - if (fw_core_add_address_handler(&lu->address_handler, - &fw_high_memory_region) < 0) { - kfree(lu); - return -ENOMEM; - } + sd = (struct sbp2_device *) host->hostdata; + unit->device.driver_data = sd; + sd->unit = unit; + INIT_LIST_HEAD(&sd->orb_list); + kref_init(&sd->kref); - lu->tgt = tgt; - lu->sdev = NULL; - lu->lun = lun_entry & 0xffff; - lu->retries = 0; - INIT_LIST_HEAD(&lu->orb_list); - INIT_DELAYED_WORK(&lu->work, sbp2_login); + sd->address_handler.length = 0x100; + sd->address_handler.address_callback = sbp2_status_write; + sd->address_handler.callback_data = sd; - list_add_tail(&lu->link, &tgt->lu_list); - return 0; -} + err = fw_core_add_address_handler(&sd->address_handler, + &fw_high_memory_region); + if (err < 0) + goto fail_host; -static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory) -{ - struct fw_csr_iterator ci; - int key, value; - - fw_csr_iterator_init(&ci, directory); - while (fw_csr_iterator_next(&ci, &key, &value)) - if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER && - sbp2_add_logical_unit(tgt, value) < 0) - return -ENOMEM; - return 0; -} + err = fw_device_enable_phys_dma(device); + if (err < 0) + goto fail_address_handler; -static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory, - u32 *model, u32 *firmware_revision) -{ - struct fw_csr_iterator ci; - int key, value; + err = scsi_add_host(host, &unit->device); + if (err < 0) + goto fail_address_handler; - fw_csr_iterator_init(&ci, directory); + /* + * Scan unit directory to get management agent address, + * firmware revison and model. Initialize firmware_revision + * and model to values that wont match anything in our table. + */ + firmware_revision = 0xff000000; + model = 0xff000000; + fw_csr_iterator_init(&ci, unit->directory); while (fw_csr_iterator_next(&ci, &key, &value)) { switch (key) { - case CSR_DEPENDENT_INFO | CSR_OFFSET: - tgt->management_agent_address = - CSR_REGISTER_BASE + 4 * value; + sd->management_agent_address = + 0xfffff0000000ULL + 4 * value; break; - - case CSR_DIRECTORY_ID: - tgt->directory_id = value; + case SBP2_FIRMWARE_REVISION: + firmware_revision = value; break; - case CSR_MODEL: - *model = value; - break; - - case SBP2_CSR_FIRMWARE_REVISION: - *firmware_revision = value; - break; - - case SBP2_CSR_LOGICAL_UNIT_NUMBER: - if (sbp2_add_logical_unit(tgt, value) < 0) - return -ENOMEM; - break; - - case SBP2_CSR_LOGICAL_UNIT_DIRECTORY: - if (sbp2_scan_logical_unit_dir(tgt, ci.p + value) < 0) - return -ENOMEM; + model = value; break; } } - return 0; -} - -static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, - u32 firmware_revision) -{ - int i; - unsigned w = sbp2_param_workarounds; - - if (w) - fw_notify("Please notify linux1394-devel@lists.sourceforge.net " - "if you need the workarounds parameter for %s\n", - tgt->unit->device.bus_id); - - if (w & SBP2_WORKAROUND_OVERRIDE) - goto out; for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { - if (sbp2_workarounds_table[i].firmware_revision != (firmware_revision & 0xffffff00)) continue; - if (sbp2_workarounds_table[i].model != model && sbp2_workarounds_table[i].model != ~0) continue; - - w |= sbp2_workarounds_table[i].workarounds; + sd->workarounds |= sbp2_workarounds_table[i].workarounds; break; } - out: - if (w) - fw_notify("Workarounds for %s: 0x%x " - "(firmware_revision 0x%06x, model_id 0x%06x)\n", - tgt->unit->device.bus_id, - w, firmware_revision, model); - tgt->workarounds = w; -} - -static struct scsi_host_template scsi_driver_template; - -static int sbp2_probe(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_target *tgt; - struct sbp2_logical_unit *lu; - struct Scsi_Host *shost; - u32 model, firmware_revision; - - shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); - if (shost == NULL) - return -ENOMEM; - tgt = (struct sbp2_target *)shost->hostdata; - unit->device.driver_data = tgt; - tgt->unit = unit; - kref_init(&tgt->kref); - INIT_LIST_HEAD(&tgt->lu_list); - - if (fw_device_enable_phys_dma(device) < 0) - goto fail_shost_put; - - if (scsi_add_host(shost, &unit->device) < 0) - goto fail_shost_put; - - /* Initialize to values that won't match anything in our table. */ - firmware_revision = 0xff000000; - model = 0xff000000; - - /* implicit directory ID */ - tgt->directory_id = ((unit->directory - device->config_rom) * 4 - + CSR_CONFIG_ROM) & 0xffffff; - - if (sbp2_scan_unit_dir(tgt, unit->directory, &model, - &firmware_revision) < 0) - goto fail_tgt_put; - - sbp2_init_workarounds(tgt, model, firmware_revision); + if (sd->workarounds) + fw_notify("Workarounds for node %s: 0x%x " + "(firmware_revision 0x%06x, model_id 0x%06x)\n", + unit->device.bus_id, + sd->workarounds, firmware_revision, model); get_device(&unit->device); @@ -869,34 +729,35 @@ static int sbp2_probe(struct device *dev) * reschedule retries. Always get the ref before scheduling * work. */ - list_for_each_entry(lu, &tgt->lu_list, link) - if (queue_delayed_work(sbp2_wq, &lu->work, 0)) - kref_get(&tgt->kref); - return 0; + INIT_DELAYED_WORK(&sd->work, sbp2_login); + if (schedule_delayed_work(&sd->work, 0)) + kref_get(&sd->kref); - fail_tgt_put: - kref_put(&tgt->kref, sbp2_release_target); - return -ENOMEM; + return 0; - fail_shost_put: - scsi_host_put(shost); - return -ENOMEM; + fail_address_handler: + fw_core_remove_address_handler(&sd->address_handler); + fail_host: + scsi_host_put(host); + fail: + return err; } static int sbp2_remove(struct device *dev) { struct fw_unit *unit = fw_unit(dev); - struct sbp2_target *tgt = unit->device.driver_data; + struct sbp2_device *sd = unit->device.driver_data; + + kref_put(&sd->kref, release_sbp2_device); - kref_put(&tgt->kref, sbp2_release_target); return 0; } static void sbp2_reconnect(struct work_struct *work) { - struct sbp2_logical_unit *lu = - container_of(work, struct sbp2_logical_unit, work.work); - struct fw_unit *unit = lu->tgt->unit; + struct sbp2_device *sd = + container_of(work, struct sbp2_device, work.work); + struct fw_unit *unit = sd->unit; struct fw_device *device = fw_device(unit->device.parent); int generation, node_id, local_node_id; @@ -904,49 +765,40 @@ static void sbp2_reconnect(struct work_struct *work) node_id = device->node->node_id; local_node_id = device->card->local_node->node_id; - if (sbp2_send_management_orb(lu, node_id, generation, + if (sbp2_send_management_orb(unit, node_id, generation, SBP2_RECONNECT_REQUEST, - lu->login_id, NULL) < 0) { - if (lu->retries++ >= 5) { + sd->login_id, NULL) < 0) { + if (sd->retries++ >= 5) { fw_error("failed to reconnect to %s\n", unit->device.bus_id); /* Fall back and try to log in again. */ - lu->retries = 0; - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); + sd->retries = 0; + PREPARE_DELAYED_WORK(&sd->work, sbp2_login); } - queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)); + schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); return; } - lu->generation = generation; - lu->tgt->node_id = node_id; - lu->tgt->address_high = local_node_id << 16; + sd->generation = generation; + sd->node_id = node_id; + sd->address_high = local_node_id << 16; - fw_notify("reconnected to %s LUN %04x (%d retries)\n", - unit->device.bus_id, lu->lun, lu->retries); - - sbp2_agent_reset(lu); - sbp2_cancel_orbs(lu); - - kref_put(&lu->tgt->kref, sbp2_release_target); + fw_notify("reconnected to unit %s (%d retries)\n", + unit->device.bus_id, sd->retries); + sbp2_agent_reset(unit); + sbp2_cancel_orbs(unit); + kref_put(&sd->kref, release_sbp2_device); } static void sbp2_update(struct fw_unit *unit) { - struct sbp2_target *tgt = unit->device.driver_data; - struct sbp2_logical_unit *lu; - - fw_device_enable_phys_dma(fw_device(unit->device.parent)); + struct fw_device *device = fw_device(unit->device.parent); + struct sbp2_device *sd = unit->device.driver_data; - /* - * Fw-core serializes sbp2_update() against sbp2_remove(). - * Iteration over tgt->lu_list is therefore safe here. - */ - list_for_each_entry(lu, &tgt->lu_list, link) { - lu->retries = 0; - if (queue_delayed_work(sbp2_wq, &lu->work, 0)) - kref_get(&tgt->kref); - } + sd->retries = 0; + fw_device_enable_phys_dma(device); + if (schedule_delayed_work(&sd->work, 0)) + kref_get(&sd->kref); } #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e @@ -1016,12 +868,13 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) { struct sbp2_command_orb *orb = container_of(base_orb, struct sbp2_command_orb, base); - struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent); + struct fw_unit *unit = orb->unit; + struct fw_device *device = fw_device(unit->device.parent); int result; if (status != NULL) { if (STATUS_GET_DEAD(*status)) - sbp2_agent_reset(orb->lu); + sbp2_agent_reset(unit); switch (STATUS_GET_RESPONSE(*status)) { case SBP2_STATUS_REQUEST_COMPLETE: @@ -1065,10 +918,12 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) orb->done(orb->cmd); } -static int -sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, - struct sbp2_logical_unit *lu) +static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) { + struct sbp2_device *sd = + (struct sbp2_device *)orb->cmd->device->host->hostdata; + struct fw_unit *unit = sd->unit; + struct fw_device *device = fw_device(unit->device.parent); struct scatterlist *sg; int sg_len, l, i, j, count; dma_addr_t sg_addr; @@ -1087,9 +942,10 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, * tables. */ if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { - orb->request.data_descriptor.high = lu->tgt->address_high; + orb->request.data_descriptor.high = sd->address_high; orb->request.data_descriptor.low = sg_dma_address(sg); - orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); + orb->request.misc |= + COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); return 0; } @@ -1133,7 +989,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, * initiator (i.e. us), but data_descriptor can refer to data * on other nodes so we need to put our ID in descriptor.high. */ - orb->request.data_descriptor.high = lu->tgt->address_high; + orb->request.data_descriptor.high = sd->address_high; orb->request.data_descriptor.low = orb->page_table_bus; orb->request.misc |= COMMAND_ORB_PAGE_TABLE_PRESENT | @@ -1152,11 +1008,12 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) { - struct sbp2_logical_unit *lu = cmd->device->hostdata; - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); + struct sbp2_device *sd = + (struct sbp2_device *)cmd->device->host->hostdata; + struct fw_unit *unit = sd->unit; + struct fw_device *device = fw_device(unit->device.parent); struct sbp2_command_orb *orb; unsigned max_payload; - int retval = SCSI_MLQUEUE_HOST_BUSY; /* * Bidirectional commands are not yet implemented, and unknown @@ -1172,14 +1029,14 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) orb = kzalloc(sizeof(*orb), GFP_ATOMIC); if (orb == NULL) { fw_notify("failed to alloc orb\n"); - return SCSI_MLQUEUE_HOST_BUSY; + goto fail_alloc; } /* Initialize rcode to something not RCODE_COMPLETE. */ orb->base.rcode = -1; kref_init(&orb->base.kref); - orb->lu = lu; + orb->unit = unit; orb->done = done; orb->cmd = cmd; @@ -1205,8 +1062,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) orb->request.misc |= COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); - if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0) - goto out; + if (scsi_sg_count(cmd) && sbp2_command_orb_map_scatterlist(orb) < 0) + goto fail_mapping; fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); @@ -1219,47 +1076,49 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) dma_map_single(device->card->device, &orb->request, sizeof(orb->request), DMA_TO_DEVICE); if (dma_mapping_error(orb->base.request_bus)) - goto out; + goto fail_mapping; + + sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation, + sd->command_block_agent_address + SBP2_ORB_POINTER); - sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation, - lu->command_block_agent_address + SBP2_ORB_POINTER); - retval = 0; - out: kref_put(&orb->base.kref, free_orb); - return retval; + return 0; + + fail_mapping: + kref_put(&orb->base.kref, free_orb); + fail_alloc: + return SCSI_MLQUEUE_HOST_BUSY; } static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) { - struct sbp2_logical_unit *lu = sdev->hostdata; + struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; sdev->allow_restart = 1; - if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36) + if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36) sdev->inquiry_len = 36; - return 0; } static int sbp2_scsi_slave_configure(struct scsi_device *sdev) { - struct sbp2_logical_unit *lu = sdev->hostdata; + struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; + struct fw_unit *unit = sd->unit; sdev->use_10_for_rw = 1; if (sdev->type == TYPE_ROM) sdev->use_10_for_ms = 1; - if (sdev->type == TYPE_DISK && - lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) + sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) sdev->skip_ms_page_8 = 1; - - if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) + if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) { + fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); sdev->fix_capacity = 1; - - if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) + } + if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); - return 0; } @@ -1269,11 +1128,13 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) */ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) { - struct sbp2_logical_unit *lu = cmd->device->hostdata; + struct sbp2_device *sd = + (struct sbp2_device *)cmd->device->host->hostdata; + struct fw_unit *unit = sd->unit; fw_notify("sbp2_scsi_abort\n"); - sbp2_agent_reset(lu); - sbp2_cancel_orbs(lu); + sbp2_agent_reset(unit); + sbp2_cancel_orbs(unit); return SUCCESS; } @@ -1290,18 +1151,37 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct scsi_device *sdev = to_scsi_device(dev); - struct sbp2_logical_unit *lu; + struct sbp2_device *sd; + struct fw_unit *unit; struct fw_device *device; + u32 directory_id; + struct fw_csr_iterator ci; + int key, value, lun; if (!sdev) return 0; + sd = (struct sbp2_device *)sdev->host->hostdata; + unit = sd->unit; + device = fw_device(unit->device.parent); + + /* implicit directory ID */ + directory_id = ((unit->directory - device->config_rom) * 4 + + CSR_CONFIG_ROM) & 0xffffff; + + /* explicit directory ID, overrides implicit ID if present */ + fw_csr_iterator_init(&ci, unit->directory); + while (fw_csr_iterator_next(&ci, &key, &value)) + if (key == CSR_DIRECTORY_ID) { + directory_id = value; + break; + } - lu = sdev->hostdata; - device = fw_device(lu->tgt->unit->device.parent); + /* FIXME: Make this work for multi-lun devices. */ + lun = 0; return sprintf(buf, "%08x%08x:%06x:%04x\n", device->config_rom[3], device->config_rom[4], - lu->tgt->directory_id, lu->lun); + directory_id, lun); } static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); @@ -1339,17 +1219,12 @@ MODULE_ALIAS("sbp2"); static int __init sbp2_init(void) { - sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME); - if (!sbp2_wq) - return -ENOMEM; - return driver_register(&sbp2_driver.driver); } static void __exit sbp2_cleanup(void) { driver_unregister(&sbp2_driver.driver); - destroy_workqueue(sbp2_wq); } module_init(sbp2_init); diff --git a/trunk/drivers/firewire/fw-topology.c b/trunk/drivers/firewire/fw-topology.c index 0fc9b000e99d..39e5cd12aa52 100644 --- a/trunk/drivers/firewire/fw-topology.c +++ b/trunk/drivers/firewire/fw-topology.c @@ -152,10 +152,6 @@ static void update_hop_count(struct fw_node *node) node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2); } -static inline struct fw_node *fw_node(struct list_head *l) -{ - return list_entry(l, struct fw_node, link); -} /** * build_tree - Build the tree representation of the topology @@ -166,7 +162,7 @@ static inline struct fw_node *fw_node(struct list_head *l) * This function builds the tree representation of the topology given * by the self IDs from the latest bus reset. During the construction * of the tree, the function checks that the self IDs are valid and - * internally consistent. On succcess this function returns the + * internally consistent. On succcess this funtions returns the * fw_node corresponding to the local card otherwise NULL. */ static struct fw_node *build_tree(struct fw_card *card, @@ -215,10 +211,6 @@ static struct fw_node *build_tree(struct fw_card *card, */ for (i = 0, h = &stack; i < child_port_count; i++) h = h->prev; - /* - * When the stack is empty, this yields an invalid value, - * but that pointer will never be dereferenced. - */ child = fw_node(h); node = fw_node_create(q, port_count, card->color); diff --git a/trunk/drivers/firewire/fw-topology.h b/trunk/drivers/firewire/fw-topology.h index cedc1ec906e9..1b56b4ac7fb2 100644 --- a/trunk/drivers/firewire/fw-topology.h +++ b/trunk/drivers/firewire/fw-topology.h @@ -50,6 +50,12 @@ struct fw_node { struct fw_node *ports[0]; }; +static inline struct fw_node * +fw_node(struct list_head *l) +{ + return list_entry(l, struct fw_node, link); +} + static inline struct fw_node * fw_node_get(struct fw_node *node) { diff --git a/trunk/drivers/firewire/fw-transaction.c b/trunk/drivers/firewire/fw-transaction.c index 9959b799dbe2..3e1cb12e43cd 100644 --- a/trunk/drivers/firewire/fw-transaction.c +++ b/trunk/drivers/firewire/fw-transaction.c @@ -410,12 +410,7 @@ EXPORT_SYMBOL(fw_unit_space_region); * controller. When a request is received that falls within the * specified address range, the specified callback is invoked. The * parameters passed to the callback give the details of the - * particular request. - * - * Return value: 0 on success, non-zero otherwise. - * The start offset of the handler's address region is determined by - * fw_core_add_address_handler() and is returned in handler->offset. - * The offset is quadlet-aligned. + * particular request */ int fw_core_add_address_handler(struct fw_address_handler *handler, @@ -427,15 +422,14 @@ fw_core_add_address_handler(struct fw_address_handler *handler, spin_lock_irqsave(&address_handler_lock, flags); - handler->offset = roundup(region->start, 4); + handler->offset = region->start; while (handler->offset + handler->length <= region->end) { other = lookup_overlapping_address_handler(&address_handler_list, handler->offset, handler->length); if (other != NULL) { - handler->offset = - roundup(other->offset + other->length, 4); + handler->offset += other->length; } else { list_add_tail(&handler->link, &address_handler_list); ret = 0; diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 6d9fd92763f4..8982c0932438 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -435,6 +435,24 @@ config BLK_DEV_IDEDMA_PCI bool select BLK_DEV_IDEPCI +config BLK_DEV_IDEDMA_FORCED + bool "Force enable legacy 2.0.X HOSTS to use DMA" + depends on BLK_DEV_IDEDMA_PCI + help + This is an old piece of lost code from Linux 2.0 Kernels. + + Generally say N here. + +# TODO: remove it +config IDEDMA_ONLYDISK + bool "Enable DMA only for disks " + depends on BLK_DEV_IDEDMA_PCI + help + This is used if you know your ATAPI Devices are going to fail DMA + Transfers. + + Generally say N here. + config BLK_DEV_AEC62XX tristate "AEC62XX chipset support" select BLK_DEV_IDEDMA_PCI diff --git a/trunk/drivers/ide/arm/icside.c b/trunk/drivers/ide/arm/icside.c index e4875cef78bb..bd1f5b670378 100644 --- a/trunk/drivers/ide/arm/icside.c +++ b/trunk/drivers/ide/arm/icside.c @@ -309,6 +309,14 @@ static int icside_dma_on(ide_drive_t *drive) return 0; } +static int icside_dma_check(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + return -1; +} + static int icside_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -415,6 +423,8 @@ static void icside_dma_lost_irq(ide_drive_t *drive) static void icside_dma_init(ide_hwif_t *hwif) { + printk(" %s: SG-DMA", hwif->name); + hwif->atapi_dma = 1; hwif->mwdma_mask = 7; /* MW0..2 */ hwif->swdma_mask = 7; /* SW0..2 */ @@ -422,7 +432,9 @@ static void icside_dma_init(ide_hwif_t *hwif) hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; hwif->set_dma_mode = icside_set_dma_mode; + hwif->autodma = 1; + hwif->ide_dma_check = icside_dma_check; hwif->dma_host_off = icside_dma_host_off; hwif->dma_off_quietly = icside_dma_off_quietly; hwif->dma_host_on = icside_dma_host_on; @@ -434,6 +446,11 @@ static void icside_dma_init(ide_hwif_t *hwif) hwif->ide_dma_test_irq = icside_dma_test_irq; hwif->dma_timeout = icside_dma_timeout; hwif->dma_lost_irq = icside_dma_lost_irq; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + + printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); } #else #define icside_dma_init(hwif) (0) diff --git a/trunk/drivers/ide/cris/ide-cris.c b/trunk/drivers/ide/cris/ide-cris.c index 06c75f18eb88..2b4d2a0ae5c2 100644 --- a/trunk/drivers/ide/cris/ide-cris.c +++ b/trunk/drivers/ide/cris/ide-cris.c @@ -664,6 +664,7 @@ cris_ide_inb(unsigned long reg) return (unsigned char)cris_ide_inw(reg); } +static int cris_dma_check (ide_drive_t *drive); static int cris_dma_end (ide_drive_t *drive); static int cris_dma_setup (ide_drive_t *drive); static void cris_dma_exec_cmd (ide_drive_t *drive, u8 command); @@ -791,6 +792,7 @@ init_e100_ide (void) hwif->ata_output_data = &cris_ide_output_data; hwif->atapi_input_bytes = &cris_atapi_input_bytes; hwif->atapi_output_bytes = &cris_atapi_output_bytes; + hwif->ide_dma_check = &cris_dma_check; hwif->ide_dma_end = &cris_dma_end; hwif->dma_setup = &cris_dma_setup; hwif->dma_exec_cmd = &cris_dma_exec_cmd; @@ -806,10 +808,11 @@ init_e100_ide (void) hwif->dma_off_quietly = &cris_dma_off; hwif->cbl = ATA_CBL_PATA40; hwif->pio_mask = ATA_PIO4, - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; hwif->ultra_mask = cris_ultra_mask; hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */ + hwif->autodma = 1; + hwif->drives[0].autodma = 1; + hwif->drives[1].autodma = 1; } /* Reset pulse */ @@ -936,8 +939,7 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) /* group sequential buffers into one large buffer */ addr = page_to_phys(sg->page) + sg->offset; size = sg_dma_len(sg); - while (--i) { - sg = sg_next(sg); + while (sg++, --i) { if ((addr + size) != page_to_phys(sg->page) + sg->offset) break; size += sg_dma_len(sg); @@ -1015,6 +1017,14 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive) * the caller should revert to PIO for the current request. */ +static int cris_dma_check(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + return -1; +} + static int cris_dma_end(ide_drive_t *drive) { drive->waiting_for_dma = 0; diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 92177ca48b4d..4754769eda97 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -716,6 +716,32 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) rq->buffer = rq->cmd; } +static int idedisk_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + ide_drive_t *drive = q->queuedata; + struct request *rq; + int ret; + + if (!drive->wcache) + return 0; + + rq = blk_get_request(q, WRITE, __GFP_WAIT); + + idedisk_prepare_flush(q, rq); + + ret = blk_execute_rq(q, disk, rq, 0); + + /* + * if we failed and caller wants error offset, get it + */ + if (ret && error_sector) + *error_sector = ide_get_error_location(drive, rq->cmd); + + blk_put_request(rq); + return ret; +} + /* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. @@ -755,6 +781,7 @@ static void update_ordered(ide_drive_t *drive) struct hd_driveid *id = drive->id; unsigned ordered = QUEUE_ORDERED_NONE; prepare_flush_fn *prep_fn = NULL; + issue_flush_fn *issue_fn = NULL; if (drive->wcache) { unsigned long long capacity; @@ -778,11 +805,13 @@ static void update_ordered(ide_drive_t *drive) if (barrier) { ordered = QUEUE_ORDERED_DRAIN_FLUSH; prep_fn = idedisk_prepare_flush; + issue_fn = idedisk_issue_flush; } } else ordered = QUEUE_ORDERED_DRAIN; blk_queue_ordered(drive->queue, ordered, prep_fn); + blk_queue_issue_flush_fn(drive->queue, issue_fn); } static int write_cache(ide_drive_t *drive, int arg) diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index bc57ce6bf0b3..b453211ee0fc 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -280,7 +280,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) } } - sg = sg_next(sg); + sg++; i--; } @@ -338,30 +338,35 @@ static int config_drive_for_dma (ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; struct hd_driveid *id = drive->id; - if (drive->media != ide_disk && hwif->atapi_dma == 0) - return 0; - - /* - * Enable DMA on any drive that has - * UltraDMA (mode 0/1/2/3/4/5/6) enabled - */ - if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) - return 1; + /* consult the list of known "bad" drives */ + if (__ide_dma_bad_drive(drive)) + return -1; - /* - * Enable DMA on any drive that has mode2 DMA - * (multi or single) enabled - */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || - (id->dma_1word & 0x404) == 0x404) - return 1; + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return -1; - /* Consult the list of known "good" drives */ - if (ide_dma_good_drive(drive)) - return 1; + if ((id->capability & 1) && drive->autodma) { + /* + * Enable DMA on any drive that has + * UltraDMA (mode 0/1/2/3/4/5/6) enabled + */ + if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) + return 0; + /* + * Enable DMA on any drive that has mode2 DMA + * (multi or single) enabled + */ + if (id->field_valid & 2) /* regular DMA */ + if ((id->dma_mword & 0x404) == 0x404 || + (id->dma_1word & 0x404) == 0x404) + return 0; + + /* Consult the list of known "good" drives */ + if (ide_dma_good_drive(drive)) + return 0; + } - return 0; + return -1; } /** @@ -622,8 +627,6 @@ static int __ide_dma_test_irq(ide_drive_t *drive) drive->name, __FUNCTION__); return 0; } -#else -static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; } #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ int __ide_dma_bad_drive (ide_drive_t *drive) @@ -755,20 +758,17 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) EXPORT_SYMBOL_GPL(ide_find_dma_mode); -static int ide_tune_dma(ide_drive_t *drive) +int ide_tune_dma(ide_drive_t *drive) { u8 speed; - if (noautodma || drive->nodma || (drive->id->capability & 1) == 0) + if ((drive->id->capability & 1) == 0 || drive->autodma == 0) return 0; /* consult the list of known "bad" drives */ if (__ide_dma_bad_drive(drive)) return 0; - if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) - return config_drive_for_dma(drive); - speed = ide_max_dma_mode(drive); if (!speed) @@ -783,22 +783,7 @@ static int ide_tune_dma(ide_drive_t *drive) return 1; } -static int ide_dma_check(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0; - - if (!vdma && ide_tune_dma(drive)) - return 0; - - /* TODO: always do PIO fallback */ - if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) - return -1; - - ide_set_max_pio(drive); - - return vdma ? 0 : -1; -} +EXPORT_SYMBOL_GPL(ide_tune_dma); void ide_dma_verbose(ide_drive_t *drive) { @@ -857,7 +842,7 @@ int ide_set_dma(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; int rc; - rc = ide_dma_check(drive); + rc = hwif->ide_dma_check(drive); switch(rc) { case -1: /* DMA needs to be disabled */ @@ -1034,6 +1019,8 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->ide_dma_on = &__ide_dma_on; if (!hwif->dma_host_on) hwif->dma_host_on = &ide_dma_host_on; + if (!hwif->ide_dma_check) + hwif->ide_dma_check = &config_drive_for_dma; if (!hwif->dma_setup) hwif->dma_setup = &ide_dma_setup; if (!hwif->dma_exec_cmd) diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index ec835e37e729..4cece930114c 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -219,11 +219,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ /* - * Right now, all we do is call ide_set_dma(drive), + * Right now, all we do is call hwif->ide_dma_check(drive), * we could be smarter and check for current xfer_speed * in struct drive etc... */ - if (drive->hwif->ide_dma_on == NULL) + if (drive->hwif->ide_dma_check == NULL) break; drive->hwif->dma_off_quietly(drive); /* @@ -322,6 +322,41 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) spin_unlock_irqrestore(&ide_lock, flags); } +/* + * FIXME: probably move this somewhere else, name is bad too :) + */ +u64 ide_get_error_location(ide_drive_t *drive, char *args) +{ + u32 high, low; + u8 hcyl, lcyl, sect; + u64 sector; + + high = 0; + hcyl = args[5]; + lcyl = args[4]; + sect = args[3]; + + if (ide_id_has_flush_cache_ext(drive->id)) { + low = (hcyl << 16) | (lcyl << 8) | sect; + HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); + high = ide_read_24(drive); + } else { + u8 cur = HWIF(drive)->INB(IDE_SELECT_REG); + if (cur & 0x40) { + high = cur & 0xf; + low = (hcyl << 16) | (lcyl << 8) | sect; + } else { + low = hcyl * drive->head * drive->sect; + low += lcyl * drive->sect; + low += sect - 1; + } + } + + sector = ((u64) high << 24) | low; + return sector; +} +EXPORT_SYMBOL(ide_get_error_location); + /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -846,8 +881,7 @@ void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = drive->hwif; hwif->nsect = hwif->nleft = rq->nr_sectors; - hwif->cursg_ofs = 0; - hwif->cursg = NULL; + hwif->cursg = hwif->cursg_ofs = 0; } EXPORT_SYMBOL_GPL(ide_init_sg_cmd); diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index d4d790f91f91..aa738833bed5 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -776,7 +776,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) // msleep(50); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->ide_dma_on) /* check if host supports DMA */ + if (hwif->ide_dma_check) /* check if host supports DMA */ hwif->dma_host_off(drive); #endif @@ -830,7 +830,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) hwif->dma_host_on(drive); - else if (hwif->ide_dma_on) /* check if host supports DMA */ + else if (hwif->ide_dma_check) /* check if host supports DMA */ hwif->dma_off_quietly(drive); #endif diff --git a/trunk/drivers/ide/ide-lib.c b/trunk/drivers/ide/ide-lib.c index af86433baede..0e2562f0f74e 100644 --- a/trunk/drivers/ide/ide-lib.c +++ b/trunk/drivers/ide/ide-lib.c @@ -96,6 +96,21 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) return min(speed, mode); } +int ide_use_fast_pio(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) && drive->autodma) + return 1; + + if ((id->capability & 8) || (id->field_valid & 2)) + return 1; + + return 0; +} + +EXPORT_SYMBOL_GPL(ide_use_fast_pio); + /* * Standard (generic) timings for PIO modes, from ATA2 specification. * These timings are for access to the IDE data port register *only*. diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 3c945d64d845..d1011712601c 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -835,7 +835,16 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) drive->nice1 = 1; - if (hwif->ide_dma_on) { + /* + * MAJOR HACK BARF :-/ + * + * FIXME: chipsets own this cruft! + */ + /* + * Move here to prevent module loading clashing. + */ + // drive->autodma = hwif->autodma; + if (hwif->ide_dma_check) { /* * Force DMAing for the beginning of the check. * Some chipsets appear to do interesting @@ -843,7 +852,10 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) * PARANOIA!!! */ hwif->dma_off_quietly(drive); - ide_set_dma(drive); +#ifdef CONFIG_IDEDMA_ONLYDISK + if (drive->media == ide_disk) +#endif + ide_set_dma(drive); } } } @@ -1337,7 +1349,7 @@ static int hwif_init(ide_hwif_t *hwif) if (!hwif->sg_max_nents) hwif->sg_max_nents = PRD_ENTRIES; - hwif->sg_table = kzalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, + hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, GFP_KERNEL); if (!hwif->sg_table) { printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 2a3c8d498343..aa06dafb74ac 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -264,7 +263,6 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; - struct scatterlist *cursg = hwif->cursg; struct page *page; #ifdef CONFIG_HIGHMEM unsigned long flags; @@ -272,14 +270,8 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) unsigned int offset; u8 *buf; - cursg = hwif->cursg; - if (!cursg) { - cursg = sg; - hwif->cursg = sg; - } - - page = cursg->page; - offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE; + page = sg[hwif->cursg].page; + offset = sg[hwif->cursg].offset + hwif->cursg_ofs * SECTOR_SIZE; /* get the current page and offset */ page = nth_page(page, (offset >> PAGE_SHIFT)); @@ -293,8 +285,8 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) hwif->nleft--; hwif->cursg_ofs++; - if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) { - hwif->cursg = sg_next(hwif->cursg); + if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) { + hwif->cursg++; hwif->cursg_ofs = 0; } @@ -375,8 +367,6 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { - HWIF(drive)->cursg = NULL; - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { ide_task_t *task = rq->special; diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index 5b090662683e..5c0e4078b5cb 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -100,6 +100,8 @@ static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ int noautodma = 0; +EXPORT_SYMBOL(noautodma); + #ifdef CONFIG_BLK_DEV_IDEACPI int ide_noacpi = 0; int ide_noacpitfs = 1; @@ -416,6 +418,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; hwif->dma_start = tmp_hwif->dma_start; hwif->ide_dma_end = tmp_hwif->ide_dma_end; + hwif->ide_dma_check = tmp_hwif->ide_dma_check; hwif->ide_dma_on = tmp_hwif->ide_dma_on; hwif->dma_off_quietly = tmp_hwif->dma_off_quietly; hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; @@ -458,6 +461,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->select_data = tmp_hwif->select_data; hwif->extra_base = tmp_hwif->extra_base; hwif->extra_ports = tmp_hwif->extra_ports; + hwif->autodma = tmp_hwif->autodma; hwif->hwif_data = tmp_hwif->hwif_data; } @@ -819,7 +823,7 @@ int set_using_dma(ide_drive_t *drive, int arg) if (!drive->id || !(drive->id->capability & 1)) goto out; - if (hwif->ide_dma_on == NULL) + if (hwif->ide_dma_check == NULL) goto out; err = -EBUSY; @@ -1272,7 +1276,7 @@ static int __init ide_setup(char *s) if (!strcmp(s, "ide=nodma")) { printk(" : Prevented DMA\n"); noautodma = 1; - goto obsolete_option; + return 1; } #ifdef CONFIG_IDEPCI_PCIBUS_ORDER @@ -1306,7 +1310,7 @@ static int __init ide_setup(char *s) */ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { - "none", "noprobe", "nowerr", "cdrom", "nodma", + "none", "noprobe", "nowerr", "cdrom", "minus5", "autotune", "noautotune", "minus8", "swapdata", "bswap", "noflush", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; @@ -1334,9 +1338,6 @@ static int __init ide_setup(char *s) drive->ready_stat = 0; hwif->noprobe = 0; goto done; - case -5: /* nodma */ - drive->nodma = 1; - goto done; case -6: /* "autotune" */ drive->autotune = IDE_TUNE_AUTO; goto obsolete_option; @@ -1398,7 +1399,7 @@ static int __init ide_setup(char *s) */ static const char *ide_words[] = { "noprobe", "serialize", "minus3", "minus4", - "reset", "minus6", "ata66", "minus8", "minus9", + "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; hw = s[3] - '0'; @@ -1477,7 +1478,6 @@ static int __init ide_setup(char *s) case -10: /* minus10 */ case -9: /* minus9 */ case -8: /* minus8 */ - case -6: case -4: case -3: goto bad_option; @@ -1492,6 +1492,9 @@ static int __init ide_setup(char *s) #else goto bad_hwif; #endif + case -6: /* dma */ + hwif->autodma = 1; + goto obsolete_option; case -5: /* "reset" */ hwif->reset = 1; goto obsolete_option; diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index e8e360c2619d..4cdb519f9832 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -28,7 +28,7 @@ and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - + ======================================================================*/ #include @@ -327,13 +327,13 @@ static int ide_config(struct pcmcia_device *link) After a card is removed, ide_release() will unregister the net device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. - + ======================================================================*/ void ide_release(struct pcmcia_device *link) { ide_info_t *info = link->priv; - + DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { @@ -353,12 +353,11 @@ void ide_release(struct pcmcia_device *link) stuff to run after an event is received. A CARD_REMOVAL event also sets some flags to discourage the ide drivers from talking to the ports. - + ======================================================================*/ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_FUNC_ID(4), - PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ @@ -367,7 +366,7 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ - PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ @@ -385,7 +384,6 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), diff --git a/trunk/drivers/ide/mips/au1xxx-ide.c b/trunk/drivers/ide/mips/au1xxx-ide.c index 47c035a550e3..aebde49365d1 100644 --- a/trunk/drivers/ide/mips/au1xxx-ide.c +++ b/trunk/drivers/ide/mips/au1xxx-ide.c @@ -296,7 +296,7 @@ static int auide_build_dmatable(ide_drive_t *drive) cur_addr += tc; cur_len -= tc; } - sg = sg_next(sg); + sg++; i--; } @@ -351,18 +351,11 @@ static int auide_dma_setup(ide_drive_t *drive) return 0; } -static u8 auide_mdma_filter(ide_drive_t *drive) +static int auide_dma_check(ide_drive_t *drive) { - /* - * FIXME: ->white_list and ->black_list are based on completely bogus - * ->ide_dma_check implementation which didn't set neither the host - * controller timings nor the device for the desired transfer mode. - * - * They should be either removed or 0x00 MWDMA mask should be - * returned for devices on the ->black_list. - */ + u8 speed = ide_max_dma_mode(drive); - if (dbdma_init_done == 0) { + if( dbdma_init_done == 0 ){ auide_hwif.white_list = ide_in_drive_list(drive->id, dma_white_list); auide_hwif.black_list = ide_in_drive_list(drive->id, @@ -373,11 +366,22 @@ static u8 auide_mdma_filter(ide_drive_t *drive) } /* Is the drive in our DMA black list? */ - if (auide_hwif.black_list) + + if ( auide_hwif.black_list ) { + drive->using_dma = 0; + + /* Borrowed the warning message from ide-dma.c */ + printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n", - drive->name, drive->id->model); + drive->name, drive->id->model); + } + else + drive->using_dma = 1; + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return 0; - return drive->hwif->mwdma_mask; + return -1; } static int auide_dma_test_irq(ide_drive_t *drive) @@ -688,8 +692,7 @@ static int au_ide_probe(struct device *dev) hwif->dma_off_quietly = &auide_dma_off_quietly; hwif->dma_timeout = &auide_dma_timeout; - hwif->mdma_filter = &auide_mdma_filter; - + hwif->ide_dma_check = &auide_dma_check; hwif->dma_exec_cmd = &auide_dma_exec_cmd; hwif->dma_start = &auide_dma_start; hwif->ide_dma_end = &auide_dma_end; @@ -700,14 +703,19 @@ static int au_ide_probe(struct device *dev) hwif->dma_lost_irq = &auide_dma_lost_irq; hwif->ide_dma_on = &auide_dma_on; + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; hwif->atapi_dma = 1; #else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ + hwif->autodma = 0; hwif->channel = 0; hwif->hold = 1; hwif->select_data = 0; /* no chipset-specific code */ hwif->config_data = 0; /* no chipset-specific code */ + hwif->drives[0].autodma = 0; hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ #endif hwif->drives[0].no_io_32bit = 1; diff --git a/trunk/drivers/ide/pci/aec62xx.c b/trunk/drivers/ide/pci/aec62xx.c index 3a4c2c26a77e..d6cb2d5143c8 100644 --- a/trunk/drivers/ide/pci/aec62xx.c +++ b/trunk/drivers/ide/pci/aec62xx.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/aec62xx.c Version 0.25 Aug 1, 2007 + * linux/drivers/ide/pci/aec62xx.c Version 0.24 May 24, 2007 * * Copyright (C) 1999-2002 Andre Hedrick * Copyright (C) 2007 MontaVista Software, Inc. @@ -141,6 +141,17 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0); } +static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static void aec62xx_dma_lost_irq (ide_drive_t *drive) { switch (HWIF(drive)->pci_dev->device) { @@ -196,14 +207,15 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) } else hwif->set_dma_mode = &aec6260_set_mode; - hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - - if (hwif->dma_base == 0) + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; return; + } hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; hwif->dma_lost_irq = &aec62xx_dma_lost_irq; if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { @@ -218,6 +230,10 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d) @@ -309,12 +325,12 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi return d.init_setup(dev, &d); } -static const struct pci_device_id aec62xx_pci_tbl[] = { - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 }, - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 }, - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 }, - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 }, - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 }, +static struct pci_device_id aec62xx_pci_tbl[] = { + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl); diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c index 31d4e50647d5..0b83443bf250 100644 --- a/trunk/drivers/ide/pci/alim15x3.c +++ b/trunk/drivers/ide/pci/alim15x3.c @@ -436,6 +436,26 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) } } +/** + * ali15x3_config_drive_for_dma - configure for DMA + * @drive: drive to configure + * + * Configure a drive for DMA operation. If DMA is not possible we + * drop the drive into PIO mode instead. + */ + +static int ali15x3_config_drive_for_dma(ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + /** * ali15x3_dma_setup - begin a DMA phase * @drive: target device @@ -660,6 +680,7 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) { + hwif->autodma = 0; hwif->set_pio_mode = &ali_set_pio_mode; hwif->set_dma_mode = &ali_set_dma_mode; hwif->udma_filter = &ali_udma_filter; @@ -694,10 +715,17 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; + hwif->ide_dma_check = &ali15x3_config_drive_for_dma; hwif->dma_setup = &ali15x3_dma_setup; if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_ali15x3(hwif); + + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } /** @@ -808,9 +836,9 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev } -static const struct pci_device_id alim15x3_pci_tbl[] = { - { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 }, - { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 }, +static struct pci_device_id alim15x3_pci_tbl[] = { + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); diff --git a/trunk/drivers/ide/pci/amd74xx.c b/trunk/drivers/ide/pci/amd74xx.c index 3bf3d931eea1..6ff4089a2379 100644 --- a/trunk/drivers/ide/pci/amd74xx.c +++ b/trunk/drivers/ide/pci/amd74xx.c @@ -1,5 +1,5 @@ /* - * Version 2.24 + * Version 2.23 * * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04 * IDE driver for Linux. @@ -28,6 +28,9 @@ #include "ide-timing.h" +#define DISPLAY_AMD_TIMINGS + +#define AMD_IDE_ENABLE (0x00 + amd_config->base) #define AMD_IDE_CONFIG (0x01 + amd_config->base) #define AMD_CABLE_DETECT (0x02 + amd_config->base) #define AMD_DRIVE_TIMING (0x08 + amd_config->base) @@ -84,6 +87,118 @@ static unsigned int amd_clock; static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" }; static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 }; +/* + * AMD /proc entry. + */ + +#ifdef CONFIG_IDE_PROC_FS + +#include +#include + +static u8 amd74xx_proc; + +static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 }; +static unsigned long amd_base; +static struct pci_dev *bmide_dev; +extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ + +#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg) +#define amd_print_drive(name, format, arg...)\ + p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); + +static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count) +{ + int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], + uen[4], udma[4], active8b[4], recover8b[4]; + struct pci_dev *dev = bmide_dev; + unsigned int v, u, i; + unsigned short c, w; + unsigned char t; + int len; + char *p = buffer; + + amd_print("----------AMD BusMastering IDE Configuration----------------"); + + amd_print("Driver Version: 2.13"); + amd_print("South Bridge: %s", pci_name(bmide_dev)); + + amd_print("Revision: IDE %#x", dev->revision); + amd_print("Highest DMA rate: UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]); + + amd_print("BM-DMA base: %#lx", amd_base); + amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10); + + amd_print("-----------------------Primary IDE-------Secondary IDE------"); + + pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); + amd_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); + amd_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); + + pci_read_config_byte(dev, AMD_IDE_ENABLE, &t); + amd_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); + + c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8); + amd_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); + + amd_print("Cable Type: %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w"); + + if (!amd_clock) + return p - buffer; + + amd_print("-------------------drive0----drive1----drive2----drive3-----"); + + pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v); + pci_read_config_word(dev, AMD_8BIT_TIMING, &w); + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + + for (i = 0; i < 4; i++) { + setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; + recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; + active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; + active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; + recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; + + udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)]; + uen[i] = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0; + den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); + + if (den[i] && uen[i] && udma[i] == 1) { + speed[i] = amd_clock * 3; + cycle[i] = 666666 / amd_clock; + continue; + } + + if (den[i] && uen[i] && udma[i] == 15) { + speed[i] = amd_clock * 4; + cycle[i] = 500000 / amd_clock; + continue; + } + + speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2); + cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2; + } + + amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); + + amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / amd_clock); + amd_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / amd_clock); + amd_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / amd_clock); + amd_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / amd_clock); + amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / amd_clock); + amd_print_drive("Cycle Time: ", "%8dns", cycle[i]); + amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); + + /* hoping p - buffer is less than 4K... */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} + +#endif + /* * amd_set_speed() writes timing values to the chipset registers */ @@ -149,6 +264,16 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio) amd_set_drive(drive, XFER_PIO_0 + pio); } +static int amd74xx_ide_dma_check(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + /* * The initialization callback. Here we determine the IDE chip type * and initialize its drive independent registers. @@ -238,6 +363,19 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch amd_chipset->name, pci_name(dev), dev->revision, amd_dma[fls(amd_config->udma_mask) - 1]); +/* + * Register /proc/ide/amd74xx entry + */ + +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_IDE_PROC_FS) + if (!amd74xx_proc) { + amd_base = pci_resource_start(dev, 4); + bmide_dev = dev; + ide_pci_create_host_proc("amd74xx", amd74xx_get_info); + amd74xx_proc = 1; + } +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_IDE_PROC_FS */ + return dev->irq; } @@ -248,6 +386,8 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) if (hwif->irq == 0) /* 0 is bogus but will do for now */ hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel); + hwif->autodma = 0; + hwif->set_pio_mode = &amd_set_pio_mode; hwif->set_dma_mode = &amd_set_drive; @@ -255,6 +395,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) hwif->drives[i].io_32bit = 1; hwif->drives[i].unmask = 1; hwif->drives[i].autotune = 1; + hwif->drives[i].dn = hwif->channel * 2 + i; } if (!hwif->dma_base) @@ -273,6 +414,12 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) else hwif->cbl = ATA_CBL_PATA40; } + + hwif->ide_dma_check = &amd74xx_ide_dma_check; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } #define DECLARE_AMD_DEV(name_str) \ @@ -342,34 +489,34 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_ return ide_setup_pci_device(dev, amd_chipset); } -static const struct pci_device_id amd74xx_pci_tbl[] = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7411), 2 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 3 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 4 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 5 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 6 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 7 }, +static struct pci_device_id amd74xx_pci_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 8 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, #endif - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 9 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 10 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 11 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 12 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, #endif - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 13 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 14 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 15 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 16 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 17 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 18 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 19 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 20 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 21 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 22 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); diff --git a/trunk/drivers/ide/pci/atiixp.c b/trunk/drivers/ide/pci/atiixp.c index 446900da1329..0eb97f021d39 100644 --- a/trunk/drivers/ide/pci/atiixp.c +++ b/trunk/drivers/ide/pci/atiixp.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/atiixp.c Version 0.03 Aug 3 2007 + * linux/drivers/ide/pci/atiixp.c Version 0.02 Jun 16 2007 * * Copyright (C) 2003 ATI Inc. * Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz @@ -47,6 +47,43 @@ static int save_mdma_mode[4]; static DEFINE_SPINLOCK(atiixp_lock); +/** + * atiixp_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the PIO or DMA + * mode requested by the controller. + */ + +static u8 atiixp_dma_2_pio(u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + static void atiixp_dma_host_on(ide_drive_t *drive) { struct pci_dev *dev = drive->hwif->pci_dev; @@ -132,9 +169,7 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; u32 tmp32; u16 tmp16; - - if (speed < XFER_MW_DMA_0) - return; + u8 pio; spin_lock_irqsave(&atiixp_lock, flags); @@ -156,6 +191,34 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) } spin_unlock_irqrestore(&atiixp_lock, flags); + + if (speed >= XFER_SW_DMA_0) + pio = atiixp_dma_2_pio(speed); + else + pio = speed - XFER_PIO_0; + + atiixp_set_pio_mode(drive, pio); +} + +/** + * atiixp_dma_check - set up an IDE device + * @drive: IDE drive to configure + * + * Set up the ATIIXP interface for the best available speed on this + * interface, preferring DMA to PIO. + */ + +static int atiixp_dma_check(ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; } /** @@ -175,6 +238,7 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) if (!hwif->irq) hwif->irq = ch ? 15 : 14; + hwif->autodma = 0; hwif->set_pio_mode = &atiixp_set_pio_mode; hwif->set_dma_mode = &atiixp_set_dma_mode; hwif->drives[0].autotune = 1; @@ -185,7 +249,8 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->ultra_mask = 0x3f; - hwif->mwdma_mask = 0x07; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode); @@ -196,6 +261,12 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) hwif->dma_host_on = &atiixp_dma_host_on; hwif->dma_host_off = &atiixp_dma_host_off; + hwif->ide_dma_check = &atiixp_dma_check; + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->autodma; } @@ -232,12 +303,12 @@ static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]); } -static const struct pci_device_id atiixp_pci_tbl[] = { - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 }, - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 }, - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 }, - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 }, - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 }, +static struct pci_device_id atiixp_pci_tbl[] = { + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); diff --git a/trunk/drivers/ide/pci/cmd64x.c b/trunk/drivers/ide/pci/cmd64x.c index f3d3bde8daba..d50f15e34b80 100644 --- a/trunk/drivers/ide/pci/cmd64x.c +++ b/trunk/drivers/ide/pci/cmd64x.c @@ -330,6 +330,17 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) (void) pci_write_config_byte(dev, pciU, regU); } +static int cmd64x_config_drive_for_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static int cmd648_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -536,6 +547,8 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5) hwif->ultra_mask = 0x00; + hwif->ide_dma_check = &cmd64x_config_drive_for_dma; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_cmd64x(hwif); @@ -559,6 +572,10 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; break; } + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d) @@ -637,11 +654,11 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic return d.init_setup(dev, &d); } -static const struct pci_device_id cmd64x_pci_tbl[] = { - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 }, - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 }, +static struct pci_device_id cmd64x_pci_tbl[] = { + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, { 0, }, }; MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl); diff --git a/trunk/drivers/ide/pci/cs5520.c b/trunk/drivers/ide/pci/cs5520.c index a8bf4940ca9c..fbce90048aec 100644 --- a/trunk/drivers/ide/pci/cs5520.c +++ b/trunk/drivers/ide/pci/cs5520.c @@ -105,6 +105,15 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed) cs5520_set_pio_mode(drive, 0); } +static int cs5520_config_drive_xfer_rate(ide_drive_t *drive) +{ + /* Tune the drive for PIO modes up to PIO 4 */ + ide_set_max_pio(drive); + + /* Then tell the core to use DMA operations */ + return 0; +} + /* * We provide a callback for our nonstandard DMA location */ @@ -139,6 +148,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) return; } + hwif->ide_dma_check = &cs5520_config_drive_xfer_rate; hwif->ide_dma_on = &cs5520_dma_on; /* ATAPI is harder so leave it for now */ @@ -146,6 +156,12 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) hwif->ultra_mask = 0; hwif->swdma_mask = 0; hwif->mwdma_mask = 0; + + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } #define DECLARE_CS_DEV(name_str) \ @@ -155,8 +171,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) .init_hwif = init_hwif_cs5520, \ .autodma = AUTODMA, \ .bootable = ON_BOARD, \ - .host_flags = IDE_HFLAG_ISA_PORTS | \ - IDE_HFLAG_VDMA, \ + .host_flags = IDE_HFLAG_ISA_PORTS, \ .pio_mask = ATA_PIO4, \ } @@ -218,9 +233,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic return 0; } -static const struct pci_device_id cs5520_pci_tbl[] = { - { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), 0 }, - { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), 1 }, +static struct pci_device_id cs5520_pci_tbl[] = { + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl); diff --git a/trunk/drivers/ide/pci/cs5530.c b/trunk/drivers/ide/pci/cs5530.c index 0d23b8aabe9c..e4121577cef0 100644 --- a/trunk/drivers/ide/pci/cs5530.c +++ b/trunk/drivers/ide/pci/cs5530.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cs5530.c Version 0.76 Aug 3 2007 + * linux/drivers/ide/pci/cs5530.c Version 0.74 Jul 28 2007 * * Copyright (C) 2000 Andre Hedrick * Copyright (C) 2000 Mark Lord @@ -104,6 +104,22 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) return mask; } +/** + * cs5530_config_dma - set DMA/UDMA mode + * @drive: drive to tune + * + * cs5530_config_dma() handles setting of DMA/UDMA mode + * for both the chipset and drive. + */ + +static int cs5530_config_dma(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + return 1; +} + static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) { unsigned long basereg; @@ -244,6 +260,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) { unsigned long basereg; u32 d0_timings; + hwif->autodma = 0; if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; @@ -253,13 +270,20 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) basereg = CS5530_BASEREG(hwif); d0_timings = inl(basereg + 0); - if (CS5530_BAD_PIO(d0_timings)) + if (CS5530_BAD_PIO(d0_timings)) { + /* PIO timings not initialized? */ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0); - if (CS5530_BAD_PIO(inl(basereg + 8))) + if (!hwif->drives[0].autotune) + hwif->drives[0].autotune = 1; + /* needs autotuning later */ + } + if (CS5530_BAD_PIO(inl(basereg + 8))) { + /* PIO timings not initialized? */ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8); - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; + if (!hwif->drives[1].autotune) + hwif->drives[1].autotune = 1; + /* needs autotuning later */ + } if (hwif->dma_base == 0) return; @@ -269,6 +293,11 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) hwif->mwdma_mask = 0x07; hwif->udma_filter = cs5530_udma_filter; + hwif->ide_dma_check = &cs5530_config_dma; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t cs5530_chipset __devinitdata = { @@ -286,8 +315,8 @@ static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, &cs5530_chipset); } -static const struct pci_device_id cs5530_pci_tbl[] = { - { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 }, +static struct pci_device_id cs5530_pci_tbl[] = { + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl); diff --git a/trunk/drivers/ide/pci/cs5535.c b/trunk/drivers/ide/pci/cs5535.c index e4891a16afef..257865778f92 100644 --- a/trunk/drivers/ide/pci/cs5535.c +++ b/trunk/drivers/ide/pci/cs5535.c @@ -157,6 +157,19 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio) cs5535_set_speed(drive, XFER_PIO_0 + pio); } +static int cs5535_dma_check(ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static u8 __devinit cs5535_cable_detect(struct pci_dev *dev) { u8 bit; @@ -177,6 +190,8 @@ static u8 __devinit cs5535_cable_detect(struct pci_dev *dev) */ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif) { + hwif->autodma = 0; + hwif->set_pio_mode = &cs5535_set_pio_mode; hwif->set_dma_mode = &cs5535_set_dma_mode; @@ -185,11 +200,18 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif) if (hwif->dma_base == 0) return; + hwif->ide_dma_check = &cs5535_dma_check; + hwif->atapi_dma = 1; hwif->ultra_mask = 0x1F; hwif->mwdma_mask = 0x07; hwif->cbl = cs5535_cable_detect(hwif->pci_dev); + + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[1].autodma = hwif->drives[0].autodma = hwif->autodma; } static ide_pci_device_t cs5535_chipset __devinitdata = { @@ -207,8 +229,10 @@ static int __devinit cs5535_init_one(struct pci_dev *dev, return ide_setup_pci_device(dev, &cs5535_chipset); } -static const struct pci_device_id cs5535_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_CS5535_IDE), 0 }, +static struct pci_device_id cs5535_pci_tbl[] = +{ + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_IDE, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0}, { 0, }, }; diff --git a/trunk/drivers/ide/pci/cy82c693.c b/trunk/drivers/ide/pci/cy82c693.c index c498ecfd7fcb..dc278025d318 100644 --- a/trunk/drivers/ide/pci/cy82c693.c +++ b/trunk/drivers/ide/pci/cy82c693.c @@ -428,6 +428,8 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c */ static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) { + hwif->autodma = 0; + hwif->chipset = ide_cy82c693; hwif->set_pio_mode = &cy82c693_set_pio_mode; @@ -442,6 +444,10 @@ static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) hwif->swdma_mask = 0x04; hwif->ide_dma_on = &cy82c693_ide_dma_on; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static __devinitdata ide_hwif_t *primary; @@ -463,7 +469,7 @@ static ide_pci_device_t cy82c693_chipset __devinitdata = { .init_hwif = init_hwif_cy82c693, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, }; @@ -483,8 +489,8 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev return ret; } -static const struct pci_device_id cy82c693_pci_tbl[] = { - { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 }, +static struct pci_device_id cy82c693_pci_tbl[] = { + { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); diff --git a/trunk/drivers/ide/pci/generic.c b/trunk/drivers/ide/pci/generic.c index cce6311b02df..48caa468b762 100644 --- a/trunk/drivers/ide/pci/generic.c +++ b/trunk/drivers/ide/pci/generic.c @@ -73,6 +73,11 @@ static void __devinit init_hwif_generic (ide_hwif_t *hwif) hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } #if 0 @@ -92,92 +97,77 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 1 */ .name = "NS87410", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 2 */ .name = "SAMURAI", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 3 */ .name = "HT6565", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 4 */ .name = "UM8673F", .init_hwif = init_hwif_generic, .autodma = NODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 5 */ .name = "UM8886A", .init_hwif = init_hwif_generic, .autodma = NODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 6 */ .name = "UM8886BF", .init_hwif = init_hwif_generic, .autodma = NODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 7 */ .name = "HINT_IDE", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 8 */ .name = "VIA_IDE", .init_hwif = init_hwif_generic, .autodma = NOAUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 9 */ .name = "OPTI621V", .init_hwif = init_hwif_generic, .autodma = NOAUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 10 */ .name = "VIA8237SATA", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = OFF_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 11 */ .name = "Piccolo0102", .init_hwif = init_hwif_generic, .autodma = NOAUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 12 */ .name = "Piccolo0103", .init_hwif = init_hwif_generic, .autodma = NOAUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 13 */ .name = "Piccolo0105", .init_hwif = init_hwif_generic, .autodma = NOAUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 14 */ .name = "Revolution", .init_hwif = init_hwif_generic, .autodma = AUTODMA, .bootable = OFF_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, } }; @@ -236,28 +226,25 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi return ret; } -static const struct pci_device_id generic_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 }, - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 }, - { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 3 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 4 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 5 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 6 }, - { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 7 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 8 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 9 }, +static struct pci_device_id generic_pci_tbl[] = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 10 }, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, #endif - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 11 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 12 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 13 }, - { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 14 }, - /* - * Must come last. If you add entries adjust - * this table and generic_chipsets[] appropriately. - */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 }, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, + { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, + /* Must come last. If you add entries adjust this table appropriately and the init_one code */ + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, generic_pci_tbl); diff --git a/trunk/drivers/ide/pci/hpt34x.c b/trunk/drivers/ide/pci/hpt34x.c index 44ac0e2f7a09..218852aaf22a 100644 --- a/trunk/drivers/ide/pci/hpt34x.c +++ b/trunk/drivers/ide/pci/hpt34x.c @@ -80,6 +80,19 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio) hpt34x_set_mode(drive, XFER_PIO_0 + pio); } +static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return -1; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + /* * If the BIOS does not set the IO base addaress to XX00, 343 will fail. */ @@ -127,6 +140,8 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) { u16 pcicmd = 0; + hwif->autodma = 0; + hwif->set_pio_mode = &hpt34x_set_pio_mode; hwif->set_dma_mode = &hpt34x_set_mode; @@ -139,13 +154,16 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) return; #ifdef CONFIG_HPT34X_AUTODMA - if ((pcicmd & PCI_COMMAND_MEMORY) == 0) - return; - hwif->ultra_mask = 0x07; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; #endif + + hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t hpt34x_chipset __devinitdata = { @@ -172,8 +190,8 @@ static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, d); } -static const struct pci_device_id hpt34x_pci_tbl[] = { - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), 0 }, +static struct pci_device_id hpt34x_pci_tbl[] = { + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl); diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index fcb21ddab2cc..8812a9bb032f 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.14 Oct 1, 2007 + * linux/drivers/ide/pci/hpt366.c Version 1.13 Sep 29, 2007 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -713,6 +713,19 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) IDE_CONTROL_REG); } +static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + /* * This is specific to the HPT366 UDMA chipset * by HighPoint|Triones Technologies, Inc. @@ -1291,10 +1304,10 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) if (new_mcr != old_mcr) pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); - hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - - if (hwif->dma_base == 0) + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; return; + } hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x07; @@ -1336,6 +1349,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; + if (chip_type >= HPT374) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; @@ -1345,6 +1360,10 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->dma_timeout = &hpt370_dma_timeout; } else hwif->dma_lost_irq = &hpt366_dma_lost_irq; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) @@ -1638,13 +1657,13 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic return d.init_setup(dev, &d); } -static const struct pci_device_id hpt366_pci_tbl[] = { - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), 0 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), 1 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), 2 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), 3 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), 4 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 }, +static struct pci_device_id hpt366_pci_tbl[] = { + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, { 0, }, }; MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); diff --git a/trunk/drivers/ide/pci/it8213.c b/trunk/drivers/ide/pci/it8213.c index 24a71d03744a..ecf4ce078dce 100644 --- a/trunk/drivers/ide/pci/it8213.c +++ b/trunk/drivers/ide/pci/it8213.c @@ -17,6 +17,37 @@ #include +/** + * it8213_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the DMA + * mode requested by the controller. + */ + +static u8 it8213_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + return 4; + case XFER_MW_DMA_1: + return 3; + case XFER_SW_DMA_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + default: + return 0; + } +} + /** * it8213_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -135,9 +166,6 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) } else pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - if (reg48 & u_flag) pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) @@ -146,21 +174,38 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); if (reg55 & w_flag) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ + it8213_set_pio_mode(drive, it8213_dma_2_pio(speed)); +} - it8213_set_pio_mode(drive, pio); - } +/** + * it8213_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int it8213_config_drive_for_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; } /** * init_hwif_it8213 - set up hwif structs * @hwif: interface to set up * - * We do the basic set up of the interface structure. + * We do the basic set up of the interface structure. The IT8212 + * requires several custom handlers so we override the default + * ide DMA handlers appropriately */ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) @@ -170,6 +215,8 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) hwif->set_dma_mode = &it8213_set_dma_mode; hwif->set_pio_mode = &it8213_set_pio_mode; + hwif->autodma = 0; + hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; @@ -183,8 +230,20 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); + hwif->ide_dma_check = &it8213_config_drive_for_dma; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } @@ -220,8 +279,9 @@ static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_devic return 0; } -static const struct pci_device_id it8213_pci_tbl[] = { - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 }, + +static struct pci_device_id it8213_pci_tbl[] = { + { PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c index f3391a8698ac..1b69d82478c6 100644 --- a/trunk/drivers/ide/pci/it821x.c +++ b/trunk/drivers/ide/pci/it821x.c @@ -415,6 +415,26 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed) it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0); } +/** + * it821x_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int it821x_config_drive_for_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + /** * ata66_it821x - check for 80 pin cable * @hwif: interface to check @@ -537,11 +557,10 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL); u8 conf; - if (idev == NULL) { + if(idev == NULL) { printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); - return; + goto fallback; } - ide_set_hwifdata(hwif, idev); hwif->atapi_dma = 1; @@ -590,14 +609,29 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; - if (hwif->dma_base == 0) - return; + if (!hwif->dma_base) + goto fallback; hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &it821x_config_drive_for_dma; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_it821x(hwif); + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + return; +fallback: + hwif->autodma = 0; + return; } static void __devinit it8212_disable_raid(struct pci_dev *dev) @@ -663,9 +697,9 @@ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_devic return 0; } -static const struct pci_device_id it821x_pci_tbl[] = { - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 }, - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 }, +static struct pci_device_id it821x_pci_tbl[] = { + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; diff --git a/trunk/drivers/ide/pci/jmicron.c b/trunk/drivers/ide/pci/jmicron.c index bb893ffcc987..582b4cae2b53 100644 --- a/trunk/drivers/ide/pci/jmicron.c +++ b/trunk/drivers/ide/pci/jmicron.c @@ -99,6 +99,24 @@ static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode) { } +/** + * jmicron_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * As the JMicron snoops for timings all we actually need to do is + * make sure we don't set an invalid mode. + */ + +static int jmicron_config_drive_for_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + /** * init_hwif_jmicron - set up hwif structs * @hwif: interface to set up @@ -114,15 +132,25 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif) hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; - if (hwif->dma_base == 0) - return; + if (!hwif->dma_base) + goto fallback; hwif->atapi_dma = 1; hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &jmicron_config_drive_for_dma; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_jmicron(hwif); + + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + return; +fallback: + hwif->autodma = 0; + return; } static ide_pci_device_t jmicron_chipset __devinitdata = { diff --git a/trunk/drivers/ide/pci/ns87415.c b/trunk/drivers/ide/pci/ns87415.c index a8cd50ab62fb..465c935fdf25 100644 --- a/trunk/drivers/ide/pci/ns87415.c +++ b/trunk/drivers/ide/pci/ns87415.c @@ -197,6 +197,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) u8 stat; #endif + hwif->autodma = 0; hwif->selectproc = &ns87415_selectproc; /* @@ -258,6 +259,11 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) outb(0x60, hwif->dma_status); hwif->dma_setup = &ns87415_ide_dma_setup; hwif->ide_dma_end = &ns87415_ide_dma_end; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t ns87415_chipset __devinitdata = { @@ -268,7 +274,6 @@ static ide_pci_device_t ns87415_chipset __devinitdata = { .init_hwif = init_hwif_ns87415, .autodma = AUTODMA, .bootable = ON_BOARD, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, }; static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) @@ -276,8 +281,8 @@ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_devi return ide_setup_pci_device(dev, &ns87415_chipset); } -static const struct pci_device_id ns87415_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 }, +static struct pci_device_id ns87415_pci_tbl[] = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); diff --git a/trunk/drivers/ide/pci/opti621.c b/trunk/drivers/ide/pci/opti621.c index 250662ea18ad..9fa06393469a 100644 --- a/trunk/drivers/ide/pci/opti621.c +++ b/trunk/drivers/ide/pci/opti621.c @@ -328,6 +328,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) */ static void __devinit init_hwif_opti621 (ide_hwif_t *hwif) { + hwif->autodma = 0; hwif->drives[0].drive_data = PIO_DONT_KNOW; hwif->drives[1].drive_data = PIO_DONT_KNOW; @@ -339,6 +340,11 @@ static void __devinit init_hwif_opti621 (ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t opti621_chipsets[] __devinitdata = { @@ -349,7 +355,6 @@ static ide_pci_device_t opti621_chipsets[] __devinitdata = { .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, .bootable = ON_BOARD, .pio_mask = ATA_PIO3, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, },{ /* 1 */ .name = "OPTI621X", .init_hwif = init_hwif_opti621, @@ -357,7 +362,6 @@ static ide_pci_device_t opti621_chipsets[] __devinitdata = { .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, .bootable = ON_BOARD, .pio_mask = ATA_PIO3, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, } }; @@ -366,9 +370,9 @@ static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_devi return ide_setup_pci_device(dev, &opti621_chipsets[id->driver_data]); } -static const struct pci_device_id opti621_pci_tbl[] = { - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 1 }, +static struct pci_device_id opti621_pci_tbl[] = { + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 8704b6f33312..ad0bdcb0c02b 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -223,6 +223,19 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA80; } +static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static int pdcnew_quirkproc(ide_drive_t *drive) { const char **list, *model = drive->id->model; @@ -469,6 +482,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) { + hwif->autodma = 0; + hwif->set_pio_mode = &pdcnew_set_pio_mode; hwif->set_dma_mode = &pdcnew_set_mode; @@ -487,8 +502,14 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = pdcnew_cable_detect(hwif); + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d) @@ -637,14 +658,14 @@ static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_de return d->init_setup(dev, d); } -static const struct pci_device_id pdc202new_pci_tbl[] = { - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 }, +static struct pci_device_id pdc202new_pci_tbl[] = { + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { 0, }, }; MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl); diff --git a/trunk/drivers/ide/pci/pdc202xx_old.c b/trunk/drivers/ide/pci/pdc202xx_old.c index e1d2337a9f1d..8c3e8cf36ec9 100644 --- a/trunk/drivers/ide/pci/pdc202xx_old.c +++ b/trunk/drivers/ide/pci/pdc202xx_old.c @@ -179,6 +179,19 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); } +static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static int pdc202xx_quirkproc (ide_drive_t *drive) { const char **list, *model = drive->id->model; @@ -312,6 +325,8 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) (dev->device == PCI_DEVICE_ID_PROMISE_20265)) hwif->rqsize = 256; + hwif->autodma = 0; + hwif->set_pio_mode = &pdc202xx_set_pio_mode; hwif->set_dma_mode = &pdc202xx_set_mode; @@ -332,6 +347,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->swdma_mask = 0x07; hwif->atapi_dma = 1; + hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate; hwif->dma_lost_irq = &pdc202xx_dma_lost_irq; hwif->dma_timeout = &pdc202xx_dma_timeout; @@ -343,6 +359,10 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; } hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) @@ -490,12 +510,12 @@ static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_dev return d->init_setup(dev, d); } -static const struct pci_device_id pdc202xx_pci_tbl[] = { - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 2 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 3 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 4 }, +static struct pci_device_id pdc202xx_pci_tbl[] = { + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { 0, }, }; MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c index a8dd0c0add35..38c91ba6497b 100644 --- a/trunk/drivers/ide/pci/piix.c +++ b/trunk/drivers/ide/pci/piix.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.53 Aug 9, 2007 + * linux/drivers/ide/pci/piix.c Version 0.52 Jul 14, 2007 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick @@ -105,6 +105,37 @@ static int no_piix_dma; +/** + * piix_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the DMA + * mode requested by the controller. + */ + +static u8 piix_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + return 4; + case XFER_MW_DMA_1: + return 3; + case XFER_SW_DMA_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + default: + return 0; + } +} + /** * piix_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -232,9 +263,6 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) } else pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - if (reg48 & u_flag) pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) @@ -243,14 +271,30 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); if (reg55 & w_flag) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ + piix_set_pio_mode(drive, piix_dma_2_pio(speed)); +} - piix_set_pio_mode(drive, pio); - } +/** + * piix_config_drive_xfer_rate - set up an IDE device + * @drive: IDE drive to configure + * + * Set up the PIIX interface for the best available speed on this + * interface, preferring DMA to PIO. + */ + +static int piix_config_drive_xfer_rate (ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; } /** @@ -384,6 +428,8 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) return; } + hwif->autodma = 0; + hwif->set_pio_mode = &piix_set_pio_mode; hwif->set_dma_mode = &piix_set_dma_mode; @@ -410,6 +456,13 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) if (no_piix_dma) hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; + + hwif->ide_dma_check = &piix_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->autodma; } #define DECLARE_PIIX_DEV(name_str, udma) \ @@ -512,34 +565,34 @@ static void __devinit piix_check_450nx(void) printk(KERN_WARNING "piix: A BIOS update may resolve this.\n"); } -static const struct pci_device_id piix_pci_tbl[] = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 0 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 3 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 4 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 5 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 7 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 8 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 9 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 10 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 11 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 12 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 13 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 14 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 15 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 16 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 17 }, +static struct pci_device_id piix_pci_tbl[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 18 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, #endif - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 19 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 20 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 21 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 22 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 23 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 24 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_19, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24}, { 0, }, }; MODULE_DEVICE_TABLE(pci, piix_pci_tbl); diff --git a/trunk/drivers/ide/pci/rz1000.c b/trunk/drivers/ide/pci/rz1000.c index 3f506e8d44e3..10e1ae7a4a02 100644 --- a/trunk/drivers/ide/pci/rz1000.c +++ b/trunk/drivers/ide/pci/rz1000.c @@ -61,9 +61,9 @@ static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, &rz1000_chipset); } -static const struct pci_device_id rz1000_pci_tbl[] = { - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 }, - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 }, +static struct pci_device_id rz1000_pci_tbl[] = { + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl); diff --git a/trunk/drivers/ide/pci/sc1200.c b/trunk/drivers/ide/pci/sc1200.c index 54c5c98a2e26..ee0e3f554d9a 100644 --- a/trunk/drivers/ide/pci/sc1200.c +++ b/trunk/drivers/ide/pci/sc1200.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/sc1200.c Version 0.97 Aug 3 2007 + * linux/drivers/ide/pci/sc1200.c Version 0.95 Jun 16 2007 * * Copyright (C) 2000-2002 Mark Lord * Copyright (C) 2007 Bartlomiej Zolnierkiewicz @@ -199,6 +199,19 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) } } +/* + * sc1200_config_dma() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + return 1; +} + + /* Replacement for the standard ide_dma_end action in * dma_proc. * @@ -364,22 +377,27 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) { if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; + hwif->autodma = 0; hwif->set_pio_mode = &sc1200_set_pio_mode; hwif->set_dma_mode = &sc1200_set_dma_mode; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - if (hwif->dma_base == 0) return; hwif->udma_filter = sc1200_udma_filter; + hwif->ide_dma_check = &sc1200_config_dma; hwif->ide_dma_end = &sc1200_ide_dma_end; + if (!noautodma) + hwif->autodma = 1; + hwif->atapi_dma = 1; hwif->ultra_mask = 0x07; hwif->mwdma_mask = 0x07; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t sc1200_chipset __devinitdata = { @@ -396,8 +414,8 @@ static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, &sc1200_chipset); } -static const struct pci_device_id sc1200_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0}, +static struct pci_device_id sc1200_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); diff --git a/trunk/drivers/ide/pci/scc_pata.c b/trunk/drivers/ide/pci/scc_pata.c index bd4c1d3070e4..67f06dd11b34 100644 --- a/trunk/drivers/ide/pci/scc_pata.c +++ b/trunk/drivers/ide/pci/scc_pata.c @@ -283,6 +283,28 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) out_be32((void __iomem *)udenvt_port, reg); } +/** + * scc_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. + * If the drive isn't suitable for DMA or we hit other problems + * then we will drop down to PIO and set up PIO appropriately. + * (return -1) + */ + +static int scc_config_drive_for_dma(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + /** * scc_ide_dma_setup - begin a DMA phase * @drive: target device @@ -680,6 +702,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) hwif->ide_dma_end = scc_ide_dma_end; hwif->set_pio_mode = scc_set_pio_mode; hwif->set_dma_mode = scc_set_dma_mode; + hwif->ide_dma_check = scc_config_drive_for_dma; hwif->ide_dma_test_irq = scc_dma_test_irq; hwif->udma_filter = scc_udma_filter; @@ -697,6 +720,12 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) /* we support 80c cable only. */ hwif->cbl = ATA_CBL_PATA80; + + hwif->autodma = 0; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } #define DECLARE_SCC_DEV(name_str) \ @@ -764,8 +793,8 @@ static void __devexit scc_remove(struct pci_dev *dev) memset(ports, 0, sizeof(*ports)); } -static const struct pci_device_id scc_pci_tbl[] = { - { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 }, +static struct pci_device_id scc_pci_tbl[] = { + { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, scc_pci_tbl); diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index d3ffc52e22af..49ec0ac64a4b 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -97,7 +97,6 @@ static u8 svwks_udma_filter(ide_drive_t *drive) mode = 2; switch(mode) { - case 3: mask = 0x3f; break; case 2: mask = 0x1f; break; case 1: mask = 0x07; break; default: mask = 0x00; break; @@ -196,6 +195,19 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, ultra_enable); } +static int svwks_config_drive_xfer_rate (ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name) { unsigned int reg; @@ -374,16 +386,23 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) hwif->mwdma_mask = 0x07; + hwif->autodma = 0; + hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; if (!hwif->dma_base) return; + hwif->ide_dma_check = &svwks_config_drive_xfer_rate; if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_svwks(hwif); } + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->drives[1].autodma = 1; } static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) @@ -471,12 +490,12 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device return d->init_setup(dev, d); } -static const struct pci_device_id svwks_pci_tbl[] = { - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 }, +static struct pci_device_id svwks_pci_tbl[] = { + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { 0, }, }; MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c index 9a9474f534e5..85ffaaa39b1b 100644 --- a/trunk/drivers/ide/pci/sgiioc4.c +++ b/trunk/drivers/ide/pci/sgiioc4.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -296,6 +295,20 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed) { } +static int sgiioc4_ide_dma_check(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + /* + * ->set_pio_mode is not implemented currently + * so this is just for the completness + */ + ide_set_max_pio(drive); + + return -1; +} + /* returns 1 if dma irq issued, 0 otherwise */ static int sgiioc4_ide_dma_test_irq(ide_drive_t * drive) @@ -524,7 +537,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) } } - sg = sg_next(sg); + sg++; i--; } @@ -598,6 +611,7 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->dma_setup = &sgiioc4_ide_dma_setup; hwif->dma_start = &sgiioc4_ide_dma_start; hwif->ide_dma_end = &sgiioc4_ide_dma_end; + hwif->ide_dma_check = &sgiioc4_ide_dma_check; hwif->ide_dma_on = &sgiioc4_ide_dma_on; hwif->dma_off_quietly = &sgiioc4_dma_off_quietly; hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; @@ -674,7 +688,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) + hwif->autodma = 0; + + if (dma_base && ide_dma_sgiioc4(hwif, dma_base) == 0) { + hwif->autodma = 1; + hwif->drives[1].autodma = hwif->drives[0].autodma = 1; + } else printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n", hwif->name, DRV_NAME); diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c index 85d0afd00e66..ce7784996d12 100644 --- a/trunk/drivers/ide/pci/siimage.c +++ b/trunk/drivers/ide/pci/siimage.c @@ -311,6 +311,27 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) } } +/** + * siimage_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int siimage_config_drive_for_dma (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + /* returns 1 if dma irq issued, 0 otherwise */ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) { @@ -873,6 +894,8 @@ static u8 __devinit ata66_siimage(ide_hwif_t *hwif) static void __devinit init_hwif_siimage(ide_hwif_t *hwif) { + hwif->autodma = 0; + hwif->resetproc = &siimage_reset; hwif->set_pio_mode = &sil_set_pio_mode; hwif->set_dma_mode = &sil_set_dma_mode; @@ -902,6 +925,8 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) if (!is_sata(hwif)) hwif->atapi_dma = 1; + hwif->ide_dma_check = &siimage_config_drive_for_dma; + if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_siimage(hwif); @@ -910,6 +935,15 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) } else { hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq; } + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } #define DECLARE_SII_DEV(name_str) \ @@ -944,11 +978,11 @@ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_devi return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]); } -static const struct pci_device_id siimage_pci_tbl[] = { - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 }, +static struct pci_device_id siimage_pci_tbl[] = { + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 }, - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 }, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, #endif { 0, }, }; diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index 5a54e2e20b3c..b375ee53d66d 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/sis5513.c Version 0.31 Aug 9, 2007 + * linux/drivers/ide/pci/sis5513.c Version 0.27 Jul 14, 2007 * * Copyright (C) 1999-2000 Andre Hedrick * Copyright (C) 2002 Lionel Bouton , Maintainer @@ -65,6 +65,8 @@ #include "ide-timing.h" +#define DISPLAY_SIS_TIMINGS + /* registers layout and init values are chipset family dependant */ #define ATA_16 0x01 @@ -191,124 +193,362 @@ static char* chipset_capability[] = { "ATA 133 (1st gen)", "ATA 133 (2nd gen)" }; -/* - * Configuration functions - */ +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#include +#include -static u8 sis_ata133_get_base(ide_drive_t *drive) -{ - struct pci_dev *dev = drive->hwif->pci_dev; - u32 reg54 = 0; +static u8 sis_proc = 0; - pci_read_config_dword(dev, 0x54, ®54); +static struct pci_dev *bmide_dev; - return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; -} +static char* cable_type[] = { + "80 pins", + "40 pins" +}; + +static char* recovery_time[] ={ + "12 PCICLK", "1 PCICLK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLCK", + "6 PCICLK", "7 PCICLCK", + "8 PCICLK", "9 PCICLCK", + "10 PCICLK", "11 PCICLK", + "13 PCICLK", "14 PCICLK", + "15 PCICLK", "15 PCICLK" +}; + +static char* active_time[] = { + "8 PCICLK", "1 PCICLCK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLK", + "6 PCICLK", "12 PCICLK" +}; -static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) +static char* cycle_time[] = { + "Reserved", "2 CLK", + "3 CLK", "4 CLK", + "5 CLK", "6 CLK", + "7 CLK", "8 CLK", + "9 CLK", "10 CLK", + "11 CLK", "12 CLK", + "13 CLK", "14 CLK", + "15 CLK", "16 CLK" +}; + +/* Generic add master or slave info function */ +static char* get_drives_info (char *buffer, u8 pos) { - struct pci_dev *dev = drive->hwif->pci_dev; - u16 t1 = 0; - u8 drive_pci = 0x40 + drive->dn * 2; + u8 reg00, reg01, reg10, reg11; /* timing registers */ + u32 regdw0, regdw1; + char* p = buffer; + +/* Postwrite/Prefetch */ + if (chipset_family < ATA_133) { + pci_read_config_byte(bmide_dev, 0x4b, ®00); + p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", + pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); + pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); + pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); + pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); + pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); + } else { + u32 reg54h; + u8 drive_pci = 0x40; + pci_read_config_dword(bmide_dev, 0x54, ®54h); + if (reg54h & 0x40000000) { + // Configuration space remapped to 0x70 + drive_pci = 0x70; + } + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos, ®dw0); + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos+8, ®dw1); - const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 }; - const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 }; + p += sprintf(p, "Drive %d:\n", pos); + } - pci_read_config_word(dev, drive_pci, &t1); - /* clear active/recovery timings */ - t1 &= ~0x070f; - if (mode >= XFER_MW_DMA_0) { - if (chipset_family > ATA_16) - t1 &= ~0x8000; /* disable UDMA */ - t1 |= mwdma_timings[mode - XFER_MW_DMA_0]; - } else - t1 |= pio_timings[mode - XFER_PIO_0]; +/* UDMA */ + if (chipset_family >= ATA_133) { + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (regdw0 & 0x04) ? "Enabled" : "Disabled", + (regdw1 & 0x04) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(regdw0 & 0xF0) >> 4], + cycle_time[(regdw1 & 0xF0) >> 4]); + } else if (chipset_family >= ATA_33) { + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg01 & 0x80) ? "Enabled" : "Disabled", + (reg11 & 0x80) ? "Enabled" : "Disabled"); + + p += sprintf(p, " UDMA Cycle Time "); + switch(chipset_family) { + case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, " \t UDMA Cycle Time "); + switch(chipset_family) { + case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, "\n"); + } - pci_write_config_word(dev, drive_pci, t1); -} -static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = drive->hwif->pci_dev; - u8 t1, drive_pci = 0x40 + drive->dn * 2; + if (chipset_family < ATA_133) { /* else case TODO */ - /* timing bits: 7:4 active 3:0 recovery */ - const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; - const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 }; +/* Data Active */ + p += sprintf(p, " Data Active Time "); + switch(chipset_family) { + case ATA_16: /* confirmed */ + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, " \t Data Active Time "); + switch(chipset_family) { + case ATA_16: + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, "\n"); - if (mode >= XFER_MW_DMA_0) { - u8 t2 = 0; +/* Data Recovery */ + /* warning: may need (reg&0x07) for pre ATA66 chips */ + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); + } - pci_read_config_byte(dev, drive_pci, &t2); - t2 &= ~0x80; /* disable UDMA */ - pci_write_config_byte(dev, drive_pci, t2); + return p; +} - t1 = mwdma_timings[mode - XFER_MW_DMA_0]; - } else - t1 = pio_timings[mode - XFER_PIO_0]; +static char* get_masters_info(char* buffer) +{ + return get_drives_info(buffer, 0); +} - pci_write_config_byte(dev, drive_pci + 1, t1); +static char* get_slaves_info(char* buffer) +{ + return get_drives_info(buffer, 1); } -static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) +/* Main get_info, called on /proc/ide/sis reads */ +static int sis_get_info (char *buffer, char **addr, off_t offset, int count) { - struct pci_dev *dev = drive->hwif->pci_dev; - u32 t1 = 0; - u8 drive_pci = sis_ata133_get_base(drive), clk, idx; + char *p = buffer; + int len; + u8 reg; + u16 reg2, reg3; + + p += sprintf(p, "\nSiS 5513 "); + switch(chipset_family) { + case ATA_16: p += sprintf(p, "DMA 16"); break; + case ATA_33: p += sprintf(p, "Ultra 33"); break; + case ATA_66: p += sprintf(p, "Ultra 66"); break; + case ATA_100a: + case ATA_100: p += sprintf(p, "Ultra 100"); break; + case ATA_133a: + case ATA_133: p += sprintf(p, "Ultra 133"); break; + default: p+= sprintf(p, "Unknown???"); break; + } + p += sprintf(p, " chipset\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + +/* Status */ + pci_read_config_byte(bmide_dev, 0x4a, ®); + if (chipset_family == ATA_133) { + pci_read_config_word(bmide_dev, 0x50, ®2); + pci_read_config_word(bmide_dev, 0x52, ®3); + } + p += sprintf(p, "Channel Status: "); + if (chipset_family < ATA_66) { + p += sprintf(p, "%s \t \t \t \t %s\n", + (reg & 0x04) ? "On" : "Off", + (reg & 0x02) ? "On" : "Off"); + } else if (chipset_family < ATA_133) { + p += sprintf(p, "%s \t \t \t \t %s \n", + (reg & 0x02) ? "On" : "Off", + (reg & 0x04) ? "On" : "Off"); + } else { /* ATA_133 */ + p += sprintf(p, "%s \t \t \t \t %s \n", + (reg2 & 0x02) ? "On" : "Off", + (reg3 & 0x02) ? "On" : "Off"); + } - pci_read_config_dword(dev, drive_pci, &t1); +/* Operation Mode */ + pci_read_config_byte(bmide_dev, 0x09, ®); + p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", + (reg & 0x01) ? "Native" : "Compatible", + (reg & 0x04) ? "Native" : "Compatible"); - t1 &= 0xc0c00fff; - clk = (t1 & 0x08) ? ATA_133 : ATA_100; - if (mode >= XFER_MW_DMA_0) { - t1 &= ~0x04; /* disable UDMA */ - idx = mode - XFER_MW_DMA_0 + 5; +/* 80-pin cable ? */ + if (chipset_family >= ATA_133) { + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg2 & 0x01) ? cable_type[1] : cable_type[0], + (reg3 & 0x01) ? cable_type[1] : cable_type[0]); + } else if (chipset_family > ATA_33) { + pci_read_config_byte(bmide_dev, 0x48, ®); + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg & 0x10) ? cable_type[1] : cable_type[0], + (reg & 0x20) ? cable_type[1] : cable_type[0]); } - idx = mode - XFER_PIO_0; - t1 |= ini_time_value[clk][idx] << 12; - t1 |= act_time_value[clk][idx] << 16; - t1 |= rco_time_value[clk][idx] << 24; - pci_write_config_dword(dev, drive_pci, t1); -} +/* Prefetch Count */ + if (chipset_family < ATA_133) { + pci_read_config_word(bmide_dev, 0x4c, ®2); + pci_read_config_word(bmide_dev, 0x4e, ®3); + p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", + reg2, reg3); + } -static void sis_program_timings(ide_drive_t *drive, const u8 mode) -{ - if (chipset_family < ATA_100) /* ATA_16/33/66/100a */ - sis_ata16_program_timings(drive, mode); - else if (chipset_family < ATA_133) /* ATA_100/133a */ - sis_ata100_program_timings(drive, mode); - else /* ATA_133 */ - sis_ata133_program_timings(drive, mode); + p = get_masters_info(p); + p = get_slaves_info(p); + + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +/* + * Configuration functions + */ +/* Enables per-drive prefetch and postwrite */ static void config_drive_art_rwp (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + u8 reg4bh = 0; - u8 rw_prefetch = 0; + u8 rw_prefetch = (0x11 << drive->dn); + if (drive->media != ide_disk) + return; pci_read_config_byte(dev, 0x4b, ®4bh); - if (drive->media == ide_disk) - rw_prefetch = 0x11 << drive->dn; - - if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) + if ((reg4bh & rw_prefetch) != rw_prefetch) pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); } +/* Set per-drive active and recovery time */ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + u8 drive_pci, test1, test2; + config_drive_art_rwp(drive); - sis_program_timings(drive, XFER_PIO_0 + pio); + + /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */ + drive_pci = 0x40; + /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */ + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + drive_pci += ((drive->dn)*0x4); + } else { + drive_pci += ((drive->dn)*0x2); + } + + /* register layout changed with newer ATA100 chips */ + if (chipset_family < ATA_100) { + pci_read_config_byte(dev, drive_pci, &test1); + pci_read_config_byte(dev, drive_pci+1, &test2); + + /* Clear active and recovery timings */ + test1 &= ~0x0F; + test2 &= ~0x07; + + switch(pio) { + case 4: test1 |= 0x01; test2 |= 0x03; break; + case 3: test1 |= 0x03; test2 |= 0x03; break; + case 2: test1 |= 0x04; test2 |= 0x04; break; + case 1: test1 |= 0x07; test2 |= 0x06; break; + case 0: /* PIO0: register setting == X000 */ + default: break; + } + pci_write_config_byte(dev, drive_pci, test1); + pci_write_config_byte(dev, drive_pci+1, test2); + } else if (chipset_family < ATA_133) { + switch(pio) { /* active recovery + v v */ + case 4: test1 = 0x30|0x01; break; + case 3: test1 = 0x30|0x03; break; + case 2: test1 = 0x40|0x04; break; + case 1: test1 = 0x60|0x07; break; + case 0: test1 = 0x00; break; + default: break; + } + pci_write_config_byte(dev, drive_pci, test1); + } else { /* ATA_133 */ + u32 test3; + pci_read_config_dword(dev, drive_pci, &test3); + test3 &= 0xc0c00fff; + if (test3 & 0x08) { + test3 |= ini_time_value[ATA_133][pio] << 12; + test3 |= act_time_value[ATA_133][pio] << 16; + test3 |= rco_time_value[ATA_133][pio] << 24; + } else { + test3 |= ini_time_value[ATA_100][pio] << 12; + test3 |= act_time_value[ATA_100][pio] << 16; + test3 |= rco_time_value[ATA_100][pio] << 24; + } + pci_write_config_dword(dev, drive_pci, test3); + } } static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + u32 regdw; + u8 drive_pci, reg; + + /* See sis_set_pio_mode() for drive PCI config registers */ + drive_pci = 0x40; + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + drive_pci += ((drive->dn)*0x4); + pci_read_config_dword(dev, (unsigned long)drive_pci, ®dw); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if (speed < XFER_UDMA_0) { + regdw &= 0xfffffffb; + pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); + } + + } else { + drive_pci += ((drive->dn)*0x2); + pci_read_config_byte(dev, drive_pci+1, ®); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { + reg &= 0x7F; + pci_write_config_byte(dev, drive_pci+1, reg); + } + } /* Config chip for mode */ switch(speed) { @@ -320,10 +560,6 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) case XFER_UDMA_1: case XFER_UDMA_0: if (chipset_family >= ATA_133) { - u32 regdw = 0; - u8 drive_pci = sis_ata133_get_base(drive); - - pci_read_config_dword(dev, drive_pci, ®dw); regdw |= 0x04; regdw &= 0xfffff00f; /* check if ATA133 enable */ @@ -336,9 +572,6 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) } pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); } else { - u8 drive_pci = 0x40 + drive->dn * 2, reg = 0; - - pci_read_config_byte(dev, drive_pci+1, ®); /* Force the UDMA bit on if we want to use UDMA */ reg |= 0x80; /* clean reg cycle time bits */ @@ -353,7 +586,9 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: - sis_program_timings(drive, speed); + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: break; default: BUG(); @@ -361,12 +596,32 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) } } +static int sis5513_config_xfer_rate(ide_drive_t *drive) +{ + /* + * TODO: always set PIO mode and remove this + */ + ide_set_max_pio(drive); + + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) { struct pci_dev *dev = drive->hwif->pci_dev; - u32 regdw = 0; - u8 drive_pci = sis_ata133_get_base(drive); + int drive_pci; + u32 reg54 = 0, regdw = 0; + pci_read_config_dword(dev, 0x54, ®54); + drive_pci = ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; pci_read_config_dword(dev, drive_pci, ®dw); /* if ATA133 disable, we should not set speed above UDMA5 */ @@ -512,6 +767,14 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c } break; } + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) + if (!sis_proc) { + sis_proc = 1; + bmide_dev = dev; + ide_pci_create_host_proc("sis", sis_get_info); + } +#endif } return 0; @@ -564,6 +827,8 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) { u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + hwif->autodma = 0; + if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; @@ -573,19 +838,32 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) if (chipset_family >= ATA_133) hwif->udma_filter = sis5513_ata133_udma_filter; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (hwif->dma_base == 0) + if (!(hwif->dma_base)) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; return; + } hwif->atapi_dma = 1; hwif->ultra_mask = udma_rates[chipset_family]; hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!chipset_family) + return; if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_sis5513(hwif); + + if (chipset_family > ATA_16) { + hwif->ide_dma_check = &sis5513_config_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + } + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + return; } static ide_pci_device_t sis5513_chipset __devinitdata = { @@ -603,10 +881,10 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi return ide_setup_pci_device(dev, &sis5513_chipset); } -static const struct pci_device_id sis5513_pci_tbl[] = { - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 }, - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 }, - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 }, +static struct pci_device_id sis5513_pci_tbl[] = { + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); diff --git a/trunk/drivers/ide/pci/sl82c105.c b/trunk/drivers/ide/pci/sl82c105.c index 771efb8884c8..2ef26e3f7be4 100644 --- a/trunk/drivers/ide/pci/sl82c105.c +++ b/trunk/drivers/ide/pci/sl82c105.c @@ -144,6 +144,19 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed) } } +/* + * Check to see if the drive and chipset are capable of DMA mode. + */ +static int sl82c105_ide_dma_check(ide_drive_t *drive) +{ + DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name)); + + if (ide_tune_dma(drive)) + return 0; + + return -1; +} + /* * The SL82C105 holds off all IDE interrupts while in DMA mode until * all DMA activity is completed. Sometimes this causes problems (eg, @@ -391,12 +404,17 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &sl82c105_ide_dma_check; hwif->ide_dma_on = &sl82c105_ide_dma_on; hwif->dma_off_quietly = &sl82c105_dma_off_quietly; hwif->dma_lost_irq = &sl82c105_dma_lost_irq; hwif->dma_start = &sl82c105_dma_start; hwif->dma_timeout = &sl82c105_dma_timeout; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; } @@ -416,8 +434,8 @@ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_dev return ide_setup_pci_device(dev, &sl82c105_chipset); } -static const struct pci_device_id sl82c105_pci_tbl[] = { - { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 }, +static struct pci_device_id sl82c105_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); diff --git a/trunk/drivers/ide/pci/slc90e66.c b/trunk/drivers/ide/pci/slc90e66.c index fa8df6d43832..ebac87f7200a 100644 --- a/trunk/drivers/ide/pci/slc90e66.c +++ b/trunk/drivers/ide/pci/slc90e66.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.18 Aug 9, 2007 + * linux/drivers/ide/pci/slc90e66.c Version 0.16 Jul 14, 2007 * * Copyright (C) 2000-2002 Andre Hedrick * Copyright (C) 2006-2007 MontaVista Software, Inc. @@ -21,6 +21,27 @@ #include +static u8 slc90e66_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + return 4; + case XFER_MW_DMA_1: + return 3; + case XFER_SW_DMA_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + default: + return 0; + } +} + static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); @@ -111,21 +132,26 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_word(dev, 0x4a, reg4a|u_speed); } } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - if (reg48 & u_flag) pci_write_config_word(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + } - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ + slc90e66_set_pio_mode(drive, slc90e66_dma_2_pio(speed)); +} - slc90e66_set_pio_mode(drive, pio); - } +static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) +{ + drive->init_speed = 0; + + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; } static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) @@ -133,6 +159,8 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) u8 reg47 = 0; u8 mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */ + hwif->autodma = 0; + if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; @@ -141,11 +169,11 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) pci_read_config_byte(hwif->pci_dev, 0x47, ®47); - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (hwif->dma_base == 0) + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; return; + } hwif->atapi_dma = 1; hwif->ultra_mask = 0x1f; @@ -155,6 +183,13 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) if (hwif->cbl != ATA_CBL_PATA40_SHORT) /* bit[0(1)]: 0:80, 1:40 */ hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + + hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t slc90e66_chipset __devinitdata = { @@ -171,8 +206,8 @@ static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_dev return ide_setup_pci_device(dev, &slc90e66_chipset); } -static const struct pci_device_id slc90e66_pci_tbl[] = { - { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 }, +static struct pci_device_id slc90e66_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl); diff --git a/trunk/drivers/ide/pci/tc86c001.c b/trunk/drivers/ide/pci/tc86c001.c index de62db576adc..840415d68d38 100644 --- a/trunk/drivers/ide/pci/tc86c001.c +++ b/trunk/drivers/ide/pci/tc86c001.c @@ -162,6 +162,17 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) return 0; } +static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + ide_set_max_pio(drive); + + return -1; +} + static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) { unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); @@ -202,6 +213,7 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) hwif->ultra_mask = 0x1f; hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate; hwif->dma_start = &tc86c001_dma_start; if (hwif->cbl != ATA_CBL_PATA40_SHORT) { @@ -212,6 +224,10 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) scr1 = hwif->INW(sc_base + 0x00); hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, @@ -240,8 +256,9 @@ static int __devinit tc86c001_init_one(struct pci_dev *dev, return ide_setup_pci_device(dev, &tc86c001_chipset); } -static const struct pci_device_id tc86c001_pci_tbl[] = { - { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 }, +static struct pci_device_id tc86c001_pci_tbl[] = { + { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, } }; MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); diff --git a/trunk/drivers/ide/pci/triflex.c b/trunk/drivers/ide/pci/triflex.c index 4075c907f05c..54e411d4e56c 100644 --- a/trunk/drivers/ide/pci/triflex.c +++ b/trunk/drivers/ide/pci/triflex.c @@ -96,6 +96,16 @@ static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio) triflex_set_mode(drive, XFER_PIO_0 + pio); } +static int triflex_config_drive_xfer_rate(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + static void __devinit init_hwif_triflex(ide_hwif_t *hwif) { hwif->set_pio_mode = &triflex_set_pio_mode; @@ -107,6 +117,12 @@ static void __devinit init_hwif_triflex(ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; + hwif->ide_dma_check = &triflex_config_drive_xfer_rate; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t triflex_device __devinitdata = { @@ -124,8 +140,9 @@ static int __devinit triflex_init_one(struct pci_dev *dev, return ide_setup_pci_device(dev, &triflex_device); } -static const struct pci_device_id triflex_pci_tbl[] = { - { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 }, +static struct pci_device_id triflex_pci_tbl[] = { + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); diff --git a/trunk/drivers/ide/pci/trm290.c b/trunk/drivers/ide/pci/trm290.c index e3d943ada7b0..dc4f4e298e00 100644 --- a/trunk/drivers/ide/pci/trm290.c +++ b/trunk/drivers/ide/pci/trm290.c @@ -292,6 +292,9 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; hwif->selectproc = &trm290_selectproc; + hwif->autodma = 0; /* play it safe for now */ + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; #if 1 { /* @@ -326,9 +329,6 @@ static ide_pci_device_t trm290_chipset __devinitdata = { .init_hwif = init_hwif_trm290, .autodma = NOAUTODMA, .bootable = ON_BOARD, -#if 0 /* play it safe for now */ - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, -#endif }; static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id) @@ -336,8 +336,8 @@ static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_devic return ide_setup_pci_device(dev, &trm290_chipset); } -static const struct pci_device_id trm290_pci_tbl[] = { - { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 }, +static struct pci_device_id trm290_pci_tbl[] = { + { PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, trm290_pci_tbl); diff --git a/trunk/drivers/ide/pci/via82cxxx.c b/trunk/drivers/ide/pci/via82cxxx.c index b25fb65b240e..479e49661032 100644 --- a/trunk/drivers/ide/pci/via82cxxx.c +++ b/trunk/drivers/ide/pci/via82cxxx.c @@ -197,6 +197,24 @@ static void via_set_pio_mode(ide_drive_t *drive, const u8 pio) via_set_drive(drive, XFER_PIO_0 + pio); } +/** + * via82cxxx_ide_dma_check - set up for DMA if possible + * @drive: IDE drive to set up + * + * Set up the drive for the highest supported speed considering the + * driver, controller and cable + */ + +static int via82cxxx_ide_dma_check (ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + ide_set_max_pio(drive); + + return -1; +} + static struct via_isa_bridge *via_config_find(struct pci_dev **isa) { struct via_isa_bridge *via_config; @@ -425,6 +443,8 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); int i; + hwif->autodma = 0; + hwif->set_pio_mode = &via_set_pio_mode; hwif->set_dma_mode = &via_set_drive; @@ -438,6 +458,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) hwif->drives[i].io_32bit = 1; hwif->drives[i].unmask = (vdev->via_config->flags & VIA_NO_UNMASK) ? 0 : 1; hwif->drives[i].autotune = 1; + hwif->drives[i].dn = hwif->channel * 2 + i; } if (!hwif->dma_base) @@ -451,6 +472,12 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = via82cxxx_cable_detect(hwif); + + hwif->ide_dma_check = &via82cxxx_ide_dma_check; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { @@ -495,11 +522,11 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]); } -static const struct pci_device_id via_pci_tbl[] = { - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, +static struct pci_device_id via_pci_tbl[] = { + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, via_pci_tbl); diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c index 1d25a3433008..7d8873839e21 100644 --- a/trunk/drivers/ide/ppc/pmac.c +++ b/trunk/drivers/ide/ppc/pmac.c @@ -1421,12 +1421,17 @@ static struct macio_driver pmac_ide_macio_driver = .resume = pmac_ide_macio_resume, }; -static const struct pci_device_id pmac_ide_pci_match[] = { - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, +static struct pci_device_id pmac_ide_pci_match[] = { + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {}, }; @@ -1534,7 +1539,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) cur_len -= tc; ++table; } - sg = sg_next(sg); + sg++; i--; } @@ -1573,6 +1578,19 @@ pmac_ide_destroy_dmatable (ide_drive_t *drive) } } +/* + * Check what is the best DMA timing setting for the drive and + * call appropriate functions to apply it. + */ +static int +pmac_ide_dma_check(ide_drive_t *drive) +{ + if (ide_tune_dma(drive)) + return 0; + + return -1; +} + /* * Prepare a DMA transfer. We build the DMA table, adjust the timings for * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion @@ -1770,6 +1788,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->dma_off_quietly = &ide_dma_off_quietly; hwif->ide_dma_on = &__ide_dma_on; + hwif->ide_dma_check = &pmac_ide_dma_check; hwif->dma_setup = &pmac_ide_dma_setup; hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; hwif->dma_start = &pmac_ide_dma_start; @@ -1804,6 +1823,9 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->swdma_mask = 0x00; break; } + + hwif->autodma = 1; + hwif->drives[1].autodma = hwif->drives[0].autodma = hwif->autodma; } #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index 3d101f73f910..1129f8c30840 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -145,13 +145,27 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) } #ifdef CONFIG_BLK_DEV_IDEDMA_PCI + +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED +/* + * Long lost data from 2.0.34 that is now in 2.0.39 + * + * This was used in ./drivers/block/triton.c to do DMA Base address setup + * when PnP failed. Oh the things we forget. I believe this was part + * of SFF-8038i that has been withdrawn from public access... :-(( + */ +#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */ +#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ +#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + /** * ide_get_or_set_dma_base - setup BMIBA * @hwif: Interface * - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. - * Where a device has a partner that is already in DMA mode we check - * and enforce IDE simplex rules. + * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: + * If need be we set up the DMA base. Where a device has a partner that + * is already in DMA mode we check and enforce IDE simplex rules. */ static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif) @@ -159,6 +173,12 @@ static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif) unsigned long dma_base = 0; struct pci_dev *dev = hwif->pci_dev; +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED + int second_chance = 0; + +second_chance_to_dma: +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + if (hwif->mmio) return hwif->dma_base; @@ -172,6 +192,26 @@ static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif) } } +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED + /* FIXME - should use pci_assign_resource surely */ + if ((!dma_base) && (!second_chance)) { + unsigned long set_bmiba = 0; + second_chance++; + switch(dev->vendor) { + case PCI_VENDOR_ID_AL: + set_bmiba = DEFAULT_BMALIBA; break; + case PCI_VENDOR_ID_VIA: + set_bmiba = DEFAULT_BMCRBA; break; + case PCI_VENDOR_ID_INTEL: + set_bmiba = DEFAULT_BMIBA; break; + default: + return dma_base; + } + pci_write_config_dword(dev, 0x20, set_bmiba|1); + goto second_chance_to_dma; + } +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + if (dma_base) { u8 simplex_stat = 0; dma_base += hwif->channel ? 8 : 0; @@ -438,6 +478,8 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi * Set up BM-DMA capability * (PnP BIOS should have done this) */ + /* default DMA off if we had to configure it here */ + hwif->autodma = 0; pci_set_master(dev); if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { printk(KERN_ERR "%s: %s error updating PCICMD\n", diff --git a/trunk/drivers/ieee1394/csr1212.c b/trunk/drivers/ieee1394/csr1212.c index e8122def164d..d08166bda1c5 100644 --- a/trunk/drivers/ieee1394/csr1212.c +++ b/trunk/drivers/ieee1394/csr1212.c @@ -218,10 +218,12 @@ static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key) if (!kv) return NULL; - atomic_set(&kv->refcnt, 1); kv->key.type = type; kv->key.id = key; + kv->associate = NULL; + kv->refcnt = 1; + kv->next = NULL; kv->prev = NULL; kv->offset = 0; @@ -324,13 +326,12 @@ void csr1212_associate_keyval(struct csr1212_keyval *kv, if (kv->associate) csr1212_release_keyval(kv->associate); - csr1212_keep_keyval(associate); + associate->refcnt++; kv->associate = associate; } -static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv, - bool keep_keyval) +int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) { struct csr1212_dentry *dentry; @@ -340,10 +341,10 @@ static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, if (!dentry) return -ENOMEM; - if (keep_keyval) - csr1212_keep_keyval(kv); dentry->kv = kv; + kv->refcnt++; + dentry->next = NULL; dentry->prev = dir->value.directory.dentries_tail; @@ -357,12 +358,6 @@ static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, return CSR1212_SUCCESS; } -int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv) -{ - return __csr1212_attach_keyval_to_directory(dir, kv, true); -} - #define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ (&((kv)->value.leaf.data[1])) @@ -488,18 +483,15 @@ void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, /* This function is used to free the memory taken by a keyval. If the given * keyval is a directory type, then any keyvals contained in that directory - * will be destroyed as well if noone holds a reference on them. By means of + * will be destroyed as well if their respective refcnts are 0. By means of * list manipulation, this routine will descend a directory structure in a * non-recursive manner. */ -void csr1212_release_keyval(struct csr1212_keyval *kv) +static void csr1212_destroy_keyval(struct csr1212_keyval *kv) { struct csr1212_keyval *k, *a; struct csr1212_dentry dentry; struct csr1212_dentry *head, *tail; - if (!atomic_dec_and_test(&kv->refcnt)) - return; - dentry.kv = kv; dentry.next = NULL; dentry.prev = NULL; @@ -511,8 +503,9 @@ void csr1212_release_keyval(struct csr1212_keyval *kv) k = head->kv; while (k) { - /* must not dec_and_test kv->refcnt again */ - if (k != kv && !atomic_dec_and_test(&k->refcnt)) + k->refcnt--; + + if (k->refcnt > 0) break; a = k->associate; @@ -543,6 +536,14 @@ void csr1212_release_keyval(struct csr1212_keyval *kv) } } +void csr1212_release_keyval(struct csr1212_keyval *kv) +{ + if (kv->refcnt > 1) + kv->refcnt--; + else + csr1212_destroy_keyval(kv); +} + void csr1212_destroy_csr(struct csr1212_csr *csr) { struct csr1212_csr_rom_cache *c, *oc; @@ -1125,7 +1126,6 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) int ret = CSR1212_SUCCESS; struct csr1212_keyval *k = NULL; u32 offset; - bool keep_keyval = true; switch (CSR1212_KV_KEY_TYPE(ki)) { case CSR1212_KV_TYPE_IMMEDIATE: @@ -1135,8 +1135,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - /* Don't keep local reference when parsing. */ - keep_keyval = false; + + k->refcnt = 0; /* Don't keep local reference when parsing. */ break; case CSR1212_KV_TYPE_CSR_OFFSET: @@ -1146,8 +1146,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - /* Don't keep local reference when parsing. */ - keep_keyval = false; + k->refcnt = 0; /* Don't keep local reference when parsing. */ break; default: @@ -1175,10 +1174,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - /* Don't keep local reference when parsing. */ - keep_keyval = false; - /* Contents not read yet so it's not valid. */ - k->valid = 0; + k->refcnt = 0; /* Don't keep local reference when parsing. */ + k->valid = 0; /* Contents not read yet so it's not valid. */ k->offset = offset; k->prev = dir; @@ -1186,7 +1183,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) dir->next->prev = k; dir->next = k; } - ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval); + ret = csr1212_attach_keyval_to_directory(dir, k); out: if (ret != CSR1212_SUCCESS && k != NULL) free_keyval(k); diff --git a/trunk/drivers/ieee1394/csr1212.h b/trunk/drivers/ieee1394/csr1212.h index 043039fc63ec..df909ce66304 100644 --- a/trunk/drivers/ieee1394/csr1212.h +++ b/trunk/drivers/ieee1394/csr1212.h @@ -32,7 +32,6 @@ #include #include -#include #define CSR1212_MALLOC(size) kmalloc((size), GFP_KERNEL) #define CSR1212_FREE(ptr) kfree(ptr) @@ -150,7 +149,7 @@ struct csr1212_keyval { struct csr1212_directory directory; } value; struct csr1212_keyval *associate; - atomic_t refcnt; + int refcnt; /* used in generating and/or parsing CSR image */ struct csr1212_keyval *next, *prev; /* flat list of CSR elements */ @@ -351,8 +350,7 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv); * need for code to retain a keyval that has been parsed. */ static inline void csr1212_keep_keyval(struct csr1212_keyval *kv) { - atomic_inc(&kv->refcnt); - smp_mb__after_atomic_inc(); + kv->refcnt++; } diff --git a/trunk/drivers/ieee1394/eth1394.c b/trunk/drivers/ieee1394/eth1394.c index b166b3575fa6..dc9dce22f6a8 100644 --- a/trunk/drivers/ieee1394/eth1394.c +++ b/trunk/drivers/ieee1394/eth1394.c @@ -1153,6 +1153,8 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, pdg->sz++; lh = find_partial_datagram(pdgl, dgl); } else { + struct partial_datagram *pd; + pd = list_entry(lh, struct partial_datagram, list); if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) { @@ -1220,19 +1222,23 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, priv->stats.rx_errors++; priv->stats.rx_dropped++; dev_kfree_skb_any(skb); - } else if (netif_rx(skb) == NET_RX_DROP) { + goto bad_proto; + } + + if (netif_rx(skb) == NET_RX_DROP) { priv->stats.rx_errors++; priv->stats.rx_dropped++; - } else { - priv->stats.rx_packets++; - priv->stats.rx_bytes += skb->len; + goto bad_proto; } - spin_unlock_irqrestore(&priv->lock, flags); + /* Statistics */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; bad_proto: if (netif_queue_stopped(dev)) netif_wake_queue(dev); + spin_unlock_irqrestore(&priv->lock, flags); dev->last_rx = jiffies; diff --git a/trunk/drivers/ieee1394/ieee1394_core.c b/trunk/drivers/ieee1394/ieee1394_core.c index 36c747b277d0..98fd985a32ff 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.c +++ b/trunk/drivers/ieee1394/ieee1394_core.c @@ -488,7 +488,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) highlevel_host_reset(host); } -static DEFINE_SPINLOCK(pending_packets_lock); +static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED; /** * hpsb_packet_sent - notify core of sending a packet diff --git a/trunk/drivers/ieee1394/nodemgr.c b/trunk/drivers/ieee1394/nodemgr.c index 90dc75be3418..1939fee616ec 100644 --- a/trunk/drivers/ieee1394/nodemgr.c +++ b/trunk/drivers/ieee1394/nodemgr.c @@ -1014,13 +1014,13 @@ static struct unit_directory *nodemgr_process_unit_directory CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { switch (last_key_id) { case CSR1212_KV_ID_VENDOR: - csr1212_keep_keyval(kv); ud->vendor_name_kv = kv; + csr1212_keep_keyval(kv); break; case CSR1212_KV_ID_MODEL: - csr1212_keep_keyval(kv); ud->model_name_kv = kv; + csr1212_keep_keyval(kv); break; } @@ -1112,7 +1112,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent { unsigned int ud_id = 0; struct csr1212_dentry *dentry; - struct csr1212_keyval *kv, *vendor_name_kv = NULL; + struct csr1212_keyval *kv; u8 last_key_id = 0; ne->needs_probe = 0; @@ -1139,8 +1139,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { + ne->vendor_name_kv = kv; csr1212_keep_keyval(kv); - vendor_name_kv = kv; } } break; @@ -1149,13 +1149,10 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent } if (ne->vendor_name_kv) { - kv = ne->vendor_name_kv; - ne->vendor_name_kv = vendor_name_kv; - csr1212_release_keyval(kv); - } else if (vendor_name_kv) { - ne->vendor_name_kv = vendor_name_kv; - if (device_create_file(&ne->device, - &dev_attr_ne_vendor_name_kv) != 0) + int error = device_create_file(&ne->device, + &dev_attr_ne_vendor_name_kv); + + if (error && error != -EEXIST) HPSB_ERR("Failed to add sysfs attribute"); } } @@ -1715,8 +1712,7 @@ static int nodemgr_host_thread(void *__hi) * to make sure things settle down. */ g = get_hpsb_generation(host); for (i = 0; i < 4 ; i++) { - msleep_interruptible(63); - if (kthread_should_stop()) + if (msleep_interruptible(63) || kthread_should_stop()) goto exit; /* Now get the generation in which the node ID's we collect diff --git a/trunk/drivers/ieee1394/pcilynx.c b/trunk/drivers/ieee1394/pcilynx.c index 8af01ab30cc9..d1a5bcdb5e0b 100644 --- a/trunk/drivers/ieee1394/pcilynx.c +++ b/trunk/drivers/ieee1394/pcilynx.c @@ -121,6 +121,16 @@ static int bit_getsda(void *data) return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010; } +static int bit_reg(struct i2c_client *client) +{ + return 0; +} + +static int bit_unreg(struct i2c_client *client) +{ + return 0; +} + static struct i2c_algo_bit_data bit_data = { .setsda = bit_setsda, .setscl = bit_setscl, @@ -130,6 +140,14 @@ static struct i2c_algo_bit_data bit_data = { .timeout = 100, }; +static struct i2c_adapter bit_ops = { + .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h + .client_register = bit_reg, + .client_unregister = bit_unreg, + .name = "PCILynx I2C", +}; + + /* * PCL handling functions. @@ -747,6 +765,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) } else { struct ti_pcl pcl; u32 ack; + struct hpsb_packet *packet; PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL"); @@ -1417,11 +1436,9 @@ static int __devinit add_card(struct pci_dev *dev, struct i2c_algo_bit_data i2c_adapter_data; error = -ENOMEM; - i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL); + i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL); if (!i2c_ad) FAIL("failed to allocate I2C adapter memory"); - i2c_ad->id = I2C_HW_B_PCILYNX; - strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name)); i2c_adapter_data = bit_data; i2c_ad->algo_data = &i2c_adapter_data; i2c_adapter_data.data = lynx; @@ -1448,11 +1465,13 @@ static int __devinit add_card(struct pci_dev *dev, { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block } }; - /* we use i2c_transfer because we have no i2c_client - at hand */ + /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we + do it more efficiently in one transaction rather then using several reads */ if (i2c_transfer(i2c_ad, msg, 2) < 0) { PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); } else { + int i; + PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), * generation(1394a) and link_spd(1394a) field and recalculate diff --git a/trunk/drivers/ieee1394/sbp2.c b/trunk/drivers/ieee1394/sbp2.c index 1b353b964b33..a81ba8fca0db 100644 --- a/trunk/drivers/ieee1394/sbp2.c +++ b/trunk/drivers/ieee1394/sbp2.c @@ -242,8 +242,6 @@ static int sbp2_max_speed_and_size(struct sbp2_lu *); static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; -static DEFINE_RWLOCK(sbp2_hi_logical_units_lock); - static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, .host_reset = sbp2_host_reset, @@ -734,7 +732,6 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) struct sbp2_fwhost_info *hi; struct Scsi_Host *shost = NULL; struct sbp2_lu *lu = NULL; - unsigned long flags; lu = kzalloc(sizeof(*lu), GFP_KERNEL); if (!lu) { @@ -787,9 +784,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) lu->hi = hi; - write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_add_tail(&lu->lu_list, &hi->logical_units); - write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); /* Register the status FIFO address range. We could use the same FIFO * for targets at different nodes. However we need different FIFOs per @@ -833,20 +828,16 @@ static void sbp2_host_reset(struct hpsb_host *host) { struct sbp2_fwhost_info *hi; struct sbp2_lu *lu; - unsigned long flags; hi = hpsb_get_hostinfo(&sbp2_highlevel, host); if (!hi) return; - - read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_for_each_entry(lu, &hi->logical_units, lu_list) if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_SHUTDOWN)) { atomic_set(&lu->state, SBP2LU_STATE_IN_RESET); scsi_block_requests(lu->shost); } - read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); } static int sbp2_start_device(struct sbp2_lu *lu) @@ -928,7 +919,6 @@ static int sbp2_start_device(struct sbp2_lu *lu) static void sbp2_remove_device(struct sbp2_lu *lu) { struct sbp2_fwhost_info *hi; - unsigned long flags; if (!lu) return; @@ -943,9 +933,7 @@ static void sbp2_remove_device(struct sbp2_lu *lu) flush_scheduled_work(); sbp2util_remove_command_orb_pool(lu, hi->host); - write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_del(&lu->lu_list); - write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); if (lu->login_response) dma_free_coherent(hi->host->device.parent, @@ -1719,7 +1707,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, } /* Find the unit which wrote the status. */ - read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) { if (lu_tmp->ne->nodeid == nodeid && lu_tmp->status_fifo_addr == addr) { @@ -1727,8 +1714,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, break; } } - read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); - if (unlikely(!lu)) { SBP2_ERR("lu is NULL - device is gone?"); return RCODE_ADDRESS_ERROR; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index 3f2d68cff764..0f7a55d35ea7 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -107,7 +107,7 @@ struct ehca_sport { struct ehca_shca { struct ib_device ib_device; - struct of_device *ofdev; + struct ibmebus_dev *ibmebus_dev; u8 num_ports; int hw_level; struct list_head shca_list; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_eq.c b/trunk/drivers/infiniband/hw/ehca/ehca_eq.c index b4ac617a70e6..1d41faa7a337 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_eq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_eq.c @@ -123,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca, /* register interrupt handlers and initialize work queues */ if (type == EHCA_EQ) { - ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq, + ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq, IRQF_DISABLED, "ehca_eq", (void *)shca); if (ret < 0) @@ -131,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca, tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); } else if (type == EHCA_NEQ) { - ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq, + ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq, IRQF_DISABLED, "ehca_neq", (void *)shca); if (ret < 0) @@ -171,7 +171,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) u64 h_ret; spin_lock_irqsave(&eq->spinlock, flags); - ibmebus_free_irq(eq->ist, (void *)shca); + ibmebus_free_irq(NULL, eq->ist, (void *)shca); h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index a3409fdb307c..403467f66fe6 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -404,7 +404,7 @@ int ehca_init_device(struct ehca_shca *shca) shca->ib_device.node_type = RDMA_NODE_IB_CA; shca->ib_device.phys_port_cnt = shca->num_ports; shca->ib_device.num_comp_vectors = 1; - shca->ib_device.dma_device = &shca->ofdev->dev; + shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev; shca->ib_device.query_device = ehca_query_device; shca->ib_device.query_port = ehca_query_port; shca->ib_device.query_gid = ehca_query_gid; @@ -658,7 +658,7 @@ static struct attribute_group ehca_dev_attr_grp = { .attrs = ehca_dev_attrs }; -static int __devinit ehca_probe(struct of_device *dev, +static int __devinit ehca_probe(struct ibmebus_dev *dev, const struct of_device_id *id) { struct ehca_shca *shca; @@ -666,16 +666,16 @@ static int __devinit ehca_probe(struct of_device *dev, struct ib_pd *ibpd; int ret; - handle = of_get_property(dev->node, "ibm,hca-handle", NULL); + handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL); if (!handle) { ehca_gen_err("Cannot get eHCA handle for adapter: %s.", - dev->node->full_name); + dev->ofdev.node->full_name); return -ENODEV; } if (!(*handle)) { ehca_gen_err("Wrong eHCA handle for adapter: %s.", - dev->node->full_name); + dev->ofdev.node->full_name); return -ENODEV; } @@ -686,9 +686,9 @@ static int __devinit ehca_probe(struct of_device *dev, } mutex_init(&shca->modify_mutex); - shca->ofdev = dev; + shca->ibmebus_dev = dev; shca->ipz_hca_handle.handle = *handle; - dev->dev.driver_data = shca; + dev->ofdev.dev.driver_data = shca; ret = ehca_sense_attributes(shca); if (ret < 0) { @@ -764,7 +764,7 @@ static int __devinit ehca_probe(struct of_device *dev, } } - ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp); + ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); if (ret) /* only complain; we can live without attributes */ ehca_err(&shca->ib_device, "Cannot create device attributes ret=%d", ret); @@ -814,12 +814,12 @@ static int __devinit ehca_probe(struct of_device *dev, return -EINVAL; } -static int __devexit ehca_remove(struct of_device *dev) +static int __devexit ehca_remove(struct ibmebus_dev *dev) { - struct ehca_shca *shca = dev->dev.driver_data; + struct ehca_shca *shca = dev->ofdev.dev.driver_data; int ret; - sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); + sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); if (ehca_open_aqp1 == 1) { int i; @@ -870,11 +870,11 @@ static struct of_device_id ehca_device_table[] = {}, }; -static struct of_platform_driver ehca_driver = { - .name = "ehca", - .match_table = ehca_device_table, - .probe = ehca_probe, - .remove = ehca_remove, +static struct ibmebus_driver ehca_driver = { + .name = "ehca", + .id_table = ehca_device_table, + .probe = ehca_probe, + .remove = ehca_remove, }; void ehca_poll_eqs(unsigned long data) diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_dma.c b/trunk/drivers/infiniband/hw/ipath/ipath_dma.c index 22709a4f8fc8..f87f003e3ef8 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_dma.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_dma.c @@ -30,7 +30,6 @@ * SOFTWARE. */ -#include #include #include "ipath_verbs.h" @@ -97,18 +96,17 @@ static void ipath_dma_unmap_page(struct ib_device *dev, BUG_ON(!valid_dma_direction(direction)); } -static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction direction) +static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) { - struct scatterlist *sg; u64 addr; int i; int ret = nents; BUG_ON(!valid_dma_direction(direction)); - for_each_sg(sgl, sg, nents, i) { - addr = (u64) page_address(sg->page); + for (i = 0; i < nents; i++) { + addr = (u64) page_address(sg[i].page); /* TODO: handle highmem pages */ if (!addr) { ret = 0; diff --git a/trunk/drivers/infiniband/ulp/iser/iser_memory.c b/trunk/drivers/infiniband/ulp/iser/iser_memory.c index f3529b6f0a33..e05690e3592f 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_memory.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_memory.c @@ -124,19 +124,17 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_dir == ISER_DIR_OUT) { /* copy the unaligned sg the buffer which is used for RDMA */ - struct scatterlist *sgl = (struct scatterlist *)data->buf; - struct scatterlist *sg; + struct scatterlist *sg = (struct scatterlist *)data->buf; int i; char *p, *from; - p = mem; - for_each_sg(sgl, sg, data->size, i) { - from = kmap_atomic(sg->page, KM_USER0); + for (p = mem, i = 0; i < data->size; i++) { + from = kmap_atomic(sg[i].page, KM_USER0); memcpy(p, - from + sg->offset, - sg->length); + from + sg[i].offset, + sg[i].length); kunmap_atomic(from, KM_USER0); - p += sg->length; + p += sg[i].length; } } @@ -178,7 +176,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_dir == ISER_DIR_IN) { char *mem; - struct scatterlist *sgl, *sg; + struct scatterlist *sg; unsigned char *p, *to; unsigned int sg_size; int i; @@ -186,17 +184,16 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, /* copy back read RDMA to unaligned sg */ mem = mem_copy->copy_buf; - sgl = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf; + sg = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf; sg_size = iser_ctask->data[ISER_DIR_IN].size; - p = mem; - for_each_sg(sgl, sg, sg_size, i) { - to = kmap_atomic(sg->page, KM_SOFTIRQ0); - memcpy(to + sg->offset, + for (p = mem, i = 0; i < sg_size; i++){ + to = kmap_atomic(sg[i].page, KM_SOFTIRQ0); + memcpy(to + sg[i].offset, p, - sg->length); + sg[i].length); kunmap_atomic(to, KM_SOFTIRQ0); - p += sg->length; + p += sg[i].length; } } @@ -227,8 +224,7 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, struct iser_page_vec *page_vec, struct ib_device *ibdev) { - struct scatterlist *sgl = (struct scatterlist *)data->buf; - struct scatterlist *sg; + struct scatterlist *sg = (struct scatterlist *)data->buf; u64 first_addr, last_addr, page; int end_aligned; unsigned int cur_page = 0; @@ -236,25 +232,24 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, int i; /* compute the offset of first element */ - page_vec->offset = (u64) sgl[0].offset & ~MASK_4K; + page_vec->offset = (u64) sg[0].offset & ~MASK_4K; - for_each_sg(sgl, sg, data->dma_nents, i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, sg); + for (i = 0; i < data->dma_nents; i++) { + unsigned int dma_len = ib_sg_dma_len(ibdev, &sg[i]); total_sz += dma_len; - first_addr = ib_sg_dma_address(ibdev, sg); + first_addr = ib_sg_dma_address(ibdev, &sg[i]); last_addr = first_addr + dma_len; end_aligned = !(last_addr & ~MASK_4K); /* continue to collect page fragments till aligned or SG ends */ while (!end_aligned && (i + 1 < data->dma_nents)) { - sg = sg_next(sg); i++; - dma_len = ib_sg_dma_len(ibdev, sg); + dma_len = ib_sg_dma_len(ibdev, &sg[i]); total_sz += dma_len; - last_addr = ib_sg_dma_address(ibdev, sg) + dma_len; + last_addr = ib_sg_dma_address(ibdev, &sg[i]) + dma_len; end_aligned = !(last_addr & ~MASK_4K); } @@ -289,26 +284,25 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, struct ib_device *ibdev) { - struct scatterlist *sgl, *sg; + struct scatterlist *sg; u64 end_addr, next_addr; int i, cnt; unsigned int ret_len = 0; - sgl = (struct scatterlist *)data->buf; + sg = (struct scatterlist *)data->buf; - cnt = 0; - for_each_sg(sgl, sg, data->dma_nents, i) { + for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) { /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX " "offset: %ld sz: %ld\n", i, - (unsigned long)page_to_phys(sg->page), - (unsigned long)sg->offset, - (unsigned long)sg->length); */ - end_addr = ib_sg_dma_address(ibdev, sg) + - ib_sg_dma_len(ibdev, sg); + (unsigned long)page_to_phys(sg[i].page), + (unsigned long)sg[i].offset, + (unsigned long)sg[i].length); */ + end_addr = ib_sg_dma_address(ibdev, &sg[i]) + + ib_sg_dma_len(ibdev, &sg[i]); /* iser_dbg("Checking sg iobuf end address " "0x%08lX\n", end_addr); */ if (i + 1 < data->dma_nents) { - next_addr = ib_sg_dma_address(ibdev, sg_next(sg)); + next_addr = ib_sg_dma_address(ibdev, &sg[i+1]); /* are i, i+1 fragments of the same page? */ if (end_addr == next_addr) continue; @@ -328,16 +322,15 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, static void iser_data_buf_dump(struct iser_data_buf *data, struct ib_device *ibdev) { - struct scatterlist *sgl = (struct scatterlist *)data->buf; - struct scatterlist *sg; + struct scatterlist *sg = (struct scatterlist *)data->buf; int i; - for_each_sg(sgl, sg, data->dma_nents, i) + for (i = 0; i < data->dma_nents; i++) iser_err("sg[%d] dma_addr:0x%lX page:0x%p " "off:0x%x sz:0x%x dma_len:0x%x\n", - i, (unsigned long)ib_sg_dma_address(ibdev, sg), - sg->page, sg->offset, - sg->length, ib_sg_dma_len(ibdev, sg)); + i, (unsigned long)ib_sg_dma_address(ibdev, &sg[i]), + sg[i].page, sg[i].offset, + sg[i].length, ib_sg_dma_len(ibdev, &sg[i])); } static void iser_dump_page_vec(struct iser_page_vec *page_vec) diff --git a/trunk/drivers/input/misc/Kconfig b/trunk/drivers/input/misc/Kconfig index 7acc6351bb44..d602b8fa7d46 100644 --- a/trunk/drivers/input/misc/Kconfig +++ b/trunk/drivers/input/misc/Kconfig @@ -152,7 +152,7 @@ config INPUT_POWERMATE config INPUT_YEALINK tristate "Yealink usb-p1k voip phone" - depends on EXPERIMENTAL + depends EXPERIMENTAL depends on USB_ARCH_HAS_HCD select USB help diff --git a/trunk/drivers/isdn/capi/capidrv.c b/trunk/drivers/isdn/capi/capidrv.c index 476012b6dfac..23b6f7bc16b7 100644 --- a/trunk/drivers/isdn/capi/capidrv.c +++ b/trunk/drivers/isdn/capi/capidrv.c @@ -506,14 +506,9 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg) { struct sk_buff *skb; size_t len; - capi_cmsg2message(cmsg, cmsg->buf); len = CAPIMSG_LEN(cmsg->buf); skb = alloc_skb(len, GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "capidrv::send_message: can't allocate mem\n"); - return; - } memcpy(skb_put(skb, len), cmsg->buf, len); if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR) kfree_skb(skb); diff --git a/trunk/drivers/isdn/capi/kcapi.c b/trunk/drivers/isdn/capi/kcapi.c index f55531869313..9f73bc2727c2 100644 --- a/trunk/drivers/isdn/capi/kcapi.c +++ b/trunk/drivers/isdn/capi/kcapi.c @@ -821,8 +821,6 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) return -EFAULT; } card = get_capi_ctr_by_nr(ldef.contr); - if (!card) - return -EINVAL; card = capi_ctr_get(card); if (!card) return -ESRCH; diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c index af7648274b38..00e31609a238 100644 --- a/trunk/drivers/isdn/gigaset/bas-gigaset.c +++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c @@ -1936,7 +1936,14 @@ static int gigaset_write_room(struct cardstate *cs) */ static int gigaset_chars_in_buffer(struct cardstate *cs) { - return cs->cmdbytes; + unsigned long flags; + unsigned bytes; + + spin_lock_irqsave(&cs->cmdlock, flags); + bytes = cs->cmdbytes; + spin_unlock_irqrestore(&cs->cmdlock, flags); + + return bytes; } /* gigaset_brkchars diff --git a/trunk/drivers/isdn/gigaset/i4l.c b/trunk/drivers/isdn/gigaset/i4l.c index 9e089f06a942..1654fa413575 100644 --- a/trunk/drivers/isdn/gigaset/i4l.c +++ b/trunk/drivers/isdn/gigaset/i4l.c @@ -109,9 +109,13 @@ EXPORT_SYMBOL_GPL(gigaset_skb_sent); static int command_from_LL(isdn_ctrl *cntrl) { struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); + //isdn_ctrl response; + //unsigned long flags; struct bc_state *bcs; int retval = 0; struct setup_parm *sp; + unsigned param; + unsigned long flags; gigaset_debugdrivers(); @@ -158,8 +162,12 @@ static int command_from_LL(isdn_ctrl *cntrl) } *sp = cntrl->parm.setup; - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, - bcs->at_state.seq_index, NULL)) { + spin_lock_irqsave(&cs->lock, flags); + param = bcs->at_state.seq_index; + spin_unlock_irqrestore(&cs->lock, flags); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param, + NULL)) { //FIXME what should we do? kfree(sp); gigaset_free_channel(bcs); diff --git a/trunk/drivers/isdn/gigaset/proc.c b/trunk/drivers/isdn/gigaset/proc.c index da6f3acf9fd0..e767afa55abf 100644 --- a/trunk/drivers/isdn/gigaset/proc.c +++ b/trunk/drivers/isdn/gigaset/proc.c @@ -19,9 +19,15 @@ static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; + unsigned long flags; struct cardstate *cs = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", cs->cidmode); + spin_lock_irqsave(&cs->lock, flags); + ret = sprintf(buf, "%u\n", cs->cidmode); + spin_unlock_irqrestore(&cs->lock, flags); + + return ret; } static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, diff --git a/trunk/drivers/isdn/gigaset/usb-gigaset.c b/trunk/drivers/isdn/gigaset/usb-gigaset.c index ca4bee173cfb..a1263019df5e 100644 --- a/trunk/drivers/isdn/gigaset/usb-gigaset.c +++ b/trunk/drivers/isdn/gigaset/usb-gigaset.c @@ -310,6 +310,7 @@ static void gigaset_modem_fill(unsigned long data) struct cardstate *cs = (struct cardstate *) data; struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ struct cmdbuf_t *cb; + unsigned long flags; int again; gig_dbg(DEBUG_OUTPUT, "modem_fill"); @@ -322,7 +323,9 @@ static void gigaset_modem_fill(unsigned long data) do { again = 0; if (!bcs->tx_skb) { /* no skb is being sent */ + spin_lock_irqsave(&cs->cmdlock, flags); cb = cs->cmdbuf; + spin_unlock_irqrestore(&cs->cmdlock, flags); if (cb) { /* commands to send? */ gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); if (send_cb(cs, cb) < 0) { @@ -543,9 +546,13 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, static int gigaset_write_room(struct cardstate *cs) { + unsigned long flags; unsigned bytes; + spin_lock_irqsave(&cs->cmdlock, flags); bytes = cs->cmdbytes; + spin_unlock_irqrestore(&cs->cmdlock, flags); + return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; } diff --git a/trunk/drivers/isdn/i4l/isdn_common.c b/trunk/drivers/isdn/i4l/isdn_common.c index c6df2925ebd0..4910bca52640 100644 --- a/trunk/drivers/isdn/i4l/isdn_common.c +++ b/trunk/drivers/isdn/i4l/isdn_common.c @@ -1365,7 +1365,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) } else { s = NULL; } - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; if ((s = isdn_net_new(s, NULL))) { if (copy_to_user(argp, s, strlen(s) + 1)){ @@ -1375,7 +1375,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) } } else ret = -ENODEV; - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; case IIOCNETASL: /* Add a slave to a network-interface */ @@ -1384,7 +1384,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) return -EFAULT; } else return -EINVAL; - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; if ((s = isdn_net_newslave(bname))) { if (copy_to_user(argp, s, strlen(s) + 1)){ @@ -1394,17 +1394,17 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) } } else ret = -ENODEV; - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; case IIOCNETDIF: /* Delete a network-interface */ if (arg) { if (copy_from_user(name, argp, sizeof(name))) return -EFAULT; - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; ret = isdn_net_rm(name); - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; } else return -EINVAL; @@ -1433,10 +1433,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (arg) { if (copy_from_user(&phone, argp, sizeof(phone))) return -EFAULT; - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; ret = isdn_net_addphone(&phone); - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; } else return -EINVAL; @@ -1445,10 +1445,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (arg) { if (copy_from_user(&phone, argp, sizeof(phone))) return -EFAULT; - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; ret = isdn_net_getphones(&phone, argp); - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; } else return -EINVAL; @@ -1457,10 +1457,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (arg) { if (copy_from_user(&phone, argp, sizeof(phone))) return -EFAULT; - ret = mutex_lock_interruptible(&dev->mtx); + ret = down_interruptible(&dev->sem); if( ret ) return ret; ret = isdn_net_delphone(&phone); - mutex_unlock(&dev->mtx); + up(&dev->sem); return ret; } else return -EINVAL; @@ -2304,7 +2304,7 @@ static int __init isdn_init(void) #ifdef MODULE dev->owner = THIS_MODULE; #endif - mutex_init(&dev->mtx); + init_MUTEX(&dev->sem); init_waitqueue_head(&dev->info_waitq); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { dev->drvmap[i] = -1; diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index ec568fa1c6cc..257b44094e4c 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -83,7 +83,7 @@ config LEDS_WRAP config LEDS_H1940 tristate "LED Support for iPAQ H1940 device" - depends on LEDS_CLASS && ARCH_H1940 + depends LEDS_CLASS && ARCH_H1940 help This option enables support for the LEDs on the h1940. diff --git a/trunk/drivers/macintosh/adbhid.c b/trunk/drivers/macintosh/adbhid.c index 2766e4fc4ea8..8cce016b3d09 100644 --- a/trunk/drivers/macintosh/adbhid.c +++ b/trunk/drivers/macintosh/adbhid.c @@ -282,7 +282,7 @@ static void adbhid_input_keycode(int id, int scancode, int repeat) { struct adbhid *ahid = adbhid[id]; - int keycode, up_flag, key; + int keycode, up_flag; keycode = scancode & 0x7f; up_flag = scancode & 0x80; diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index 64fee90bb68b..8216a6f75be5 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -441,12 +441,33 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) return clone; } -static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) +static void crypt_free_buffer_pages(struct crypt_config *cc, + struct bio *clone, unsigned int bytes) { - unsigned int i; + unsigned int i, start, end; struct bio_vec *bv; - for (i = 0; i < clone->bi_vcnt; i++) { + /* + * This is ugly, but Jens Axboe thinks that using bi_idx in the + * endio function is too dangerous at the moment, so I calculate the + * correct position using bi_vcnt and bi_size. + * The bv_offset and bv_len fields might already be modified but we + * know that we always allocated whole pages. + * A fix to the bi_idx issue in the kernel is in the works, so + * we will hopefully be able to revert to the cleaner solution soon. + */ + i = clone->bi_vcnt - 1; + bv = bio_iovec_idx(clone, i); + end = (i << PAGE_SHIFT) + (bv->bv_offset + bv->bv_len) - clone->bi_size; + start = end - bytes; + + start >>= PAGE_SHIFT; + if (!clone->bi_size) + end = clone->bi_vcnt; + else + end >>= PAGE_SHIFT; + + for (i = start; i < end; i++) { bv = bio_iovec_idx(clone, i); BUG_ON(!bv->bv_page); mempool_free(bv->bv_page, cc->page_pool); @@ -498,7 +519,7 @@ static void crypt_endio(struct bio *clone, int error) * free the processed pages */ if (!read_io) { - crypt_free_buffer_pages(cc, clone); + crypt_free_buffer_pages(cc, clone, clone->bi_size); goto out; } @@ -587,7 +608,7 @@ static void process_write(struct dm_crypt_io *io) ctx.idx_out = 0; if (unlikely(crypt_convert(cc, &ctx) < 0)) { - crypt_free_buffer_pages(cc, clone); + crypt_free_buffer_pages(cc, clone, clone->bi_size); bio_put(clone); dec_pending(io, -EIO); return; diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index fbe477bb2c68..2bcde5798b5a 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -999,6 +999,33 @@ void dm_table_unplug_all(struct dm_table *t) } } +int dm_table_flush_all(struct dm_table *t) +{ + struct list_head *d, *devices = dm_table_get_devices(t); + int ret = 0; + unsigned i; + + for (i = 0; i < t->num_targets; i++) + if (t->targets[i].type->flush) + t->targets[i].type->flush(&t->targets[i]); + + for (d = devices->next; d != devices; d = d->next) { + struct dm_dev *dd = list_entry(d, struct dm_dev, list); + struct request_queue *q = bdev_get_queue(dd->bdev); + int err; + + if (!q->issue_flush_fn) + err = -EOPNOTSUPP; + else + err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL); + + if (!ret) + ret = err; + } + + return ret; +} + struct mapped_device *dm_table_get_md(struct dm_table *t) { dm_get(t->md); @@ -1016,3 +1043,4 @@ EXPORT_SYMBOL(dm_table_get_md); EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_unplug_all); +EXPORT_SYMBOL(dm_table_flush_all); diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index d837d37f6209..167765c47747 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -840,6 +840,21 @@ static int dm_request(struct request_queue *q, struct bio *bio) return 0; } +static int dm_flush_all(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct mapped_device *md = q->queuedata; + struct dm_table *map = dm_get_table(md); + int ret = -ENXIO; + + if (map) { + ret = dm_table_flush_all(map); + dm_table_put(map); + } + + return ret; +} + static void dm_unplug_all(struct request_queue *q) { struct mapped_device *md = q->queuedata; @@ -988,6 +1003,7 @@ static struct mapped_device *alloc_dev(int minor) blk_queue_make_request(md->queue, dm_request); blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); md->queue->unplug_fn = dm_unplug_all; + md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); if (!md->io_pool) diff --git a/trunk/drivers/md/dm.h b/trunk/drivers/md/dm.h index 4b3faa45277e..462ee652a890 100644 --- a/trunk/drivers/md/dm.h +++ b/trunk/drivers/md/dm.h @@ -111,6 +111,7 @@ void dm_table_postsuspend_targets(struct dm_table *t); int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); +int dm_table_flush_all(struct dm_table *t); /*----------------------------------------------------------------- * A registry of target types. diff --git a/trunk/drivers/md/linear.c b/trunk/drivers/md/linear.c index 56a11f6c127b..550148770bb2 100644 --- a/trunk/drivers/md/linear.c +++ b/trunk/drivers/md/linear.c @@ -92,6 +92,25 @@ static void linear_unplug(struct request_queue *q) } } +static int linear_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + linear_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; i < mddev->raid_disks && ret == 0; i++) { + struct block_device *bdev = conf->disks[i].rdev->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + } + return ret; +} + static int linear_congested(void *data, int bits) { mddev_t *mddev = data; @@ -260,6 +279,7 @@ static int linear_run (mddev_t *mddev) blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; + mddev->queue->issue_flush_fn = linear_issue_flush; mddev->queue->backing_dev_info.congested_fn = linear_congested; mddev->queue->backing_dev_info.congested_data = mddev; return 0; diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 0dc563d76b39..acf1b81b47cb 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -3463,6 +3463,7 @@ static int do_md_stop(mddev_t * mddev, int mode) mddev->pers->stop(mddev); mddev->queue->merge_bvec_fn = NULL; mddev->queue->unplug_fn = NULL; + mddev->queue->issue_flush_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; if (mddev->pers->sync_request) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); diff --git a/trunk/drivers/md/multipath.c b/trunk/drivers/md/multipath.c index b35731cceac6..f2a63f394ad9 100644 --- a/trunk/drivers/md/multipath.c +++ b/trunk/drivers/md/multipath.c @@ -194,6 +194,35 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) seq_printf (seq, "]"); } +static int multipath_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + multipath_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); + if (rdev && !test_bit(Faulty, &rdev->flags)) { + struct block_device *bdev = rdev->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} static int multipath_congested(void *data, int bits) { mddev_t *mddev = data; @@ -498,6 +527,7 @@ static int multipath_run (mddev_t *mddev) mddev->array_size = mddev->size; mddev->queue->unplug_fn = multipath_unplug; + mddev->queue->issue_flush_fn = multipath_issue_flush; mddev->queue->backing_dev_info.congested_fn = multipath_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/trunk/drivers/md/raid0.c b/trunk/drivers/md/raid0.c index e79e1a538d44..ef0da2d84959 100644 --- a/trunk/drivers/md/raid0.c +++ b/trunk/drivers/md/raid0.c @@ -40,6 +40,26 @@ static void raid0_unplug(struct request_queue *q) } } +static int raid0_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t **devlist = conf->strip_zone[0].dev; + int i, ret = 0; + + for (i=0; iraid_disks && ret == 0; i++) { + struct block_device *bdev = devlist[i]->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + } + return ret; +} + static int raid0_congested(void *data, int bits) { mddev_t *mddev = data; @@ -230,6 +250,7 @@ static int create_strip_zones (mddev_t *mddev) mddev->queue->unplug_fn = raid0_unplug; + mddev->queue->issue_flush_fn = raid0_issue_flush; mddev->queue->backing_dev_info.congested_fn = raid0_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 0bcefad82413..6d03bea6fa58 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -567,6 +567,36 @@ static void raid1_unplug(struct request_queue *q) md_wakeup_thread(mddev->thread); } +static int raid1_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); + if (rdev && !test_bit(Faulty, &rdev->flags)) { + struct block_device *bdev = rdev->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + static int raid1_congested(void *data, int bits) { mddev_t *mddev = data; @@ -1967,6 +1997,7 @@ static int run(mddev_t *mddev) mddev->array_size = mddev->size; mddev->queue->unplug_fn = raid1_unplug; + mddev->queue->issue_flush_fn = raid1_issue_flush; mddev->queue->backing_dev_info.congested_fn = raid1_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index fc6607acb6e4..25a96c42bdb0 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -611,6 +611,36 @@ static void raid10_unplug(struct request_queue *q) md_wakeup_thread(mddev->thread); } +static int raid10_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); + if (rdev && !test_bit(Faulty, &rdev->flags)) { + struct block_device *bdev = rdev->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + static int raid10_congested(void *data, int bits) { mddev_t *mddev = data; @@ -2088,6 +2118,7 @@ static int run(mddev_t *mddev) mddev->resync_max_sectors = size << conf->chunk_shift; mddev->queue->unplug_fn = raid10_unplug; + mddev->queue->issue_flush_fn = raid10_issue_flush; mddev->queue->backing_dev_info.congested_fn = raid10_congested; mddev->queue->backing_dev_info.congested_data = mddev; diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 8ee181a01f52..caaca9e178bc 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -3204,6 +3204,36 @@ static void raid5_unplug_device(struct request_queue *q) unplug_slaves(mddev); } +static int raid5_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid5_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && !test_bit(Faulty, &rdev->flags)) { + struct block_device *bdev = rdev->bdev; + struct request_queue *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + static int raid5_congested(void *data, int bits) { mddev_t *mddev = data; @@ -4233,6 +4263,7 @@ static int run(mddev_t *mddev) mdname(mddev)); mddev->queue->unplug_fn = raid5_unplug_device; + mddev->queue->issue_flush_fn = raid5_issue_flush; mddev->queue->backing_dev_info.congested_data = mddev; mddev->queue->backing_dev_info.congested_fn = raid5_congested; diff --git a/trunk/drivers/media/video/cx88/cx88-alsa.c b/trunk/drivers/media/video/cx88/cx88-alsa.c index 141dadf7cf1b..90c36c5705c3 100644 --- a/trunk/drivers/media/video/cx88/cx88-alsa.c +++ b/trunk/drivers/media/video/cx88/cx88-alsa.c @@ -7,7 +7,7 @@ * (c) 2005,2006 Ricardo Cerqueira * (c) 2005 Mauro Carvalho Chehab * Based on a dummy cx88 module by Gerd Knorr - * Based on dummy.c by Jaroslav Kysela + * Based on dummy.c by Jaroslav Kysela * * 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 diff --git a/trunk/drivers/message/fusion/mptscsih.c b/trunk/drivers/message/fusion/mptscsih.c index 626bb3c9af2b..bdff950a54a1 100644 --- a/trunk/drivers/message/fusion/mptscsih.c +++ b/trunk/drivers/message/fusion/mptscsih.c @@ -293,7 +293,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, for (ii=0; ii < (numSgeThisFrame-1); ii++) { thisxfer = sg_dma_len(sg); if (thisxfer == 0) { - sg = sg_next(sg); /* Get next SG element from the OS */ + sg ++; /* Get next SG element from the OS */ sg_done++; continue; } @@ -301,7 +301,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, v2 = sg_dma_address(sg); mptscsih_add_sge(psge, sgflags | thisxfer, v2); - sg = sg_next(sg); /* Get next SG element from the OS */ + sg++; /* Get next SG element from the OS */ psge += (sizeof(u32) + sizeof(dma_addr_t)); sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); sg_done++; @@ -322,7 +322,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, v2 = sg_dma_address(sg); mptscsih_add_sge(psge, sgflags | thisxfer, v2); /* - sg = sg_next(sg); + sg++; psge += (sizeof(u32) + sizeof(dma_addr_t)); */ sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); @@ -2605,10 +2605,14 @@ mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd) } /** - * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list + * SCPNT_TO_LOOKUP_IDX + * + * search's for a given scmd in the ScsiLookup[] array list + * * @ioc: Pointer to MPT_ADAPTER structure - * @sc: scsi_cmnd pointer - */ + * @scmd: scsi_cmnd pointer + * + **/ static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc) { diff --git a/trunk/drivers/message/i2o/i2o_block.c b/trunk/drivers/message/i2o/i2o_block.c index d602ba6d5417..50b2c7334410 100644 --- a/trunk/drivers/message/i2o/i2o_block.c +++ b/trunk/drivers/message/i2o/i2o_block.c @@ -148,6 +148,29 @@ static int i2o_block_device_flush(struct i2o_device *dev) return i2o_msg_post_wait(dev->iop, msg, 60); }; +/** + * i2o_block_issue_flush - device-flush interface for block-layer + * @queue: the request queue of the device which should be flushed + * @disk: gendisk + * @error_sector: error offset + * + * Helper function to provide flush functionality to block-layer. + * + * Returns 0 on success or negative error code on failure. + */ + +static int i2o_block_issue_flush(struct request_queue * queue, struct gendisk *disk, + sector_t * error_sector) +{ + struct i2o_block_device *i2o_blk_dev = queue->queuedata; + int rc = -ENODEV; + + if (likely(i2o_blk_dev)) + rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev); + + return rc; +} + /** * i2o_block_device_mount - Mount (load) the media of device dev * @dev: I2O device which should receive the mount request @@ -986,6 +1009,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void) } blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + blk_queue_issue_flush_fn(queue, i2o_block_issue_flush); gd->major = I2O_MAJOR; gd->queue = queue; diff --git a/trunk/drivers/mmc/card/queue.c b/trunk/drivers/mmc/card/queue.c index a5d0354bbbda..b0abc7d92805 100644 --- a/trunk/drivers/mmc/card/queue.c +++ b/trunk/drivers/mmc/card/queue.c @@ -153,14 +153,14 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_max_hw_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); - mq->sg = kzalloc(sizeof(struct scatterlist), + mq->sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } - mq->bounce_sg = kzalloc(sizeof(struct scatterlist) * + mq->bounce_sg = kmalloc(sizeof(struct scatterlist) * bouncesz / 512, GFP_KERNEL); if (!mq->bounce_sg) { ret = -ENOMEM; @@ -177,7 +177,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); - mq->sg = kzalloc(sizeof(struct scatterlist) * + mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; diff --git a/trunk/drivers/mmc/host/mmc_spi.c b/trunk/drivers/mmc/host/mmc_spi.c index 7ae18eaed6c5..254b194e7625 100644 --- a/trunk/drivers/mmc/host/mmc_spi.c +++ b/trunk/drivers/mmc/host/mmc_spi.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include /* for R1_SPI_* bit values */ @@ -1281,8 +1280,8 @@ static int mmc_spi_probe(struct spi_device *spi) if (!host->data) goto fail_nobuf1; - if (spi->master->dev.parent->dma_mask) { - struct device *dev = spi->master->dev.parent; + if (spi->master->cdev.dev->dma_mask) { + struct device *dev = spi->master->cdev.dev; host->dma_dev = dev; host->ones_dma = dma_map_single(dev, ones, diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index 862f47223fdc..8d3893da06f5 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -3118,13 +3118,7 @@ static void acpi_set_WOL(struct net_device *dev) iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); iowrite16(RxEnable, ioaddr + EL3_CMD); - if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) { - printk(KERN_INFO "%s: WOL not supported.\n", - pci_name(VORTEX_PCI(vp))); - - vp->enable_wol = 0; - return; - } + pci_enable_wake(VORTEX_PCI(vp), 0, 1); /* Change the power state to D3; RxEnable doesn't take effect. */ pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 83d52c8acab0..8f99a0626616 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2173,16 +2173,6 @@ config SKGE To compile this driver as a module, choose M here: the module will be called skge. This is recommended. -config SKGE_DEBUG - bool "Debugging interface" - depends on SKGE && DEBUG_FS - help - This option adds the ability to dump driver state for debugging. - The file debugfs/skge/ethX displays the state of the internal - transmit and receive rings. - - If unsure, say N. - config SKY2 tristate "SysKonnect Yukon2 support" depends on PCI diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 6f85cc31f8a2..db80f243dd37 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -1263,7 +1263,6 @@ static void bond_setup_by_slave(struct net_device *bond_dev, struct bonding *bond = bond_dev->priv; bond_dev->neigh_setup = slave_dev->neigh_setup; - bond_dev->header_ops = slave_dev->header_ops; bond_dev->type = slave_dev->type; bond_dev->hard_header_len = slave_dev->hard_header_len; @@ -3352,10 +3351,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave switch (event) { case NETDEV_UNREGISTER: if (bond_dev) { - if (bond->setup_by_slave) - bond_release_and_destroy(bond_dev, slave_dev); - else - bond_release(bond_dev, slave_dev); + bond_release(bond_dev, slave_dev); } break; case NETDEV_CHANGE: @@ -3370,6 +3366,11 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave * ... Or is it this? */ break; + case NETDEV_GOING_DOWN: + dprintk("slave %s is going down\n", slave_dev->name); + if (bond->setup_by_slave) + bond_release_and_destroy(bond_dev, slave_dev); + break; case NETDEV_CHANGEMTU: /* * TODO: Should slaves be allowed to diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index b8180600a309..a8bbd563265c 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.1" -#define DRV_RELDATE "October 15, 2007" +#define DRV_VERSION "3.2.0" +#define DRV_RELDATE "September 13, 2007" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" diff --git a/trunk/drivers/net/e1000e/ethtool.c b/trunk/drivers/net/e1000e/ethtool.c index 0666e62e9ad2..b7a7e2ae5e13 100644 --- a/trunk/drivers/net/e1000e/ethtool.c +++ b/trunk/drivers/net/e1000e/ethtool.c @@ -110,7 +110,6 @@ static int e1000_get_settings(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 status; if (hw->media_type == e1000_media_type_copper) { @@ -148,16 +147,16 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; } - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - if (status & E1000_STATUS_SPEED_1000) - ecmd->speed = 1000; - else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = 100; - else - ecmd->speed = 10; + if (er32(STATUS) & E1000_STATUS_LU) { + + adapter->hw.mac.ops.get_link_up_info(hw, &adapter->link_speed, + &adapter->link_duplex); + ecmd->speed = adapter->link_speed; + + /* unfortunately FULL_DUPLEX != DUPLEX_FULL + * and HALF_DUPLEX != DUPLEX_HALF */ - if (status & E1000_STATUS_FD) + if (adapter->link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; @@ -171,16 +170,6 @@ static int e1000_get_settings(struct net_device *netdev, return 0; } -static u32 e1000_get_link(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 status; - - status = er32(STATUS); - return (status & E1000_STATUS_LU); -} - static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) { struct e1000_mac_info *mac = &adapter->hw.mac; @@ -1462,11 +1451,11 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) } *data = e1000_setup_desc_rings(adapter); - if (*data) + if (data) goto out; *data = e1000_setup_loopback_test(adapter); - if (*data) + if (data) goto err_loopback; *data = e1000_run_loopback_test(adapter); @@ -1762,7 +1751,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_msglevel = e1000_get_msglevel, .set_msglevel = e1000_set_msglevel, .nway_reset = e1000_nway_reset, - .get_link = e1000_get_link, + .get_link = ethtool_op_get_link, .get_eeprom_len = e1000_get_eeprom_len, .get_eeprom = e1000_get_eeprom, .set_eeprom = e1000_set_eeprom, diff --git a/trunk/drivers/net/e1000e/hw.h b/trunk/drivers/net/e1000e/hw.h index 64515789fd4d..aa82f1afb7fb 100644 --- a/trunk/drivers/net/e1000e/hw.h +++ b/trunk/drivers/net/e1000e/hw.h @@ -852,7 +852,7 @@ struct e1000_hw { #ifdef DEBUG #define hw_dbg(hw, format, arg...) \ - printk(KERN_DEBUG "%s: " format, e1000e_get_hw_dev_name(hw), ##arg) + printk(KERN_DEBUG, "%s: " format, e1000e_get_hw_dev_name(hw), ##arg); #else static inline int __attribute__ ((format (printf, 2, 3))) hw_dbg(struct e1000_hw *hw, const char *format, ...) diff --git a/trunk/drivers/net/ehea/ehea.h b/trunk/drivers/net/ehea/ehea.h index b557bb44a36f..ac21526b6de8 100644 --- a/trunk/drivers/net/ehea/ehea.h +++ b/trunk/drivers/net/ehea/ehea.h @@ -388,7 +388,7 @@ struct ehea_port_res { #define EHEA_MAX_PORTS 16 struct ehea_adapter { u64 handle; - struct of_device *ofdev; + struct ibmebus_dev *ebus_dev; struct ehea_port *port[EHEA_MAX_PORTS]; struct ehea_eq *neq; /* notification event queue */ struct tasklet_struct neq_tasklet; diff --git a/trunk/drivers/net/ehea/ehea_main.c b/trunk/drivers/net/ehea/ehea_main.c index fe5ffac7ac57..2ba57e6ace4d 100644 --- a/trunk/drivers/net/ehea/ehea_main.c +++ b/trunk/drivers/net/ehea/ehea_main.c @@ -98,10 +98,10 @@ struct work_struct ehea_rereg_mr_task; struct semaphore dlpar_mem_lock; -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, const struct of_device_id *id); -static int __devexit ehea_remove(struct of_device *dev); +static int __devexit ehea_remove(struct ibmebus_dev *dev); static struct of_device_id ehea_device_table[] = { { @@ -111,9 +111,9 @@ static struct of_device_id ehea_device_table[] = { {}, }; -static struct of_platform_driver ehea_driver = { +static struct ibmebus_driver ehea_driver = { .name = "ehea", - .match_table = ehea_device_table, + .id_table = ehea_device_table, .probe = ehea_probe_adapter, .remove = ehea_remove, }; @@ -1044,7 +1044,7 @@ static int ehea_reg_interrupts(struct net_device *dev) snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff", dev->name); - ret = ibmebus_request_irq(port->qp_eq->attr.ist1, + ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1, ehea_qp_aff_irq_handler, IRQF_DISABLED, port->int_aff_name, port); if (ret) { @@ -1062,7 +1062,7 @@ static int ehea_reg_interrupts(struct net_device *dev) pr = &port->port_res[i]; snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1, "%s-queue%d", dev->name, i); - ret = ibmebus_request_irq(pr->eq->attr.ist1, + ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1, ehea_recv_irq_handler, IRQF_DISABLED, pr->int_send_name, pr); @@ -1083,11 +1083,11 @@ static int ehea_reg_interrupts(struct net_device *dev) out_free_req: while (--i >= 0) { u32 ist = port->port_res[i].eq->attr.ist1; - ibmebus_free_irq(ist, &port->port_res[i]); + ibmebus_free_irq(NULL, ist, &port->port_res[i]); } out_free_qpeq: - ibmebus_free_irq(port->qp_eq->attr.ist1, port); + ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port); i = port->num_def_qps; goto out; @@ -1104,14 +1104,14 @@ static void ehea_free_interrupts(struct net_device *dev) for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { pr = &port->port_res[i]; - ibmebus_free_irq(pr->eq->attr.ist1, pr); + ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr); if (netif_msg_intr(port)) ehea_info("free send irq for res %d with handle 0x%X", i, pr->eq->attr.ist1); } /* associated events */ - ibmebus_free_irq(port->qp_eq->attr.ist1, port); + ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port); if (netif_msg_intr(port)) ehea_info("associated event interrupt for handle 0x%X freed", port->qp_eq->attr.ist1); @@ -2832,7 +2832,7 @@ static struct device *ehea_register_port(struct ehea_port *port, int ret; port->ofdev.node = of_node_get(dn); - port->ofdev.dev.parent = &port->adapter->ofdev->dev; + port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev; port->ofdev.dev.bus = &ibmebus_bus_type; sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++); @@ -3011,7 +3011,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) const u32 *dn_log_port_id; int i = 0; - lhea_dn = adapter->ofdev->node; + lhea_dn = adapter->ebus_dev->ofdev.node; while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", @@ -3051,7 +3051,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, struct device_node *eth_dn = NULL; const u32 *dn_log_port_id; - lhea_dn = adapter->ofdev->node; + lhea_dn = adapter->ebus_dev->ofdev.node; while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", @@ -3157,31 +3157,31 @@ static ssize_t ehea_remove_port(struct device *dev, static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); -int ehea_create_device_sysfs(struct of_device *dev) +int ehea_create_device_sysfs(struct ibmebus_dev *dev) { - int ret = device_create_file(&dev->dev, &dev_attr_probe_port); + int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port); if (ret) goto out; - ret = device_create_file(&dev->dev, &dev_attr_remove_port); + ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port); out: return ret; } -void ehea_remove_device_sysfs(struct of_device *dev) +void ehea_remove_device_sysfs(struct ibmebus_dev *dev) { - device_remove_file(&dev->dev, &dev_attr_probe_port); - device_remove_file(&dev->dev, &dev_attr_remove_port); + device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port); + device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port); } -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, const struct of_device_id *id) { struct ehea_adapter *adapter; const u64 *adapter_handle; int ret; - if (!dev || !dev->node) { + if (!dev || !dev->ofdev.node) { ehea_error("Invalid ibmebus device probed"); return -EINVAL; } @@ -3189,36 +3189,36 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { ret = -ENOMEM; - dev_err(&dev->dev, "no mem for ehea_adapter\n"); + dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n"); goto out; } list_add(&adapter->list, &adapter_list); - adapter->ofdev = dev; + adapter->ebus_dev = dev; - adapter_handle = of_get_property(dev->node, "ibm,hea-handle", + adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle", NULL); if (adapter_handle) adapter->handle = *adapter_handle; if (!adapter->handle) { - dev_err(&dev->dev, "failed getting handle for adapter" - " '%s'\n", dev->node->full_name); + dev_err(&dev->ofdev.dev, "failed getting handle for adapter" + " '%s'\n", dev->ofdev.node->full_name); ret = -ENODEV; goto out_free_ad; } adapter->pd = EHEA_PD_ID; - dev->dev.driver_data = adapter; + dev->ofdev.dev.driver_data = adapter; /* initialize adapter and ports */ /* get adapter properties */ ret = ehea_sense_adapter_attr(adapter); if (ret) { - dev_err(&dev->dev, "sense_adapter_attr failed: %d", ret); + dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret); goto out_free_ad; } @@ -3226,18 +3226,18 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1); if (!adapter->neq) { ret = -EIO; - dev_err(&dev->dev, "NEQ creation failed"); + dev_err(&dev->ofdev.dev, "NEQ creation failed"); goto out_free_ad; } tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet, (unsigned long)adapter); - ret = ibmebus_request_irq(adapter->neq->attr.ist1, + ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1, ehea_interrupt_neq, IRQF_DISABLED, "ehea_neq", adapter); if (ret) { - dev_err(&dev->dev, "requesting NEQ IRQ failed"); + dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed"); goto out_kill_eq; } @@ -3247,7 +3247,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ret = ehea_setup_ports(adapter); if (ret) { - dev_err(&dev->dev, "setup_ports failed"); + dev_err(&dev->ofdev.dev, "setup_ports failed"); goto out_rem_dev_sysfs; } @@ -3258,7 +3258,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ehea_remove_device_sysfs(dev); out_free_irq: - ibmebus_free_irq(adapter->neq->attr.ist1, adapter); + ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); out_kill_eq: ehea_destroy_eq(adapter->neq); @@ -3269,9 +3269,9 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, return ret; } -static int __devexit ehea_remove(struct of_device *dev) +static int __devexit ehea_remove(struct ibmebus_dev *dev) { - struct ehea_adapter *adapter = dev->dev.driver_data; + struct ehea_adapter *adapter = dev->ofdev.dev.driver_data; int i; for (i = 0; i < EHEA_MAX_PORTS; i++) @@ -3284,7 +3284,7 @@ static int __devexit ehea_remove(struct of_device *dev) flush_scheduled_work(); - ibmebus_free_irq(adapter->neq->attr.ist1, adapter); + ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); ehea_destroy_eq(adapter->neq); diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index cfbb7aacfe94..dae30b731342 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -128,7 +128,7 @@ #else #define DRIVERNAPI #endif -#define FORCEDETH_VERSION "0.61" +#define FORCEDETH_VERSION "0.60" #define DRV_NAME "forcedeth" #include @@ -752,6 +752,7 @@ struct fe_priv { /* General data: * Locking: spin_lock(&np->lock); */ + struct net_device_stats stats; struct nv_ethtool_stats estats; int in_shutdown; u32 linkspeed; @@ -1504,16 +1505,15 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) nv_get_hw_stats(dev); /* copy to net_device stats */ - dev->stats.tx_bytes = np->estats.tx_bytes; - dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors; - dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors; - dev->stats.rx_crc_errors = np->estats.rx_crc_errors; - dev->stats.rx_over_errors = np->estats.rx_over_errors; - dev->stats.rx_errors = np->estats.rx_errors_total; - dev->stats.tx_errors = np->estats.tx_errors_total; - } - - return &dev->stats; + np->stats.tx_bytes = np->estats.tx_bytes; + np->stats.tx_fifo_errors = np->estats.tx_fifo_errors; + np->stats.tx_carrier_errors = np->estats.tx_carrier_errors; + np->stats.rx_crc_errors = np->estats.rx_crc_errors; + np->stats.rx_over_errors = np->estats.rx_over_errors; + np->stats.rx_errors = np->estats.rx_errors_total; + np->stats.tx_errors = np->estats.tx_errors_total; + } + return &np->stats; } /* @@ -1733,7 +1733,7 @@ static void nv_drain_tx(struct net_device *dev) np->tx_ring.ex[i].buflow = 0; } if (nv_release_txskb(dev, &np->tx_skb[i])) - dev->stats.tx_dropped++; + np->stats.tx_dropped++; } } @@ -2049,13 +2049,13 @@ static void nv_tx_done(struct net_device *dev) if (flags & NV_TX_LASTPACKET) { if (flags & NV_TX_ERROR) { if (flags & NV_TX_UNDERFLOW) - dev->stats.tx_fifo_errors++; + np->stats.tx_fifo_errors++; if (flags & NV_TX_CARRIERLOST) - dev->stats.tx_carrier_errors++; - dev->stats.tx_errors++; + np->stats.tx_carrier_errors++; + np->stats.tx_errors++; } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; + np->stats.tx_packets++; + np->stats.tx_bytes += np->get_tx_ctx->skb->len; } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; @@ -2064,13 +2064,13 @@ static void nv_tx_done(struct net_device *dev) if (flags & NV_TX2_LASTPACKET) { if (flags & NV_TX2_ERROR) { if (flags & NV_TX2_UNDERFLOW) - dev->stats.tx_fifo_errors++; + np->stats.tx_fifo_errors++; if (flags & NV_TX2_CARRIERLOST) - dev->stats.tx_carrier_errors++; - dev->stats.tx_errors++; + np->stats.tx_carrier_errors++; + np->stats.tx_errors++; } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; + np->stats.tx_packets++; + np->stats.tx_bytes += np->get_tx_ctx->skb->len; } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; @@ -2107,7 +2107,7 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit) if (flags & NV_TX2_LASTPACKET) { if (!(flags & NV_TX2_ERROR)) - dev->stats.tx_packets++; + np->stats.tx_packets++; dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; } @@ -2268,13 +2268,13 @@ static int nv_rx_process(struct net_device *dev, int limit) { struct fe_priv *np = netdev_priv(dev); u32 flags; - int rx_work = 0; + u32 rx_processed_cnt = 0; struct sk_buff *skb; int len; while((np->get_rx.orig != np->put_rx.orig) && !((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) && - (rx_work < limit)) { + (rx_processed_cnt++ < limit)) { dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n", dev->name, flags); @@ -2308,7 +2308,7 @@ static int nv_rx_process(struct net_device *dev, int limit) if (flags & NV_RX_ERROR4) { len = nv_getlen(dev, skb->data, len); if (len < 0) { - dev->stats.rx_errors++; + np->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2322,12 +2322,12 @@ static int nv_rx_process(struct net_device *dev, int limit) /* the rest are hard errors */ else { if (flags & NV_RX_MISSEDFRAME) - dev->stats.rx_missed_errors++; + np->stats.rx_missed_errors++; if (flags & NV_RX_CRCERR) - dev->stats.rx_crc_errors++; + np->stats.rx_crc_errors++; if (flags & NV_RX_OVERFLOW) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++; + np->stats.rx_over_errors++; + np->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2343,7 +2343,7 @@ static int nv_rx_process(struct net_device *dev, int limit) if (flags & NV_RX2_ERROR4) { len = nv_getlen(dev, skb->data, len); if (len < 0) { - dev->stats.rx_errors++; + np->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2357,10 +2357,10 @@ static int nv_rx_process(struct net_device *dev, int limit) /* the rest are hard errors */ else { if (flags & NV_RX2_CRCERR) - dev->stats.rx_crc_errors++; + np->stats.rx_crc_errors++; if (flags & NV_RX2_OVERFLOW) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++; + np->stats.rx_over_errors++; + np->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2389,18 +2389,16 @@ static int nv_rx_process(struct net_device *dev, int limit) netif_rx(skb); #endif dev->last_rx = jiffies; - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; + np->stats.rx_packets++; + np->stats.rx_bytes += len; next_pkt: if (unlikely(np->get_rx.orig++ == np->last_rx.orig)) np->get_rx.orig = np->first_rx.orig; if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx)) np->get_rx_ctx = np->first_rx_ctx; - - rx_work++; } - return rx_work; + return rx_processed_cnt; } static int nv_rx_process_optimized(struct net_device *dev, int limit) @@ -2507,8 +2505,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) } dev->last_rx = jiffies; - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; + np->stats.rx_packets++; + np->stats.rx_bytes += len; } else { dev_kfree_skb(skb); } @@ -3729,7 +3727,7 @@ static void nv_do_stats_poll(unsigned long data) static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); + strcpy(info->driver, "forcedeth"); strcpy(info->version, FORCEDETH_VERSION); strcpy(info->bus_info, pci_name(np->pci_dev)); } @@ -4993,11 +4991,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i u32 phystate_orig = 0, phystate; int phyinitialized = 0; DECLARE_MAC_BUF(mac); - static int printed_version; - - if (!printed_version++) - printk(KERN_INFO "%s: Reverse Engineered nForce ethernet" - " driver. Version %s.\n", DRV_NAME, FORCEDETH_VERSION); dev = alloc_etherdev(sizeof(struct fe_priv)); err = -ENOMEM; @@ -5021,8 +5014,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->stats_poll.function = &nv_do_stats_poll; /* timer handler */ err = pci_enable_device(pci_dev); - if (err) + if (err) { + printk(KERN_INFO "forcedeth: pci_enable_dev failed (%d) for device %s\n", + err, pci_name(pci_dev)); goto out_free; + } pci_set_master(pci_dev); @@ -5051,8 +5047,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } } if (i == DEVICE_COUNT_RESOURCE) { - dev_printk(KERN_INFO, &pci_dev->dev, - "Couldn't find register window\n"); + printk(KERN_INFO "forcedeth: Couldn't find register window for device %s.\n", + pci_name(pci_dev)); goto out_relreg; } @@ -5065,14 +5061,16 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->desc_ver = DESC_VER_3; np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; if (dma_64bit) { - if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) - dev_printk(KERN_INFO, &pci_dev->dev, - "64-bit DMA failed, using 32-bit addressing\n"); - else + if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { + printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", + pci_name(pci_dev)); + } else { dev->features |= NETIF_F_HIGHDMA; + printk(KERN_INFO "forcedeth: using HIGHDMA\n"); + } if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) { - dev_printk(KERN_INFO, &pci_dev->dev, - "64-bit DMA (consistent) failed, using 32-bit ring buffers\n"); + printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n", + pci_name(pci_dev)); } } } else if (id->driver_data & DEV_HAS_LARGEDESC) { @@ -5207,11 +5205,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i * Bad mac address. At least one bios sets the mac address * to 01:23:45:67:89:ab */ - dev_printk(KERN_ERR, &pci_dev->dev, - "Invalid Mac address detected: %s\n", - print_mac(mac, dev->dev_addr)); - dev_printk(KERN_ERR, &pci_dev->dev, - "Please complain to your hardware vendor. Switching to a random MAC.\n"); + printk(KERN_ERR "%s: Invalid Mac address detected: %s\n", + pci_name(pci_dev), print_mac(mac, dev->dev_addr)); + printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n"); dev->dev_addr[0] = 0x00; dev->dev_addr[1] = 0x00; dev->dev_addr[2] = 0x6c; @@ -5325,8 +5321,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i break; } if (i == 33) { - dev_printk(KERN_INFO, &pci_dev->dev, - "open: Could not find a valid PHY.\n"); + printk(KERN_INFO "%s: open: Could not find a valid PHY.\n", + pci_name(pci_dev)); goto out_error; } @@ -5348,37 +5344,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i err = register_netdev(dev); if (err) { - dev_printk(KERN_INFO, &pci_dev->dev, - "unable to register netdev: %d\n", err); + printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err); goto out_error; } - - dev_printk(KERN_INFO, &pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, " - "addr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", - dev->name, - np->phy_oui, - np->phyaddr, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); - - dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n", - dev->features & NETIF_F_HIGHDMA ? "highdma " : "", - dev->features & (NETIF_F_HW_CSUM | NETIF_F_SG) ? - "csum " : "", - dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ? - "vlan " : "", - id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "", - id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "", - id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "", - np->gigabit == PHY_GIGABIT ? "gbit " : "", - np->need_linktimer ? "lnktim " : "", - np->msi_flags & NV_MSI_CAPABLE ? "msi " : "", - np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "", - np->desc_ver); + printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n", + dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device, + pci_name(pci_dev)); return 0; @@ -5596,16 +5567,17 @@ static struct pci_device_id pci_tbl[] = { }; static struct pci_driver driver = { - .name = DRV_NAME, - .id_table = pci_tbl, - .probe = nv_probe, - .remove = __devexit_p(nv_remove), - .suspend = nv_suspend, - .resume = nv_resume, + .name = "forcedeth", + .id_table = pci_tbl, + .probe = nv_probe, + .remove = __devexit_p(nv_remove), + .suspend = nv_suspend, + .resume = nv_resume, }; static int __init init_nic(void) { + printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION); return pci_register_driver(&driver); } diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index cc288d8f6a53..558440c15b6c 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -1237,6 +1237,8 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) * starting over will fix the problem. */ static void gfar_timeout(struct net_device *dev) { + struct gfar_private *priv = netdev_priv(dev); + dev->stats.tx_errors++; if (dev->flags & IFF_UP) { @@ -1342,9 +1344,8 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) return skb; } -static inline void count_errors(unsigned short status, struct net_device *dev) +static inline void count_errors(unsigned short status, struct gfar_private *priv) { - struct gfar_private *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct gfar_extra_stats *estats = &priv->extra_stats; @@ -1538,7 +1539,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) dev->stats.rx_bytes += pkt_len; } else { - count_errors(bdp->status, dev); + count_errors(bdp->status, priv); if (skb) dev_kfree_skb_any(skb); diff --git a/trunk/drivers/net/hp100.c b/trunk/drivers/net/hp100.c index 49421d1cd3a5..e4fde17e2841 100644 --- a/trunk/drivers/net/hp100.c +++ b/trunk/drivers/net/hp100.c @@ -8,7 +8,7 @@ ** Extended for new busmaster capable chipsets by ** Siegfried "Frieder" Loeffler (dg1sek) ** -** Maintained by: Jaroslav Kysela +** Maintained by: Jaroslav Kysela ** ** This driver has only been tested with ** -- HP J2585B 10/100 Mbit/s PCI Busmaster @@ -2951,7 +2951,7 @@ static struct pci_driver hp100_pci_driver = { */ MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jaroslav Kysela , " +MODULE_AUTHOR("Jaroslav Kysela , " "Siegfried \"Frieder\" Loeffler (dg1sek) "); MODULE_DESCRIPTION("HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters"); diff --git a/trunk/drivers/net/ibm_newemac/mal.c b/trunk/drivers/net/ibm_newemac/mal.c index a680eb05ba60..39f4cb6b0cf3 100644 --- a/trunk/drivers/net/ibm_newemac/mal.c +++ b/trunk/drivers/net/ibm_newemac/mal.c @@ -45,8 +45,6 @@ int __devinit mal_register_commac(struct mal_instance *mal, return -EBUSY; } - if (list_empty(&mal->list)) - napi_enable(&mal->napi); mal->tx_chan_mask |= commac->tx_chan_mask; mal->rx_chan_mask |= commac->rx_chan_mask; list_add(&commac->list, &mal->list); @@ -69,8 +67,6 @@ void __devexit mal_unregister_commac(struct mal_instance *mal, mal->tx_chan_mask &= ~commac->tx_chan_mask; mal->rx_chan_mask &= ~commac->rx_chan_mask; list_del_init(&commac->list); - if (list_empty(&mal->list)) - napi_disable(&mal->napi); spin_unlock_irqrestore(&mal->lock, flags); } @@ -186,7 +182,7 @@ static inline void mal_enable_eob_irq(struct mal_instance *mal) set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE); } -/* synchronized by NAPI state */ +/* synchronized by __LINK_STATE_RX_SCHED bit in ndev->state */ static inline void mal_disable_eob_irq(struct mal_instance *mal) { // XXX might want to cache MAL_CFG as the DCR read can be slooooow @@ -321,8 +317,8 @@ void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac) while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags)) msleep(1); - /* Synchronize with the MAL NAPI poller */ - __napi_synchronize(&mal->napi); + /* Synchronize with the MAL NAPI poller. */ + napi_disable(&mal->napi); } void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac) @@ -330,12 +326,7 @@ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac) smp_wmb(); clear_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags); - /* Feels better to trigger a poll here to catch up with events that - * may have happened on this channel while disabled. It will most - * probably be delayed until the next interrupt but that's mostly a - * non-issue in the context where this is called. - */ - napi_schedule(&mal->napi); + // XXX might want to kick a poll now... } static int mal_poll(struct napi_struct *napi, int budget) @@ -345,7 +336,8 @@ static int mal_poll(struct napi_struct *napi, int budget) int received = 0; unsigned long flags; - MAL_DBG2(mal, "poll(%d)" NL, budget); + MAL_DBG2(mal, "poll(%d) %d ->" NL, *budget, + rx_work_limit); again: /* Process TX skbs */ list_for_each(l, &mal->poll_list) { @@ -536,12 +528,11 @@ static int __devinit mal_probe(struct of_device *ofdev, } INIT_LIST_HEAD(&mal->poll_list); + mal->napi.weight = CONFIG_IBM_NEW_EMAC_POLL_WEIGHT; + mal->napi.poll = mal_poll; INIT_LIST_HEAD(&mal->list); spin_lock_init(&mal->lock); - netif_napi_add(NULL, &mal->napi, mal_poll, - CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); - /* Load power-on reset defaults */ mal_reset(mal); diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index b9961dc47606..2aae9fe38c5a 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -36,15 +36,13 @@ #include #include #include -#include -#include #include #include #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.12" +#define DRV_VERSION "1.11" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -59,10 +57,7 @@ #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 #define BLINK_MS 250 -#define LINK_HZ HZ - -#define SKGE_EEPROM_MAGIC 0x9933aabb - +#define LINK_HZ (HZ/2) MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); MODULE_AUTHOR("Stephen Hemminger "); @@ -450,15 +445,15 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) else yukon_get_stats(skge, data); - dev->stats.tx_bytes = data[0]; - dev->stats.rx_bytes = data[1]; - dev->stats.tx_packets = data[2] + data[4] + data[6]; - dev->stats.rx_packets = data[3] + data[5] + data[7]; - dev->stats.multicast = data[3] + data[5]; - dev->stats.collisions = data[10]; - dev->stats.tx_aborted_errors = data[12]; + skge->net_stats.tx_bytes = data[0]; + skge->net_stats.rx_bytes = data[1]; + skge->net_stats.tx_packets = data[2] + data[4] + data[6]; + skge->net_stats.rx_packets = data[3] + data[5] + data[7]; + skge->net_stats.multicast = data[3] + data[5]; + skge->net_stats.collisions = data[10]; + skge->net_stats.tx_aborted_errors = data[12]; - return &dev->stats; + return &skge->net_stats; } static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -803,98 +798,6 @@ static int skge_phys_id(struct net_device *dev, u32 data) return 0; } -static int skge_get_eeprom_len(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - u32 reg2; - - pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, ®2); - return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); -} - -static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset) -{ - u32 val; - - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (!(offset & PCI_VPD_ADDR_F)); - - pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val); - return val; -} - -static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val) -{ - pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val); - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, - offset | PCI_VPD_ADDR_F); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (offset & PCI_VPD_ADDR_F); -} - -static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - eeprom->magic = SKGE_EEPROM_MAGIC; - - while (length > 0) { - u32 val = skge_vpd_read(pdev, cap, offset); - int n = min_t(int, length, sizeof(val)); - - memcpy(data, &val, n); - length -= n; - data += n; - offset += n; - } - return 0; -} - -static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - if (eeprom->magic != SKGE_EEPROM_MAGIC) - return -EINVAL; - - while (length > 0) { - u32 val; - int n = min_t(int, length, sizeof(val)); - - if (n < sizeof(val)) - val = skge_vpd_read(pdev, cap, offset); - memcpy(&val, data, n); - - skge_vpd_write(pdev, cap, offset, val); - - length -= n; - data += n; - offset += n; - } - return 0; -} - static const struct ethtool_ops skge_ethtool_ops = { .get_settings = skge_get_settings, .set_settings = skge_set_settings, @@ -907,9 +810,6 @@ static const struct ethtool_ops skge_ethtool_ops = { .set_msglevel = skge_set_msglevel, .nway_reset = skge_nway_reset, .get_link = ethtool_op_get_link, - .get_eeprom_len = skge_get_eeprom_len, - .get_eeprom = skge_get_eeprom, - .set_eeprom = skge_set_eeprom, .get_ringparam = skge_get_ring_param, .set_ringparam = skge_set_ring_param, .get_pauseparam = skge_get_pauseparam, @@ -1095,15 +995,19 @@ static void xm_link_down(struct skge_hw *hw, int port) { struct net_device *dev = hw->dev[port]; struct skge_port *skge = netdev_priv(dev); - u16 cmd = xm_read16(hw, port, XM_MMU_CMD); + u16 cmd, msk; - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); + if (hw->phy_type == SK_PHY_XMAC) { + msk = xm_read16(hw, port, XM_IMSK); + msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND; + xm_write16(hw, port, XM_IMSK, msk); + } + cmd = xm_read16(hw, port, XM_MMU_CMD); cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); xm_write16(hw, port, XM_MMU_CMD, cmd); - /* dummy read to ensure writing */ - xm_read16(hw, port, XM_MMU_CMD); + (void) xm_read16(hw, port, XM_MMU_CMD); if (netif_carrier_ok(dev)) skge_link_down(skge); @@ -1199,7 +1103,7 @@ static void genesis_reset(struct skge_hw *hw, int port) /* reset the statistics module */ xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); + xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ @@ -1237,7 +1141,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) u16 status; /* read twice because of latch */ - xm_phy_read(hw, port, PHY_BCOM_STAT); + (void) xm_phy_read(hw, port, PHY_BCOM_STAT); status = xm_phy_read(hw, port, PHY_BCOM_STAT); if ((status & PHY_ST_LSYNC) == 0) { @@ -1438,7 +1342,7 @@ static void xm_phy_init(struct skge_port *skge) mod_timer(&skge->link_timer, jiffies + LINK_HZ); } -static int xm_check_link(struct net_device *dev) +static void xm_check_link(struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; @@ -1446,25 +1350,25 @@ static int xm_check_link(struct net_device *dev) u16 status; /* read twice because of latch */ - xm_phy_read(hw, port, PHY_XMAC_STAT); + (void) xm_phy_read(hw, port, PHY_XMAC_STAT); status = xm_phy_read(hw, port, PHY_XMAC_STAT); if ((status & PHY_ST_LSYNC) == 0) { xm_link_down(hw, port); - return 0; + return; } if (skge->autoneg == AUTONEG_ENABLE) { u16 lpa, res; if (!(status & PHY_ST_AN_OVER)) - return 0; + return; lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); if (lpa & PHY_B_AN_RF) { printk(KERN_NOTICE PFX "%s: remote fault\n", dev->name); - return 0; + return; } res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI); @@ -1480,7 +1384,7 @@ static int xm_check_link(struct net_device *dev) default: printk(KERN_NOTICE PFX "%s: duplex mismatch\n", dev->name); - return 0; + return; } /* We are using IEEE 802.3z/D5.0 Table 37-4 */ @@ -1504,14 +1408,11 @@ static int xm_check_link(struct net_device *dev) if (!netif_carrier_ok(dev)) genesis_link_up(skge); - return 1; } /* Poll to check for link coming up. - * * Since internal PHY is wired to a level triggered pin, can't - * get an interrupt when carrier is detected, need to poll for - * link coming up. + * get an interrupt when carrier is detected. */ static void xm_link_timer(unsigned long arg) { @@ -1519,35 +1420,29 @@ static void xm_link_timer(unsigned long arg) struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; - int i; - unsigned long flags; if (!netif_running(dev)) return; - spin_lock_irqsave(&hw->phy_lock, flags); - - /* - * Verify that the link by checking GPIO register three times. - * This pin has the signal from the link_sync pin connected to it. - */ - for (i = 0; i < 3; i++) { - if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) - goto link_down; - } - - /* Re-enable interrupt to detect link down */ - if (xm_check_link(dev)) { - u16 msk = xm_read16(hw, port, XM_IMSK); - msk &= ~XM_IS_INP_ASS; - xm_write16(hw, port, XM_IMSK, msk); + if (netif_carrier_ok(dev)) { xm_read16(hw, port, XM_ISRC); + if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)) + goto nochange; } else { -link_down: - mod_timer(&skge->link_timer, - round_jiffies(jiffies + LINK_HZ)); + if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) + goto nochange; + xm_read16(hw, port, XM_ISRC); + if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS) + goto nochange; } - spin_unlock_irqrestore(&hw->phy_lock, flags); + + spin_lock(&hw->phy_lock); + xm_check_link(dev); + spin_unlock(&hw->phy_lock); + +nochange: + if (netif_running(dev)) + mod_timer(&skge->link_timer, jiffies + LINK_HZ); } static void genesis_mac_init(struct skge_hw *hw, int port) @@ -1784,27 +1679,24 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data) static void genesis_mac_intr(struct skge_hw *hw, int port) { - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); + struct skge_port *skge = netdev_priv(hw->dev[port]); u16 status = xm_read16(hw, port, XM_ISRC); if (netif_msg_intr(skge)) printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", - dev->name, status); + skge->netdev->name, status); - if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { - xm_link_down(hw, port); - mod_timer(&skge->link_timer, jiffies + 1); - } + if (hw->phy_type == SK_PHY_XMAC && + (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC))) + xm_link_down(hw, port); if (status & XM_IS_TXF_UR) { xm_write32(hw, port, XM_MODE, XM_MD_FTF); - ++dev->stats.tx_fifo_errors; + ++skge->net_stats.tx_fifo_errors; } - if (status & XM_IS_RXF_OV) { xm_write32(hw, port, XM_MODE, XM_MD_FRF); - ++dev->stats.rx_fifo_errors; + ++skge->net_stats.rx_fifo_errors; } } @@ -1861,12 +1753,11 @@ static void genesis_link_up(struct skge_port *skge) } xm_write32(hw, port, XM_MODE, mode); + msk = XM_DEF_MSK; + if (hw->phy_type != SK_PHY_XMAC) + msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */ - /* Turn on detection of Tx underrun, Rx overrun */ - msk = xm_read16(hw, port, XM_IMSK); - msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR); xm_write16(hw, port, XM_IMSK, msk); - xm_read16(hw, port, XM_ISRC); /* get MMU Command Reg. */ @@ -2301,12 +2192,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port) dev->name, status); if (status & GM_IS_RX_FF_OR) { - ++dev->stats.rx_fifo_errors; + ++skge->net_stats.rx_fifo_errors; skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); } if (status & GM_IS_TX_FF_UR) { - ++dev->stats.tx_fifo_errors; + ++skge->net_stats.tx_fifo_errors; skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); } @@ -2512,31 +2403,32 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } -/* Assign Ram Buffer allocation to queue */ -static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space) +static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) { u32 end; - /* convert from K bytes to qwords used for hw register */ - start *= 1024/8; - space *= 1024/8; - end = start + space - 1; + start /= 8; + len /= 8; + end = start + len - 1; skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); skge_write32(hw, RB_ADDR(q, RB_START), start); - skge_write32(hw, RB_ADDR(q, RB_END), end); skge_write32(hw, RB_ADDR(q, RB_WP), start); skge_write32(hw, RB_ADDR(q, RB_RP), start); + skge_write32(hw, RB_ADDR(q, RB_END), end); if (q == Q_R1 || q == Q_R2) { - u32 tp = space - space/4; - /* Set thresholds on receive queue's */ - skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); - skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); - } else if (hw->chip_id != CHIP_ID_GENESIS) - /* Genesis Tx Fifo is too small for normal store/forward */ + skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), + start + (2*len)/3); + skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), + start + (len/3)); + } else { + /* Enable store & forward on Tx queue's because + * Tx FIFO is only 4K on Genesis and 1K on Yukon + */ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); + } skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); } @@ -2564,7 +2456,7 @@ static int skge_up(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - u32 ramaddr, ramsize, rxspace; + u32 chunk, ram_addr; size_t rx_size, tx_size; int err; @@ -2619,15 +2511,14 @@ static int skge_up(struct net_device *dev) spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ - ramsize = (hw->ram_size - hw->ram_offset) / hw->ports; - ramaddr = hw->ram_offset + port * ramsize; - rxspace = 8 + (2*(ramsize - 16))/3; - - skge_ramset(hw, rxqaddr[port], ramaddr, rxspace); - skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace); + chunk = hw->ram_size / ((hw->ports + 1)*2); + ram_addr = hw->ram_offset + 2 * chunk * port; + skge_ramset(hw, rxqaddr[port], ram_addr, chunk); skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); + BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); + skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); /* Start receiver BMU */ @@ -2653,15 +2544,6 @@ static int skge_up(struct net_device *dev) return err; } -/* stop receiver */ -static void skge_rx_stop(struct skge_hw *hw, int port) -{ - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); -} - static int skge_down(struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); @@ -2713,8 +2595,11 @@ static int skge_down(struct net_device *dev) /* Reset the RAM Buffer async Tx queue */ skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET); - - skge_rx_stop(hw, port); + /* stop receiver */ + skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); + skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), + RB_RST_SET|RB_DIS_OP_MD); + skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); if (hw->chip_id == CHIP_ID_GENESIS) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); @@ -2897,11 +2782,7 @@ static void skge_tx_timeout(struct net_device *dev) static int skge_change_mtu(struct net_device *dev, int new_mtu) { - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; int err; - u16 ctl, reg; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; @@ -2911,40 +2792,13 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu) return 0; } - skge_write32(hw, B0_IMSK, 0); - dev->trans_start = jiffies; /* prevent tx timeout */ - netif_stop_queue(dev); - napi_disable(&skge->napi); - - ctl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); - - skge_rx_clean(skge); - skge_rx_stop(hw, port); + skge_down(dev); dev->mtu = new_mtu; - reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (new_mtu > 1500) - reg |= GM_SMOD_JUMBO_ENA; - gma_write16(hw, port, GM_SERIAL_MODE, reg); - - skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); - - err = skge_rx_fill(dev); - wmb(); - if (!err) - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - skge_write32(hw, B0_IMSK, hw->intr_mask); - + err = skge_up(dev); if (err) dev_close(dev); - else { - gma_write16(hw, port, GM_GP_CTRL, ctl); - - napi_enable(&skge->napi); - netif_wake_queue(dev); - } return err; } @@ -3140,18 +2994,18 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, if (skge->hw->chip_id == CHIP_ID_GENESIS) { if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) - dev->stats.rx_length_errors++; + skge->net_stats.rx_length_errors++; if (status & XMR_FS_FRA_ERR) - dev->stats.rx_frame_errors++; + skge->net_stats.rx_frame_errors++; if (status & XMR_FS_FCS_ERR) - dev->stats.rx_crc_errors++; + skge->net_stats.rx_crc_errors++; } else { if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) - dev->stats.rx_length_errors++; + skge->net_stats.rx_length_errors++; if (status & GMR_FS_FRAGMENT) - dev->stats.rx_frame_errors++; + skge->net_stats.rx_frame_errors++; if (status & GMR_FS_CRC_ERR) - dev->stats.rx_crc_errors++; + skge->net_stats.rx_crc_errors++; } resubmit: @@ -3249,7 +3103,10 @@ static void skge_mac_parity(struct skge_hw *hw, int port) { struct net_device *dev = hw->dev[port]; - ++dev->stats.tx_heartbeat_errors; + if (dev) { + struct skge_port *skge = netdev_priv(dev); + ++skge->net_stats.tx_heartbeat_errors; + } if (hw->chip_id == CHIP_ID_GENESIS) skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), @@ -3402,7 +3259,9 @@ static irqreturn_t skge_intr(int irq, void *dev_id) skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); if (status & IS_PA_TO_RX1) { - ++hw->dev[0]->stats.rx_over_errors; + struct skge_port *skge = netdev_priv(hw->dev[0]); + + ++skge->net_stats.rx_over_errors; skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); } @@ -3419,7 +3278,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id) } if (status & IS_PA_TO_RX2) { - ++hw->dev[1]->stats.rx_over_errors; + ++skge->net_stats.rx_over_errors; skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); } @@ -3591,12 +3450,15 @@ static int skge_reset(struct skge_hw *hw) if (hw->chip_id == CHIP_ID_GENESIS) { if (t8 == 3) { /* special case: 4 x 64k x 36, offset = 0x80000 */ - hw->ram_size = 1024; - hw->ram_offset = 512; + hw->ram_size = 0x100000; + hw->ram_offset = 0x80000; } else hw->ram_size = t8 * 512; - } else /* Yukon */ - hw->ram_size = t8 ? t8 * 4 : 128; + } + else if (t8 == 0) + hw->ram_size = 0x20000; + else + hw->ram_size = t8 * 4096; hw->intr_mask = IS_HW_ERR; @@ -3678,145 +3540,6 @@ static int skge_reset(struct skge_hw *hw) return 0; } - -#ifdef CONFIG_SKGE_DEBUG - -static struct dentry *skge_debug; - -static int skge_debug_show(struct seq_file *seq, void *v) -{ - struct net_device *dev = seq->private; - const struct skge_port *skge = netdev_priv(dev); - const struct skge_hw *hw = skge->hw; - const struct skge_element *e; - - if (!netif_running(dev)) - return -ENETDOWN; - - seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC), - skge_read32(hw, B0_IMSK)); - - seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring)); - for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { - const struct skge_tx_desc *t = e->desc; - seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n", - t->control, t->dma_hi, t->dma_lo, t->status, - t->csum_offs, t->csum_write, t->csum_start); - } - - seq_printf(seq, "\nRx Ring: \n"); - for (e = skge->rx_ring.to_clean; ; e = e->next) { - const struct skge_rx_desc *r = e->desc; - - if (r->control & BMU_OWN) - break; - - seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n", - r->control, r->dma_hi, r->dma_lo, r->status, - r->timestamp, r->csum1, r->csum1_start); - } - - return 0; -} - -static int skge_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, skge_debug_show, inode->i_private); -} - -static const struct file_operations skge_debug_fops = { - .owner = THIS_MODULE, - .open = skge_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * Use network device events to create/remove/rename - * debugfs file entries - */ -static int skge_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - struct skge_port *skge; - struct dentry *d; - - if (dev->open != &skge_up || !skge_debug) - goto done; - - skge = netdev_priv(dev); - switch(event) { - case NETDEV_CHANGENAME: - if (skge->debugfs) { - d = debugfs_rename(skge_debug, skge->debugfs, - skge_debug, dev->name); - if (d) - skge->debugfs = d; - else { - pr_info(PFX "%s: rename failed\n", dev->name); - debugfs_remove(skge->debugfs); - } - } - break; - - case NETDEV_GOING_DOWN: - if (skge->debugfs) { - debugfs_remove(skge->debugfs); - skge->debugfs = NULL; - } - break; - - case NETDEV_UP: - d = debugfs_create_file(dev->name, S_IRUGO, - skge_debug, dev, - &skge_debug_fops); - if (!d || IS_ERR(d)) - pr_info(PFX "%s: debugfs create failed\n", - dev->name); - else - skge->debugfs = d; - break; - } - -done: - return NOTIFY_DONE; -} - -static struct notifier_block skge_notifier = { - .notifier_call = skge_device_event, -}; - - -static __init void skge_debug_init(void) -{ - struct dentry *ent; - - ent = debugfs_create_dir("skge", NULL); - if (!ent || IS_ERR(ent)) { - pr_info(PFX "debugfs create directory failed\n"); - return; - } - - skge_debug = ent; - register_netdevice_notifier(&skge_notifier); -} - -static __exit void skge_debug_cleanup(void) -{ - if (skge_debug) { - unregister_netdevice_notifier(&skge_notifier); - debugfs_remove(skge_debug); - skge_debug = NULL; - } -} - -#else -#define skge_debug_init() -#define skge_debug_cleanup() -#endif - /* Initialize network device */ static struct net_device *skge_devinit(struct skge_hw *hw, int port, int highmem) @@ -4181,14 +3904,12 @@ static struct pci_driver skge_driver = { static int __init skge_init_module(void) { - skge_debug_init(); return pci_register_driver(&skge_driver); } static void __exit skge_cleanup_module(void) { pci_unregister_driver(&skge_driver); - skge_debug_cleanup(); } module_init(skge_init_module); diff --git a/trunk/drivers/net/skge.h b/trunk/drivers/net/skge.h index 17caccbb7685..1a57bdd1ddf1 100644 --- a/trunk/drivers/net/skge.h +++ b/trunk/drivers/net/skge.h @@ -1,5 +1,5 @@ /* - * Definitions for the new Marvell Yukon / SysKonnect driver. + * Definitions for the new Marvell Yukon / SysKonenct driver. */ #ifndef _SKGE_H #define _SKGE_H @@ -8,10 +8,8 @@ #define PCI_DEV_REG1 0x40 #define PCI_PHY_COMA 0x8000000 #define PCI_VIO 0x2000000 - #define PCI_DEV_REG2 0x44 -#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */ -#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */ +#define PCI_REV_DESC 0x4 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ @@ -2193,10 +2191,12 @@ enum { XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */ XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */ XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ - - XM_IMSK_DISABLE = 0xffff, }; +#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \ + XM_IS_RXF_OV | XM_IS_TXF_UR)) + + /* XM_HW_CFG 16 bit r/w Hardware Config Register */ enum { XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */ @@ -2469,9 +2469,8 @@ struct skge_port { void *mem; /* PCI memory for rings */ dma_addr_t dma; unsigned long mem_size; -#ifdef CONFIG_SKGE_DEBUG - struct dentry *debugfs; -#endif + + struct net_device_stats net_stats; }; diff --git a/trunk/drivers/net/tokenring/3c359.c b/trunk/drivers/net/tokenring/3c359.c index 5d31519a6c67..7224d368b2a7 100644 --- a/trunk/drivers/net/tokenring/3c359.c +++ b/trunk/drivers/net/tokenring/3c359.c @@ -760,7 +760,7 @@ static int xl_open_hw(struct net_device *dev) if (xl_priv->xl_laa[0]) { /* If using a LAA address */ for (i=10;i<16;i++) { writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - writeb(xl_priv->xl_laa[i-10],xl_mmio + MMIO_MACDATA) ; + writeb(xl_priv->xl_laa[i],xl_mmio + MMIO_MACDATA) ; } memcpy(dev->dev_addr,xl_priv->xl_laa,dev->addr_len) ; } else { /* Regular hardware address */ diff --git a/trunk/drivers/pcmcia/Kconfig b/trunk/drivers/pcmcia/Kconfig index f201bd673137..c0c77f82d051 100644 --- a/trunk/drivers/pcmcia/Kconfig +++ b/trunk/drivers/pcmcia/Kconfig @@ -2,7 +2,9 @@ # PCCARD (PCMCIA/CardBus) bus subsystem configuration # -menuconfig PCCARD +menu "PCCARD (PCMCIA/CardBus) support" + +config PCCARD tristate "PCCard (PCMCIA/CardBus) support" depends on HOTPLUG ---help--- @@ -276,3 +278,5 @@ config PCCARD_IODYN bool endif # PCCARD + +endmenu diff --git a/trunk/drivers/pcmcia/au1000_xxs1500.c b/trunk/drivers/pcmcia/au1000_xxs1500.c index ce9d5c44a7b5..01874b0bb03b 100644 --- a/trunk/drivers/pcmcia/au1000_xxs1500.c +++ b/trunk/drivers/pcmcia/au1000_xxs1500.c @@ -50,10 +50,7 @@ #include #include - -#define PCMCIA_MAX_SOCK 0 -#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) -#define PCMCIA_IRQ AU1000_GPIO_4 +#include #if 0 #define DEBUG(x,args...) printk(__FUNCTION__ ": " x,##args) diff --git a/trunk/drivers/pcmcia/cistpl.c b/trunk/drivers/pcmcia/cistpl.c index 06a85d7d5aa2..d154dee76e7f 100644 --- a/trunk/drivers/pcmcia/cistpl.c +++ b/trunk/drivers/pcmcia/cistpl.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -402,15 +401,6 @@ EXPORT_SYMBOL(pcmcia_replace_cis); ======================================================================*/ -static inline u16 cis_get_u16(void *ptr) -{ - return le16_to_cpu(get_unaligned((__le16 *) ptr)); -} -static inline u32 cis_get_u32(void *ptr) -{ - return le32_to_cpu(get_unaligned((__le32 *) ptr)); -} - typedef struct tuple_flags { u_int link_space:4; u_int has_link:1; @@ -471,7 +461,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) /* Get indirect link from the MFC tuple */ read_cis_cache(s, LINK_SPACE(tuple->Flags), tuple->LinkOffset, 5, link); - ofs = cis_get_u32(link + 1); + ofs = le32_to_cpu(*(__le32 *)(link+1)); SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR); /* Move to the next indirect link */ tuple->LinkOffset += 5; @@ -678,10 +668,10 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum) u_char *p; if (tuple->TupleDataLen < 5) return CS_BAD_TUPLE; - p = (u_char *) tuple->TupleData; - csum->addr = tuple->CISOffset + cis_get_u16(p) - 2; - csum->len = cis_get_u16(p + 2); - csum->sum = *(p + 4); + p = (u_char *)tuple->TupleData; + csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2; + csum->len = le16_to_cpu(*(__le16 *)(p + 2)); + csum->sum = *(p+4); return CS_SUCCESS; } @@ -691,7 +681,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link) { if (tuple->TupleDataLen < 4) return CS_BAD_TUPLE; - link->addr = cis_get_u32(tuple->TupleData); + link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData); return CS_SUCCESS; } @@ -710,8 +700,7 @@ static int parse_longlink_mfc(tuple_t *tuple, return CS_BAD_TUPLE; for (i = 0; i < link->nfn; i++) { link->fn[i].space = *p; p++; - link->fn[i].addr = cis_get_u32(p); - p += 4; + link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4; } return CS_SUCCESS; } @@ -798,10 +787,12 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec) static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m) { + __le16 *p; if (tuple->TupleDataLen < 4) return CS_BAD_TUPLE; - m->manf = cis_get_u16(tuple->TupleData); - m->card = cis_get_u16(tuple->TupleData + 2); + p = (__le16 *)tuple->TupleData; + m->manf = le16_to_cpu(p[0]); + m->card = le16_to_cpu(p[1]); return CS_SUCCESS; } @@ -1100,7 +1091,7 @@ static int parse_cftable_entry(tuple_t *tuple, break; case 0x20: entry->mem.nwin = 1; - entry->mem.win[0].len = cis_get_u16(p) << 8; + entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8; entry->mem.win[0].card_addr = 0; entry->mem.win[0].host_addr = 0; p += 2; @@ -1108,8 +1099,9 @@ static int parse_cftable_entry(tuple_t *tuple, break; case 0x40: entry->mem.nwin = 1; - entry->mem.win[0].len = cis_get_u16(p) << 8; - entry->mem.win[0].card_addr = cis_get_u16(p + 2) << 8; + entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8; + entry->mem.win[0].card_addr = + le16_to_cpu(*(__le16 *)(p+2)) << 8; entry->mem.win[0].host_addr = 0; p += 4; if (p > q) return CS_BAD_TUPLE; @@ -1146,7 +1138,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar) p = (u_char *)tuple->TupleData; bar->attr = *p; p += 2; - bar->size = cis_get_u32(p); + bar->size = le32_to_cpu(*(__le32 *)p); return CS_SUCCESS; } @@ -1159,7 +1151,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config) return CS_BAD_TUPLE; config->last_idx = *(++p); p++; - config->base = cis_get_u32(p); + config->base = le32_to_cpu(*(__le32 *)p); config->subtuples = tuple->TupleDataLen - 6; return CS_SUCCESS; } @@ -1275,7 +1267,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2) v2->vers = p[0]; v2->comply = p[1]; - v2->dindex = cis_get_u16(p +2 ); + v2->dindex = le16_to_cpu(*(__le16 *)(p+2)); v2->vspec8 = p[6]; v2->vspec9 = p[7]; v2->nhdr = p[8]; @@ -1316,8 +1308,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt) fmt->type = p[0]; fmt->edc = p[1]; - fmt->offset = cis_get_u32(p + 2); - fmt->length = cis_get_u32(p + 6); + fmt->offset = le32_to_cpu(*(__le32 *)(p+2)); + fmt->length = le32_to_cpu(*(__le32 *)(p+6)); return CS_SUCCESS; } diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c index 7bf78c127898..55baa1f0fcbb 100644 --- a/trunk/drivers/pcmcia/ds.c +++ b/trunk/drivers/pcmcia/ds.c @@ -23,7 +23,6 @@ #include #include #include -#include #define IN_CARD_SERVICES #include @@ -671,9 +670,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->dev.parent; p_dev->dev.release = pcmcia_release_dev; - /* by default don't allow DMA */ - p_dev->dma_mask = DMA_MASK_NONE; - p_dev->dev.dma_mask = &p_dev->dma_mask; bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL); diff --git a/trunk/drivers/pcmcia/pxa2xx_base.c b/trunk/drivers/pcmcia/pxa2xx_base.c index 874923fcb2f9..dca9f8549b32 100644 --- a/trunk/drivers/pcmcia/pxa2xx_base.c +++ b/trunk/drivers/pcmcia/pxa2xx_base.c @@ -58,7 +58,7 @@ static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns, u_int mem_clk_10khz) { u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 300000) + ((code % 300000) ? 1 : 0) + 1; + return (code / 300000) + ((code % 300000) ? 1 : 0) - 1; } static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns, diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c index e0ee28a88da3..a0cfb75bbb8d 100644 --- a/trunk/drivers/pnp/interface.c +++ b/trunk/drivers/pnp/interface.c @@ -1,7 +1,7 @@ /* * interface.c - contains everything related to the user interface * - * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela + * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela * Copyright 2002 Adam Belay */ diff --git a/trunk/drivers/pnp/isapnp/core.c b/trunk/drivers/pnp/isapnp/core.c index 2c925b7cd93e..b035d60a1dcc 100644 --- a/trunk/drivers/pnp/isapnp/core.c +++ b/trunk/drivers/pnp/isapnp/core.c @@ -1,6 +1,6 @@ /* * ISA Plug & Play support - * Copyright (c) by Jaroslav Kysela + * Copyright (c) by Jaroslav Kysela * * * This program is free software; you can redistribute it and/or modify @@ -53,7 +53,7 @@ static int isapnp_rdp; /* Read Data Port */ static int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ static int isapnp_verbose = 1; /* verbose mode */ -MODULE_AUTHOR("Jaroslav Kysela "); +MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Generic ISA Plug & Play support"); module_param(isapnp_disable, int, 0); MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable"); diff --git a/trunk/drivers/pnp/isapnp/proc.c b/trunk/drivers/pnp/isapnp/proc.c index 2b8266c3d40f..560ccb640816 100644 --- a/trunk/drivers/pnp/isapnp/proc.c +++ b/trunk/drivers/pnp/isapnp/proc.c @@ -1,6 +1,6 @@ /* * ISA Plug & Play support - * Copyright (c) by Jaroslav Kysela + * Copyright (c) by Jaroslav Kysela * * 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 diff --git a/trunk/drivers/pnp/manager.c b/trunk/drivers/pnp/manager.c index ea3eac2404ca..0826287eef53 100644 --- a/trunk/drivers/pnp/manager.c +++ b/trunk/drivers/pnp/manager.c @@ -1,7 +1,7 @@ /* * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices * - * based on isapnp.c resource management (c) Jaroslav Kysela + * based on isapnp.c resource management (c) Jaroslav Kysela * Copyright 2003 Adam Belay */ diff --git a/trunk/drivers/pnp/resource.c b/trunk/drivers/pnp/resource.c index 087fed18628f..ef1286900db3 100644 --- a/trunk/drivers/pnp/resource.c +++ b/trunk/drivers/pnp/resource.c @@ -1,7 +1,7 @@ /* * resource.c - Contains functions for registering and analyzing resource information * - * based on isapnp.c resource management (c) Jaroslav Kysela + * based on isapnp.c resource management (c) Jaroslav Kysela * Copyright 2003 Adam Belay */ diff --git a/trunk/drivers/ps3/ps3av.c b/trunk/drivers/ps3/ps3av.c index 397f4ce849dc..85e21614f868 100644 --- a/trunk/drivers/ps3/ps3av.c +++ b/trunk/drivers/ps3/ps3av.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -34,8 +33,6 @@ #define BUFSIZE 4096 /* vuart buf size */ #define PS3AV_BUF_SIZE 512 /* max packet size */ -static int safe_mode; - static int timeout = 5000; /* in msec ( 5 sec ) */ module_param(timeout, int, 0644); @@ -494,10 +491,10 @@ static int ps3av_set_videomode(void) return 0; } -static void ps3av_set_videomode_packet(u32 id) +static void ps3av_set_videomode_cont(u32 id, u32 old_id) { struct ps3av_pkt_avb_param avb_param; - unsigned int i; + int i; u32 len = 0, av_video_cs; const struct avset_video_mode *video_mode; int res; @@ -510,6 +507,24 @@ static void ps3av_set_videomode_packet(u32 id) ps3av->av_hw_conf.num_of_avmulti; avb_param.num_of_av_audio_pkt = 0; + /* video signal off */ + ps3av_set_video_disable_sig(); + + /* Retail PS3 product doesn't support this */ + if (id & PS3AV_MODE_HDCP_OFF) { + res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); + if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) + dev_dbg(&ps3av->dev->core, "Not supported\n"); + else if (res) + dev_dbg(&ps3av->dev->core, + "ps3av_cmd_av_hdmi_mode failed\n"); + } else if (old_id & PS3AV_MODE_HDCP_OFF) { + res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); + if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) + dev_dbg(&ps3av->dev->core, + "ps3av_cmd_av_hdmi_mode failed\n"); + } + /* video_pkt */ for (i = 0; i < avb_param.num_of_video_pkt; i++) len += ps3av_cmd_set_video_mode(&avb_param.buf[len], @@ -540,42 +555,6 @@ static void ps3av_set_videomode_packet(u32 id) __func__); else if (res) dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); -} - -static void ps3av_set_videomode_cont(u32 id, u32 old_id) -{ - static int vesa = 0; - int res; - - /* video signal off */ - ps3av_set_video_disable_sig(); - - /* - * AV backend needs non-VESA mode setting at least one time - * when VESA mode is used. - */ - if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) { - /* vesa mode */ - ps3av_set_videomode_packet(2); /* 480P */ - } - vesa = 1; - - /* Retail PS3 product doesn't support this */ - if (id & PS3AV_MODE_HDCP_OFF) { - res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); - if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) - dev_dbg(&ps3av->dev->core, "Not supported\n"); - else if (res) - dev_dbg(&ps3av->dev->core, - "ps3av_cmd_av_hdmi_mode failed\n"); - } else if (old_id & PS3AV_MODE_HDCP_OFF) { - res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); - if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) - dev_dbg(&ps3av->dev->core, - "ps3av_cmd_av_hdmi_mode failed\n"); - } - - ps3av_set_videomode_packet(id); msleep(1500); /* av video mute */ @@ -588,251 +567,165 @@ static void ps3avd(struct work_struct *work) complete(&ps3av->done); } -#define SHIFT_50 0 -#define SHIFT_60 4 -#define SHIFT_VESA 8 - -static const struct { - unsigned mask : 19; - unsigned id : 4; -} ps3av_preferred_modes[] = { - { .mask = PS3AV_RESBIT_WUXGA << SHIFT_VESA, .id = 13 }, - { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_60, .id = 5 }, - { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_50, .id = 10 }, - { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_60, .id = 4 }, - { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_50, .id = 9 }, - { .mask = PS3AV_RESBIT_SXGA << SHIFT_VESA, .id = 12 }, - { .mask = PS3AV_RESBIT_WXGA << SHIFT_VESA, .id = 11 }, - { .mask = PS3AV_RESBIT_1280x720P << SHIFT_60, .id = 3 }, - { .mask = PS3AV_RESBIT_1280x720P << SHIFT_50, .id = 8 }, - { .mask = PS3AV_RESBIT_720x480P << SHIFT_60, .id = 2 }, - { .mask = PS3AV_RESBIT_720x576P << SHIFT_50, .id = 7 }, -}; - -static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) +static int ps3av_vid2table_id(int vid) { - unsigned int i; - u32 res_all; - - /* - * We mask off the resolution bits we care about and combine the - * results in one bitfield, so make sure there's no overlap - */ - BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & - PS3AV_RES_MASK_60 << SHIFT_60); - BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & - PS3AV_RES_MASK_VESA << SHIFT_VESA); - BUILD_BUG_ON(PS3AV_RES_MASK_60 << SHIFT_60 & - PS3AV_RES_MASK_VESA << SHIFT_VESA); - res_all = (res_50 & PS3AV_RES_MASK_50) << SHIFT_50 | - (res_60 & PS3AV_RES_MASK_60) << SHIFT_60 | - (res_vesa & PS3AV_RES_MASK_VESA) << SHIFT_VESA; - - if (!res_all) - return 0; - - for (i = 0; i < ARRAY_SIZE(ps3av_preferred_modes); i++) - if (res_all & ps3av_preferred_modes[i].mask) - return ps3av_preferred_modes[i].id; + int i; - return 0; + for (i = 1; i < ARRAY_SIZE(video_mode_table); i++) + if (video_mode_table[i].vid == vid) + return i; + return -1; } -static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info) +static int ps3av_resbit2vid(u32 res_50, u32 res_60) { - int id; - - if (safe_mode) - return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; + int vid = -1; - /* check native resolution */ - id = ps3av_resbit2id(info->res_50.native, info->res_60.native, - info->res_vesa.native); - if (id) { - pr_debug("%s: Using native mode %d\n", __func__, id); - return id; - } - - /* check supported resolutions */ - id = ps3av_resbit2id(info->res_50.res_bits, info->res_60.res_bits, - info->res_vesa.res_bits); - if (id) { - pr_debug("%s: Using supported mode %d\n", __func__, id); - return id; + if (res_50 > res_60) { /* if res_50 == res_60, res_60 will be used */ + if (res_50 & PS3AV_RESBIT_1920x1080P) + vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ; + else if (res_50 & PS3AV_RESBIT_1920x1080I) + vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ; + else if (res_50 & PS3AV_RESBIT_1280x720P) + vid = PS3AV_CMD_VIDEO_VID_720P_50HZ; + else if (res_50 & PS3AV_RESBIT_720x576P) + vid = PS3AV_CMD_VIDEO_VID_576P; + else + vid = -1; + } else { + if (res_60 & PS3AV_RESBIT_1920x1080P) + vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ; + else if (res_60 & PS3AV_RESBIT_1920x1080I) + vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ; + else if (res_60 & PS3AV_RESBIT_1280x720P) + vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; + else if (res_60 & PS3AV_RESBIT_720x480P) + vid = PS3AV_CMD_VIDEO_VID_480P; + else + vid = -1; } - - if (ps3av->region & PS3AV_REGION_60) - id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; - else - id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_50; - pr_debug("%s: Using default mode %d\n", __func__, id); - return id; + return vid; } -static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) +static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info) { - const struct ps3av_info_monitor *info = &monitor_info->info; - const struct ps3av_info_audio *audio = info->audio; - char id[sizeof(info->monitor_id)*3+1]; - int i; + u32 res_50, res_60; + int vid = -1; - pr_debug("Monitor Info: size %u\n", monitor_info->send_hdr.size); - - pr_debug("avport: %02x\n", info->avport); - for (i = 0; i < sizeof(info->monitor_id); i++) - sprintf(&id[i*3], " %02x", info->monitor_id[i]); - pr_debug("monitor_id: %s\n", id); - pr_debug("monitor_type: %02x\n", info->monitor_type); - pr_debug("monitor_name: %.*s\n", (int)sizeof(info->monitor_name), - info->monitor_name); - - /* resolution */ - pr_debug("resolution_60: bits: %08x native: %08x\n", - info->res_60.res_bits, info->res_60.native); - pr_debug("resolution_50: bits: %08x native: %08x\n", - info->res_50.res_bits, info->res_50.native); - pr_debug("resolution_other: bits: %08x native: %08x\n", - info->res_other.res_bits, info->res_other.native); - pr_debug("resolution_vesa: bits: %08x native: %08x\n", - info->res_vesa.res_bits, info->res_vesa.native); - - /* color space */ - pr_debug("color space rgb: %02x\n", info->cs.rgb); - pr_debug("color space yuv444: %02x\n", info->cs.yuv444); - pr_debug("color space yuv422: %02x\n", info->cs.yuv422); - - /* color info */ - pr_debug("color info red: X %04x Y %04x\n", info->color.red_x, - info->color.red_y); - pr_debug("color info green: X %04x Y %04x\n", info->color.green_x, - info->color.green_y); - pr_debug("color info blue: X %04x Y %04x\n", info->color.blue_x, - info->color.blue_y); - pr_debug("color info white: X %04x Y %04x\n", info->color.white_x, - info->color.white_y); - pr_debug("color info gamma: %08x\n", info->color.gamma); - - /* other info */ - pr_debug("supported_AI: %02x\n", info->supported_ai); - pr_debug("speaker_info: %02x\n", info->speaker_info); - pr_debug("num of audio: %02x\n", info->num_of_audio_block); - - /* audio block */ - for (i = 0; i < info->num_of_audio_block; i++) { - pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " - "%02x\n", - i, audio->type, audio->max_num_of_ch, audio->fs, - audio->sbit); - audio++; - } -} + if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI) + return -1; -static const struct ps3av_monitor_quirk { - const char *monitor_name; - u32 clear_60, clear_50, clear_vesa; -} ps3av_monitor_quirks[] = { - { - .monitor_name = "DELL 2007WFP", - .clear_60 = PS3AV_RESBIT_1920x1080I - }, { - .monitor_name = "L226WTQ", - .clear_60 = PS3AV_RESBIT_1920x1080I | - PS3AV_RESBIT_1920x1080P - }, { - .monitor_name = "SyncMaster", - .clear_60 = PS3AV_RESBIT_1920x1080I + /* check native resolution */ + res_50 = info->res_50.native & PS3AV_RES_MASK_50; + res_60 = info->res_60.native & PS3AV_RES_MASK_60; + if (res_50 || res_60) { + vid = ps3av_resbit2vid(res_50, res_60); + return vid; } -}; -static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info) -{ - unsigned int i; - const struct ps3av_monitor_quirk *quirk; - - for (i = 0; i < ARRAY_SIZE(ps3av_monitor_quirks); i++) { - quirk = &ps3av_monitor_quirks[i]; - if (!strncmp(info->monitor_name, quirk->monitor_name, - sizeof(info->monitor_name))) { - pr_info("%s: Applying quirk for %s\n", __func__, - quirk->monitor_name); - info->res_60.res_bits &= ~quirk->clear_60; - info->res_60.native &= ~quirk->clear_60; - info->res_50.res_bits &= ~quirk->clear_50; - info->res_50.native &= ~quirk->clear_50; - info->res_vesa.res_bits &= ~quirk->clear_vesa; - info->res_vesa.native &= ~quirk->clear_vesa; - break; - } + /* check resolution */ + res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50; + res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60; + if (res_50 || res_60) { + vid = ps3av_resbit2vid(res_50, res_60); + return vid; } + + if (ps3av->region & PS3AV_REGION_60) + vid = PS3AV_DEFAULT_HDMI_VID_REG_60; + else + vid = PS3AV_DEFAULT_HDMI_VID_REG_50; + return vid; } -static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf) +static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf, + int boot) { - int i, res, id = 0, dvi = 0, rgb = 0; + int i, res, vid = -1, dvi = 0, rgb = 0; struct ps3av_pkt_av_get_monitor_info monitor_info; struct ps3av_info_monitor *info; - /* get mode id for hdmi */ - for (i = 0; i < av_hw_conf->num_of_hdmi && !id; i++) { + /* get vid for hdmi */ + for (i = 0; i < av_hw_conf->num_of_hdmi; i++) { res = ps3av_cmd_video_get_monitor_info(&monitor_info, PS3AV_CMD_AVPORT_HDMI_0 + i); if (res < 0) return -1; - ps3av_monitor_info_dump(&monitor_info); - + ps3av_cmd_av_monitor_info_dump(&monitor_info); info = &monitor_info.info; - ps3av_fixup_monitor_info(info); - - switch (info->monitor_type) { - case PS3AV_MONITOR_TYPE_DVI: + /* check DVI */ + if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) { dvi = PS3AV_MODE_DVI; - /* fall through */ - case PS3AV_MONITOR_TYPE_HDMI: - id = ps3av_hdmi_get_id(info); + break; + } + /* check HDMI */ + vid = ps3av_hdmi_get_vid(info); + if (vid != -1) { + /* got valid vid */ break; } } - if (!id) { + if (dvi) { + /* DVI mode */ + vid = PS3AV_DEFAULT_DVI_VID; + } else if (vid == -1) { /* no HDMI interface or HDMI is off */ if (ps3av->region & PS3AV_REGION_60) - id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60; + vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; else - id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50; + vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; if (ps3av->region & PS3AV_REGION_RGB) rgb = PS3AV_MODE_RGB; - pr_debug("%s: Using avmulti mode %d\n", __func__, id); + } else if (boot) { + /* HDMI: using DEFAULT HDMI_VID while booting up */ + info = &monitor_info.info; + if (ps3av->region & PS3AV_REGION_60) { + if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) + vid = PS3AV_DEFAULT_HDMI_VID_REG_60; + else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) + vid = PS3AV_DEFAULT_HDMI_VID_REG_50; + else { + /* default */ + vid = PS3AV_DEFAULT_HDMI_VID_REG_60; + } + } else { + if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) + vid = PS3AV_DEFAULT_HDMI_VID_REG_50; + else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) + vid = PS3AV_DEFAULT_HDMI_VID_REG_60; + else { + /* default */ + vid = PS3AV_DEFAULT_HDMI_VID_REG_50; + } + } } - return id | dvi | rgb; + return (ps3av_vid2table_id(vid) | dvi | rgb); } static int ps3av_get_hw_conf(struct ps3av *ps3av) { int i, j, k, res; - const struct ps3av_pkt_av_get_hw_conf *hw_conf; /* get av_hw_conf */ res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf); if (res < 0) return -1; - hw_conf = &ps3av->av_hw_conf; - pr_debug("av_h_conf: num of hdmi: %u\n", hw_conf->num_of_hdmi); - pr_debug("av_h_conf: num of avmulti: %u\n", hw_conf->num_of_avmulti); - pr_debug("av_h_conf: num of spdif: %u\n", hw_conf->num_of_spdif); + ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf); for (i = 0; i < PS3AV_HEAD_MAX; i++) ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i; for (i = 0; i < PS3AV_OPT_PORT_MAX; i++) ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i; - for (i = 0; i < hw_conf->num_of_hdmi; i++) + for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++) ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i; - for (j = 0; j < hw_conf->num_of_avmulti; j++) + for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++) ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j; - for (k = 0; k < hw_conf->num_of_spdif; k++) + for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++) ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k; /* set all audio port */ @@ -845,7 +738,7 @@ static int ps3av_get_hw_conf(struct ps3av *ps3av) } /* set mode using id */ -int ps3av_set_video_mode(u32 id) +int ps3av_set_video_mode(u32 id, int boot) { int size; u32 option; @@ -859,7 +752,7 @@ int ps3av_set_video_mode(u32 id) /* auto mode */ option = id & ~PS3AV_MODE_MASK; if ((id & PS3AV_MODE_MASK) == 0) { - id = ps3av_auto_videomode(&ps3av->av_hw_conf); + id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot); if (id < 1) { printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); return -EINVAL; @@ -879,13 +772,34 @@ int ps3av_set_video_mode(u32 id) EXPORT_SYMBOL_GPL(ps3av_set_video_mode); -int ps3av_get_auto_mode(void) +int ps3av_get_auto_mode(int boot) { - return ps3av_auto_videomode(&ps3av->av_hw_conf); + return ps3av_auto_videomode(&ps3av->av_hw_conf, boot); } EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); +int ps3av_set_mode(u32 id, int boot) +{ + int res; + + res = ps3av_set_video_mode(id, boot); + if (res) + return res; + + res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2, + PS3AV_CMD_AUDIO_FS_48K, + PS3AV_CMD_AUDIO_WORD_BITS_16, + PS3AV_CMD_AUDIO_FORMAT_PCM, + PS3AV_CMD_AUDIO_SOURCE_SERIAL); + if (res) + return res; + + return 0; +} + +EXPORT_SYMBOL_GPL(ps3av_set_mode); + int ps3av_get_mode(void) { return ps3av ? ps3av->ps3av_mode : 0; @@ -1027,14 +941,7 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) res); ps3av_get_hw_conf(ps3av); - -#ifdef CONFIG_FB - if (fb_mode_option && !strcmp(fb_mode_option, "safe")) - safe_mode = 1; -#endif /* CONFIG_FB */ - id = ps3av_auto_videomode(&ps3av->av_hw_conf); - safe_mode = 0; - + id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1); mutex_lock(&ps3av->mutex); ps3av->ps3av_mode = id; mutex_unlock(&ps3av->mutex); diff --git a/trunk/drivers/ps3/ps3av_cmd.c b/trunk/drivers/ps3/ps3av_cmd.c index 7f880c26122f..f72f5ddf18e4 100644 --- a/trunk/drivers/ps3/ps3av_cmd.c +++ b/trunk/drivers/ps3/ps3av_cmd.c @@ -512,6 +512,7 @@ static const u32 ps3av_ns_table[][5] = { static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) { u32 av_vid, ns_val; + u8 *p = ns; int d; d = ns_val = 0; @@ -550,22 +551,24 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) else ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d]; - *ns++ = ns_val & 0x000000FF; - *ns++ = (ns_val & 0x0000FF00) >> 8; - *ns = (ns_val & 0x00FF0000) >> 16; + *p++ = ns_val & 0x000000FF; + *p++ = (ns_val & 0x0000FF00) >> 8; + *p = (ns_val & 0x00FF0000) >> 16; } #undef BASE static u8 ps3av_cnv_enable(u32 source, const u8 *enable) { + const u8 *p; u8 ret = 0; if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) { ret = 0x03; } else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) { - ret = ((enable[0] << 4) + (enable[1] << 5) + (enable[2] << 6) + - (enable[3] << 7)) | 0x01; + p = enable; + ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) | + 0x01; } else printk(KERN_ERR "%s failed, source:%x\n", __func__, source); return ret; @@ -573,9 +576,11 @@ static u8 ps3av_cnv_enable(u32 source, const u8 *enable) static u8 ps3av_cnv_fifomap(const u8 *map) { + const u8 *p; u8 ret = 0; - ret = map[0] + (map[1] << 2) + (map[2] << 4) + (map[3] << 6); + p = map; + ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6); return ret; } @@ -922,6 +927,72 @@ int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info, return res; } +#ifdef PS3AV_DEBUG +void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf) +{ + printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi); + printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti); + printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif); +} + +void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) +{ + const struct ps3av_info_monitor *info = &monitor_info->info; + const struct ps3av_info_audio *audio = info->audio; + int i; + + printk("Monitor Info: size%d\n", monitor_info->send_hdr.size); + + printk("avport:%02x\n", info->avport); + printk("monitor_id:"); + for (i = 0; i < 10; i++) + printk("%02x ", info->monitor_id[i]); + printk("\nmonitor_type:%02x\n", info->monitor_type); + printk("monitor_name:"); + for (i = 0; i < 16; i++) + printk("%c", info->monitor_name[i]); + + /* resolution */ + printk("\nresolution_60: bits:%08x native:%08x\n", + info->res_60.res_bits, info->res_60.native); + printk("resolution_50: bits:%08x native:%08x\n", + info->res_50.res_bits, info->res_50.native); + printk("resolution_other: bits:%08x native:%08x\n", + info->res_other.res_bits, info->res_other.native); + printk("resolution_vesa: bits:%08x native:%08x\n", + info->res_vesa.res_bits, info->res_vesa.native); + + /* color space */ + printk("color space rgb:%02x\n", info->cs.rgb); + printk("color space yuv444:%02x\n", info->cs.yuv444); + printk("color space yuv422:%02x\n", info->cs.yuv422); + + /* color info */ + printk("color info red:X %04x Y %04x\n", + info->color.red_x, info->color.red_y); + printk("color info green:X %04x Y %04x\n", + info->color.green_x, info->color.green_y); + printk("color info blue:X %04x Y %04x\n", + info->color.blue_x, info->color.blue_y); + printk("color info white:X %04x Y %04x\n", + info->color.white_x, info->color.white_y); + printk("color info gamma: %08x\n", info->color.gamma); + + /* other info */ + printk("supported_AI:%02x\n", info->supported_ai); + printk("speaker_info:%02x\n", info->speaker_info); + printk("num of audio:%02x\n", info->num_of_audio_block); + + /* audio block */ + for (i = 0; i < info->num_of_audio_block; i++) { + printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n", + i, audio->type, audio->max_num_of_ch, audio->fs, + audio->sbit); + audio++; + } +} +#endif /* PS3AV_DEBUG */ + #define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \ | PS3AV_CMD_AV_LAYOUT_44 \ | PS3AV_CMD_AV_LAYOUT_48) diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 6420a90a4a92..ff9e35cb308d 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -139,17 +139,6 @@ config RTC_DRV_DS1307 This driver can also be built as a module. If so, the module will be called rtc-ds1307. -config RTC_DRV_DS1374 - tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" - depends on RTC_CLASS && I2C - help - If you say yes here you get support for Dallas Semiconductor - DS1374 real-time clock chips. If an interrupt is associated - with the device, the alarm functionality is supported. - - This driver can also be built as a module. If so, the module - will be called rtc-ds1374. - config RTC_DRV_DS1672 tristate "Dallas/Maxim DS1672" help diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index 465db4dd50b2..d3a33aa2696f 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o -obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o diff --git a/trunk/drivers/rtc/class.c b/trunk/drivers/rtc/class.c index 4dfdf019fccc..10ab3b71ffc6 100644 --- a/trunk/drivers/rtc/class.c +++ b/trunk/drivers/rtc/class.c @@ -153,7 +153,6 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, mutex_init(&rtc->ops_lock); spin_lock_init(&rtc->irq_lock); spin_lock_init(&rtc->irq_task_lock); - init_waitqueue_head(&rtc->irq_queue); strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id); diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index de0da545c7a1..ad66c6ecf365 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -12,7 +12,6 @@ */ #include -#include int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) { @@ -100,7 +99,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) } EXPORT_SYMBOL_GPL(rtc_set_mmss); -static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; @@ -120,87 +119,6 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al mutex_unlock(&rtc->ops_lock); return err; } - -int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) -{ - int err; - struct rtc_time before, now; - int first_time = 1; - - /* The lower level RTC driver may not be capable of filling - * in all fields of the rtc_time struct (eg. rtc-cmos), - * and so might instead return -1 in some fields. - * We deal with that here by grabbing a current RTC timestamp - * and using values from that for any missing (-1) values. - * - * But this can be racey, because some fields of the RTC timestamp - * may have wrapped in the interval since we read the RTC alarm, - * which would lead to us inserting inconsistent values in place - * of the -1 fields. - * - * Reading the alarm and timestamp in the reverse sequence - * would have the same race condition, and not solve the issue. - * - * So, we must first read the RTC timestamp, - * then read the RTC alarm value, - * and then read a second RTC timestamp. - * - * If any fields of the second timestamp have changed - * when compared with the first timestamp, then we know - * our timestamp may be inconsistent with that used by - * the low-level rtc_read_alarm_internal() function. - * - * So, when the two timestamps disagree, we just loop and do - * the process again to get a fully consistent set of values. - * - * This could all instead be done in the lower level driver, - * but since more than one lower level RTC implementation needs it, - * then it's probably best best to do it here instead of there.. - */ - - /* Get the "before" timestamp */ - err = rtc_read_time(rtc, &before); - if (err < 0) - return err; - do { - if (!first_time) - memcpy(&before, &now, sizeof(struct rtc_time)); - first_time = 0; - - /* get the RTC alarm values, which may be incomplete */ - err = rtc_read_alarm_internal(rtc, alarm); - if (err) - return err; - if (!alarm->enabled) - return 0; - - /* get the "after" timestamp, to detect wrapped fields */ - err = rtc_read_time(rtc, &now); - if (err < 0) - return err; - - /* note that tm_sec is a "don't care" value here: */ - } while ( before.tm_min != now.tm_min - || before.tm_hour != now.tm_hour - || before.tm_mon != now.tm_mon - || before.tm_year != now.tm_year - || before.tm_isdst != now.tm_isdst); - - /* Fill in any missing alarm fields using the timestamp */ - if (alarm->time.tm_sec == -1) - alarm->time.tm_sec = now.tm_sec; - if (alarm->time.tm_min == -1) - alarm->time.tm_min = now.tm_min; - if (alarm->time.tm_hour == -1) - alarm->time.tm_hour = now.tm_hour; - if (alarm->time.tm_mday == -1) - alarm->time.tm_mday = now.tm_mday; - if (alarm->time.tm_mon == -1) - alarm->time.tm_mon = now.tm_mon; - if (alarm->time.tm_year == -1) - alarm->time.tm_year = now.tm_year; - return 0; -} EXPORT_SYMBOL_GPL(rtc_read_alarm); int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -292,10 +210,6 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) if (task == NULL || task->func == NULL) return -EINVAL; - /* Cannot register while the char dev is in use */ - if (!(mutex_trylock(&rtc->char_lock))) - return -EBUSY; - spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == NULL) { rtc->irq_task = task; @@ -303,14 +217,13 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) } spin_unlock_irq(&rtc->irq_task_lock); - mutex_unlock(&rtc->char_lock); - return retval; } EXPORT_SYMBOL_GPL(rtc_irq_register); void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) { + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == task) rtc->irq_task = NULL; @@ -318,16 +231,6 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) } EXPORT_SYMBOL_GPL(rtc_irq_unregister); -/** - * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs - * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() - * @enabled: true to enable periodic IRQs - * Context: any - * - * Note that rtc_irq_set_freq() should previously have been used to - * specify the desired frequency of periodic IRQ task->func() callbacks. - */ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) { int err = 0; @@ -337,10 +240,8 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled return -ENXIO; spin_lock_irqsave(&rtc->irq_task_lock, flags); - if (rtc->irq_task != NULL && task == NULL) - err = -EBUSY; if (rtc->irq_task != task) - err = -EACCES; + err = -ENXIO; spin_unlock_irqrestore(&rtc->irq_task_lock, flags); if (err == 0) @@ -350,16 +251,6 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled } EXPORT_SYMBOL_GPL(rtc_irq_set_state); -/** - * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ - * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() - * @freq: positive frequency with which task->func() will be called - * Context: any - * - * Note that rtc_irq_set_state() is used to enable or disable the - * periodic IRQs. - */ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) { int err = 0; @@ -368,14 +259,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) if (rtc->ops->irq_set_freq == NULL) return -ENXIO; - if (!is_power_of_2(freq)) - return -EINVAL; - spin_lock_irqsave(&rtc->irq_task_lock, flags); - if (rtc->irq_task != NULL && task == NULL) - err = -EBUSY; if (rtc->irq_task != task) - err = -EACCES; + err = -ENXIO; spin_unlock_irqrestore(&rtc->irq_task_lock, flags); if (err == 0) { diff --git a/trunk/drivers/rtc/rtc-cmos.c b/trunk/drivers/rtc/rtc-cmos.c index e3fe83a23cf7..5d760bb6c2cd 100644 --- a/trunk/drivers/rtc/rtc-cmos.c +++ b/trunk/drivers/rtc/rtc-cmos.c @@ -246,9 +246,11 @@ static int cmos_irq_set_freq(struct device *dev, int freq) /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ f = ffs(freq); - if (f-- > 16) - return -EINVAL; - f = 16 - f; + if (f != 0) { + if (f-- > 16 || freq != (1 << f)) + return -EINVAL; + f = 16 - f; + } spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); @@ -433,19 +435,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) if (!ports) return -ENODEV; - /* Claim I/O ports ASAP, minimizing conflict with legacy driver. - * - * REVISIT non-x86 systems may instead use memory space resources - * (needing ioremap etc), not i/o space resources like this ... - */ - ports = request_region(ports->start, - ports->end + 1 - ports->start, - driver_name); - if (!ports) { - dev_dbg(dev, "i/o registers already in use\n"); - return -EBUSY; - } - cmos_rtc.irq = rtc_irq; cmos_rtc.iomem = ports; @@ -467,13 +456,24 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) cmos_rtc.rtc = rtc_device_register(driver_name, dev, &cmos_rtc_ops, THIS_MODULE); - if (IS_ERR(cmos_rtc.rtc)) { - retval = PTR_ERR(cmos_rtc.rtc); - goto cleanup0; - } + if (IS_ERR(cmos_rtc.rtc)) + return PTR_ERR(cmos_rtc.rtc); cmos_rtc.dev = dev; dev_set_drvdata(dev, &cmos_rtc); + + /* platform and pnp busses handle resources incompatibly. + * + * REVISIT for non-x86 systems we may need to handle io memory + * resources: ioremap them, and request_mem_region(). + */ + if (is_pnp()) { + retval = request_resource(&ioport_resource, ports); + if (retval < 0) { + dev_dbg(dev, "i/o registers already in use\n"); + goto cleanup0; + } + } rename_region(ports, cmos_rtc.rtc->dev.bus_id); spin_lock_irq(&rtc_lock); @@ -536,10 +536,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) return 0; cleanup1: - cmos_rtc.dev = NULL; - rtc_device_unregister(cmos_rtc.rtc); + rename_region(ports, NULL); cleanup0: - release_region(ports->start, ports->end + 1 - ports->start); + rtc_device_unregister(cmos_rtc.rtc); return retval; } @@ -558,21 +557,19 @@ static void cmos_do_shutdown(void) static void __exit cmos_do_remove(struct device *dev) { struct cmos_rtc *cmos = dev_get_drvdata(dev); - struct resource *ports; cmos_do_shutdown(); - if (is_valid_irq(cmos->irq)) - free_irq(cmos->irq, cmos->rtc); + if (is_pnp()) + release_resource(cmos->iomem); + rename_region(cmos->iomem, NULL); - rtc_device_unregister(cmos->rtc); - cmos->rtc = NULL; + if (is_valid_irq(cmos->irq)) + free_irq(cmos->irq, cmos_rtc.rtc); - ports = cmos->iomem; - release_region(ports->start, ports->end + 1 - ports->start); - cmos->iomem = NULL; + rtc_device_unregister(cmos_rtc.rtc); - cmos->dev = NULL; + cmos_rtc.dev = NULL; dev_set_drvdata(dev, NULL); } @@ -659,8 +656,7 @@ static int cmos_resume(struct device *dev) /*----------------------------------------------------------------*/ /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, - * the device node will always be created as a PNPACPI device. Plus - * pre-ACPI PCs probably list it in the PNPBIOS tables. + * the device node will always be created as a PNPACPI device. */ #ifdef CONFIG_PNP diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 814583bd2fe7..005fff3a3508 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -142,7 +142,7 @@ static int set_uie(struct rtc_device *rtc) static ssize_t rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct rtc_device *rtc = file->private_data; + struct rtc_device *rtc = to_rtc_device(file->private_data); DECLARE_WAITQUEUE(wait, current); unsigned long data; @@ -196,7 +196,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) { - struct rtc_device *rtc = file->private_data; + struct rtc_device *rtc = to_rtc_device(file->private_data); unsigned long data; poll_wait(file, &rtc->irq_queue, wait); @@ -233,12 +233,22 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, break; case RTC_PIE_ON: - if (rtc->irq_freq > rtc->max_user_freq && - !capable(CAP_SYS_RESOURCE)) + if (!capable(CAP_SYS_RESOURCE)) return -EACCES; break; } + /* avoid conflicting IRQ users */ + if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { + spin_lock_irq(&rtc->irq_task_lock); + if (rtc->irq_task) + err = -EBUSY; + spin_unlock_irq(&rtc->irq_task_lock); + + if (err < 0) + return err; + } + /* try the driver's ioctl interface */ if (ops->ioctl) { err = ops->ioctl(rtc->dev.parent, cmd, arg); @@ -328,20 +338,18 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, err = rtc_set_time(rtc, &tm); break; - case RTC_PIE_ON: - err = rtc_irq_set_state(rtc, NULL, 1); - break; - - case RTC_PIE_OFF: - err = rtc_irq_set_state(rtc, NULL, 0); + case RTC_IRQP_READ: + if (ops->irq_set_freq) + err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); + else + err = -ENOTTY; break; case RTC_IRQP_SET: - err = rtc_irq_set_freq(rtc, NULL, arg); - break; - - case RTC_IRQP_READ: - err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); + if (ops->irq_set_freq) + err = rtc_irq_set_freq(rtc, rtc->irq_task, arg); + else + err = -ENOTTY; break; #if 0 @@ -397,7 +405,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, static int rtc_dev_release(struct inode *inode, struct file *file) { - struct rtc_device *rtc = file->private_data; + struct rtc_device *rtc = to_rtc_device(file->private_data); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL clear_uie(rtc); @@ -411,7 +419,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) static int rtc_dev_fasync(int fd, struct file *file, int on) { - struct rtc_device *rtc = file->private_data; + struct rtc_device *rtc = to_rtc_device(file->private_data); return fasync_helper(fd, file, on, &rtc->async_queue); } @@ -441,6 +449,8 @@ void rtc_dev_prepare(struct rtc_device *rtc) rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); mutex_init(&rtc->char_lock); + spin_lock_init(&rtc->irq_lock); + init_waitqueue_head(&rtc->irq_queue); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); diff --git a/trunk/drivers/rtc/rtc-ds1374.c b/trunk/drivers/rtc/rtc-ds1374.c deleted file mode 100644 index 45bda186befc..000000000000 --- a/trunk/drivers/rtc/rtc-ds1374.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * RTC client/driver for the Maxim/Dallas DS1374 Real-Time Clock over I2C - * - * Based on code by Randy Vinson , - * which was based on the m41t00.c by Mark Greer . - * - * Copyright (C) 2006-2007 Freescale Semiconductor - * - * 2005 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -/* - * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section - * "Sending and receiving", using SMBus level communication is preferred. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DS1374_REG_TOD0 0x00 /* Time of Day */ -#define DS1374_REG_TOD1 0x01 -#define DS1374_REG_TOD2 0x02 -#define DS1374_REG_TOD3 0x03 -#define DS1374_REG_WDALM0 0x04 /* Watchdog/Alarm */ -#define DS1374_REG_WDALM1 0x05 -#define DS1374_REG_WDALM2 0x06 -#define DS1374_REG_CR 0x07 /* Control */ -#define DS1374_REG_CR_AIE 0x01 /* Alarm Int. Enable */ -#define DS1374_REG_CR_WDALM 0x20 /* 1=Watchdog, 0=Alarm */ -#define DS1374_REG_CR_WACE 0x40 /* WD/Alarm counter enable */ -#define DS1374_REG_SR 0x08 /* Status */ -#define DS1374_REG_SR_OSF 0x80 /* Oscillator Stop Flag */ -#define DS1374_REG_SR_AF 0x01 /* Alarm Flag */ -#define DS1374_REG_TCR 0x09 /* Trickle Charge */ - -struct ds1374 { - struct i2c_client *client; - struct rtc_device *rtc; - struct work_struct work; - - /* The mutex protects alarm operations, and prevents a race - * between the enable_irq() in the workqueue and the free_irq() - * in the remove function. - */ - struct mutex mutex; - int exiting; -}; - -static struct i2c_driver ds1374_driver; - -static int ds1374_read_rtc(struct i2c_client *client, u32 *time, - int reg, int nbytes) -{ - u8 buf[4]; - int ret; - int i; - - if (nbytes > 4) { - WARN_ON(1); - return -EINVAL; - } - - ret = i2c_smbus_read_i2c_block_data(client, reg, nbytes, buf); - - if (ret < 0) - return ret; - if (ret < nbytes) - return -EIO; - - for (i = nbytes - 1, *time = 0; i >= 0; i--) - *time = (*time << 8) | buf[i]; - - return 0; -} - -static int ds1374_write_rtc(struct i2c_client *client, u32 time, - int reg, int nbytes) -{ - u8 buf[4]; - int i; - - if (nbytes > 4) { - WARN_ON(1); - return -EINVAL; - } - - for (i = 0; i < nbytes; i++) { - buf[i] = time & 0xff; - time >>= 8; - } - - return i2c_smbus_write_i2c_block_data(client, reg, nbytes, buf); -} - -static int ds1374_check_rtc_status(struct i2c_client *client) -{ - int ret = 0; - int control, stat; - - stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); - if (stat < 0) - return stat; - - if (stat & DS1374_REG_SR_OSF) - dev_warn(&client->dev, - "oscillator discontinuity flagged, " - "time unreliable\n"); - - stat &= ~(DS1374_REG_SR_OSF | DS1374_REG_SR_AF); - - ret = i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat); - if (ret < 0) - return ret; - - /* If the alarm is pending, clear it before requesting - * the interrupt, so an interrupt event isn't reported - * before everything is initialized. - */ - - control = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (control < 0) - return control; - - control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE); - return i2c_smbus_write_byte_data(client, DS1374_REG_CR, control); -} - -static int ds1374_read_time(struct device *dev, struct rtc_time *time) -{ - struct i2c_client *client = to_i2c_client(dev); - u32 itime; - int ret; - - ret = ds1374_read_rtc(client, &itime, DS1374_REG_TOD0, 4); - if (!ret) - rtc_time_to_tm(itime, time); - - return ret; -} - -static int ds1374_set_time(struct device *dev, struct rtc_time *time) -{ - struct i2c_client *client = to_i2c_client(dev); - unsigned long itime; - - rtc_tm_to_time(time, &itime); - return ds1374_write_rtc(client, itime, DS1374_REG_TOD0, 4); -} - -/* The ds1374 has a decrementer for an alarm, rather than a comparator. - * If the time of day is changed, then the alarm will need to be - * reset. - */ -static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ds1374 *ds1374 = i2c_get_clientdata(client); - u32 now, cur_alarm; - int cr, sr; - int ret = 0; - - if (client->irq < 0) - return -EINVAL; - - mutex_lock(&ds1374->mutex); - - cr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (ret < 0) - goto out; - - sr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_SR); - if (ret < 0) - goto out; - - ret = ds1374_read_rtc(client, &now, DS1374_REG_TOD0, 4); - if (ret) - goto out; - - ret = ds1374_read_rtc(client, &cur_alarm, DS1374_REG_WDALM0, 3); - if (ret) - goto out; - - rtc_time_to_tm(now + cur_alarm, &alarm->time); - alarm->enabled = !!(cr & DS1374_REG_CR_WACE); - alarm->pending = !!(sr & DS1374_REG_SR_AF); - -out: - mutex_unlock(&ds1374->mutex); - return ret; -} - -static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ds1374 *ds1374 = i2c_get_clientdata(client); - struct rtc_time now; - unsigned long new_alarm, itime; - int cr; - int ret = 0; - - if (client->irq < 0) - return -EINVAL; - - ret = ds1374_read_time(dev, &now); - if (ret < 0) - return ret; - - rtc_tm_to_time(&alarm->time, &new_alarm); - rtc_tm_to_time(&now, &itime); - - new_alarm -= itime; - - /* This can happen due to races, in addition to dates that are - * truly in the past. To avoid requiring the caller to check for - * races, dates in the past are assumed to be in the recent past - * (i.e. not something that we'd rather the caller know about via - * an error), and the alarm is set to go off as soon as possible. - */ - if (new_alarm <= 0) - new_alarm = 1; - - mutex_lock(&ds1374->mutex); - - ret = cr = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (ret < 0) - goto out; - - /* Disable any existing alarm before setting the new one - * (or lack thereof). */ - cr &= ~DS1374_REG_CR_WACE; - - ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr); - if (ret < 0) - goto out; - - ret = ds1374_write_rtc(client, new_alarm, DS1374_REG_WDALM0, 3); - if (ret) - goto out; - - if (alarm->enabled) { - cr |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; - cr &= ~DS1374_REG_CR_WDALM; - - ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr); - } - -out: - mutex_unlock(&ds1374->mutex); - return ret; -} - -static irqreturn_t ds1374_irq(int irq, void *dev_id) -{ - struct i2c_client *client = dev_id; - struct ds1374 *ds1374 = i2c_get_clientdata(client); - - disable_irq_nosync(irq); - schedule_work(&ds1374->work); - return IRQ_HANDLED; -} - -static void ds1374_work(struct work_struct *work) -{ - struct ds1374 *ds1374 = container_of(work, struct ds1374, work); - struct i2c_client *client = ds1374->client; - int stat, control; - - mutex_lock(&ds1374->mutex); - - stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); - if (stat < 0) - return; - - if (stat & DS1374_REG_SR_AF) { - stat &= ~DS1374_REG_SR_AF; - i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat); - - control = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (control < 0) - goto out; - - control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE); - i2c_smbus_write_byte_data(client, DS1374_REG_CR, control); - - /* rtc_update_irq() assumes that it is called - * from IRQ-disabled context. - */ - local_irq_disable(); - rtc_update_irq(ds1374->rtc, 1, RTC_AF | RTC_IRQF); - local_irq_enable(); - } - -out: - if (!ds1374->exiting) - enable_irq(client->irq); - - mutex_unlock(&ds1374->mutex); -} - -static int ds1374_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ds1374 *ds1374 = i2c_get_clientdata(client); - int ret = -ENOIOCTLCMD; - - mutex_lock(&ds1374->mutex); - - switch (cmd) { - case RTC_AIE_OFF: - ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (ret < 0) - goto out; - - ret &= ~DS1374_REG_CR_WACE; - - ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); - if (ret < 0) - goto out; - - break; - - case RTC_AIE_ON: - ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (ret < 0) - goto out; - - ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; - ret &= ~DS1374_REG_CR_WDALM; - - ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); - if (ret < 0) - goto out; - - break; - } - -out: - mutex_unlock(&ds1374->mutex); - return ret; -} - -static const struct rtc_class_ops ds1374_rtc_ops = { - .read_time = ds1374_read_time, - .set_time = ds1374_set_time, - .read_alarm = ds1374_read_alarm, - .set_alarm = ds1374_set_alarm, - .ioctl = ds1374_ioctl, -}; - -static int ds1374_probe(struct i2c_client *client) -{ - struct ds1374 *ds1374; - int ret; - - ds1374 = kzalloc(sizeof(struct ds1374), GFP_KERNEL); - if (!ds1374) - return -ENOMEM; - - ds1374->client = client; - i2c_set_clientdata(client, ds1374); - - INIT_WORK(&ds1374->work, ds1374_work); - mutex_init(&ds1374->mutex); - - ret = ds1374_check_rtc_status(client); - if (ret) - goto out_free; - - if (client->irq >= 0) { - ret = request_irq(client->irq, ds1374_irq, 0, - "ds1374", client); - if (ret) { - dev_err(&client->dev, "unable to request IRQ\n"); - goto out_free; - } - } - - ds1374->rtc = rtc_device_register(client->name, &client->dev, - &ds1374_rtc_ops, THIS_MODULE); - if (IS_ERR(ds1374->rtc)) { - ret = PTR_ERR(ds1374->rtc); - dev_err(&client->dev, "unable to register the class device\n"); - goto out_irq; - } - - return 0; - -out_irq: - if (client->irq >= 0) - free_irq(client->irq, client); - -out_free: - i2c_set_clientdata(client, NULL); - kfree(ds1374); - return ret; -} - -static int __devexit ds1374_remove(struct i2c_client *client) -{ - struct ds1374 *ds1374 = i2c_get_clientdata(client); - - if (client->irq >= 0) { - mutex_lock(&ds1374->mutex); - ds1374->exiting = 1; - mutex_unlock(&ds1374->mutex); - - free_irq(client->irq, client); - flush_scheduled_work(); - } - - rtc_device_unregister(ds1374->rtc); - i2c_set_clientdata(client, NULL); - kfree(ds1374); - return 0; -} - -static struct i2c_driver ds1374_driver = { - .driver = { - .name = "rtc-ds1374", - .owner = THIS_MODULE, - }, - .probe = ds1374_probe, - .remove = __devexit_p(ds1374_remove), -}; - -static int __init ds1374_init(void) -{ - return i2c_add_driver(&ds1374_driver); -} - -static void __exit ds1374_exit(void) -{ - i2c_del_driver(&ds1374_driver); -} - -module_init(ds1374_init); -module_exit(ds1374_exit); - -MODULE_AUTHOR("Scott Wood "); -MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-ds1553.c b/trunk/drivers/rtc/rtc-ds1553.c index bb53c09bad16..5ab3492817d1 100644 --- a/trunk/drivers/rtc/rtc-ds1553.c +++ b/trunk/drivers/rtc/rtc-ds1553.c @@ -395,7 +395,7 @@ static struct platform_driver ds1553_rtc_driver = { .probe = ds1553_rtc_probe, .remove = __devexit_p(ds1553_rtc_remove), .driver = { - .name = "rtc-ds1553", + .name = "ds1553", .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/rtc/rtc-ds1742.c b/trunk/drivers/rtc/rtc-ds1742.c index c535b78698e2..67291b0f8283 100644 --- a/trunk/drivers/rtc/rtc-ds1742.c +++ b/trunk/drivers/rtc/rtc-ds1742.c @@ -251,7 +251,7 @@ static struct platform_driver ds1742_rtc_driver = { .probe = ds1742_rtc_probe, .remove = __devexit_p(ds1742_rtc_remove), .driver = { - .name = "rtc-ds1742", + .name = "ds1742", .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/rtc/rtc-pcf8583.c b/trunk/drivers/rtc/rtc-pcf8583.c index 556d0e7da35b..d48b03374586 100644 --- a/trunk/drivers/rtc/rtc-pcf8583.c +++ b/trunk/drivers/rtc/rtc-pcf8583.c @@ -332,9 +332,6 @@ static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) } }; - if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) - return 0; - pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); if (!pcf) return -ENOMEM; diff --git a/trunk/drivers/rtc/rtc-sysfs.c b/trunk/drivers/rtc/rtc-sysfs.c index 6cad0841f3c4..69df94b44841 100644 --- a/trunk/drivers/rtc/rtc-sysfs.c +++ b/trunk/drivers/rtc/rtc-sysfs.c @@ -73,35 +73,11 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, return retval; } -static ssize_t -rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); -} - -static ssize_t -rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, - const char *buf, size_t n) -{ - struct rtc_device *rtc = to_rtc_device(dev); - unsigned long val = simple_strtoul(buf, NULL, 0); - - if (val >= 4096 || val == 0) - return -EINVAL; - - rtc->max_user_freq = (int)val; - - return n; -} - static struct device_attribute rtc_attrs[] = { __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), - __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, - rtc_sysfs_set_max_user_freq), { }, }; diff --git a/trunk/drivers/s390/scsi/zfcp_def.h b/trunk/drivers/s390/scsi/zfcp_def.h index 57cac7008e0b..16e5563e0c65 100644 --- a/trunk/drivers/s390/scsi/zfcp_def.h +++ b/trunk/drivers/s390/scsi/zfcp_def.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index 51d92b196ee7..3f105fdcf239 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -590,7 +590,7 @@ zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, */ int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, - struct scatterlist *sgl, int sg_count, int max_sbals) + struct scatterlist *sg, int sg_count, int max_sbals) { int sg_index; struct scatterlist *sg_segment; @@ -606,7 +606,9 @@ zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, sbale->flags |= sbtype; /* process all segements of scatter-gather list */ - for_each_sg(sgl, sg_segment, sg_count, sg_index) { + for (sg_index = 0, sg_segment = sg, bytes = 0; + sg_index < sg_count; + sg_index++, sg_segment++) { retval = zfcp_qdio_sbals_from_segment( fsf_req, sbtype, diff --git a/trunk/drivers/scsi/3w-9xxx.c b/trunk/drivers/scsi/3w-9xxx.c index fb14014ee16e..efd9d8d3a890 100644 --- a/trunk/drivers/scsi/3w-9xxx.c +++ b/trunk/drivers/scsi/3w-9xxx.c @@ -1990,7 +1990,6 @@ static struct scsi_host_template driver_template = { .max_sectors = TW_MAX_SECTORS, .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = twa_host_attrs, .emulated = 1 }; diff --git a/trunk/drivers/scsi/3w-xxxx.c b/trunk/drivers/scsi/3w-xxxx.c index a64153b96034..c7995fc216e8 100644 --- a/trunk/drivers/scsi/3w-xxxx.c +++ b/trunk/drivers/scsi/3w-xxxx.c @@ -2261,7 +2261,6 @@ static struct scsi_host_template driver_template = { .max_sectors = TW_MAX_SECTORS, .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = tw_host_attrs, .emulated = 1 }; diff --git a/trunk/drivers/scsi/BusLogic.c b/trunk/drivers/scsi/BusLogic.c index 49e1ffa4b2ff..9b206176f717 100644 --- a/trunk/drivers/scsi/BusLogic.c +++ b/trunk/drivers/scsi/BusLogic.c @@ -3575,7 +3575,6 @@ static struct scsi_host_template Bus_Logic_template = { .unchecked_isa_dma = 1, .max_sectors = 128, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; /* diff --git a/trunk/drivers/scsi/NCR53c406a.c b/trunk/drivers/scsi/NCR53c406a.c index 3168a1794849..eda8c48f6be7 100644 --- a/trunk/drivers/scsi/NCR53c406a.c +++ b/trunk/drivers/scsi/NCR53c406a.c @@ -1066,8 +1066,7 @@ static struct scsi_host_template driver_template = .sg_tablesize = 32 /*SG_ALL*/ /*SG_NONE*/, .cmd_per_lun = 1 /* commands per lun */, .unchecked_isa_dma = 1 /* unchecked_isa_dma */, - .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, + .use_clustering = ENABLE_CLUSTERING }; #include "scsi_module.c" diff --git a/trunk/drivers/scsi/a100u2w.c b/trunk/drivers/scsi/a100u2w.c index d3a6d15fb77a..f608d4a1d6da 100644 --- a/trunk/drivers/scsi/a100u2w.c +++ b/trunk/drivers/scsi/a100u2w.c @@ -1071,7 +1071,6 @@ static struct scsi_host_template inia100_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int __devinit inia100_probe_one(struct pci_dev *pdev, diff --git a/trunk/drivers/scsi/aacraid/linit.c b/trunk/drivers/scsi/aacraid/linit.c index 038980be763d..a7f42a17b5c7 100644 --- a/trunk/drivers/scsi/aacraid/linit.c +++ b/trunk/drivers/scsi/aacraid/linit.c @@ -944,7 +944,6 @@ static struct scsi_host_template aac_driver_template = { .cmd_per_lun = AAC_NUM_IO_FIB, #endif .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .emulated = 1, }; diff --git a/trunk/drivers/scsi/aha1542.c b/trunk/drivers/scsi/aha1542.c index 961a1882cb7e..cbbfbc9f3e0f 100644 --- a/trunk/drivers/scsi/aha1542.c +++ b/trunk/drivers/scsi/aha1542.c @@ -61,15 +61,15 @@ static void BAD_DMA(void *address, unsigned int length) } static void BAD_SG_DMA(Scsi_Cmnd * SCpnt, - struct scatterlist *sgp, + struct scatterlist *sgpnt, int nseg, int badseg) { printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n", badseg, nseg, - page_address(sgp->page) + sgp->offset, - (unsigned long long)SCSI_SG_PA(sgp), - sgp->length); + page_address(sgpnt[badseg].page) + sgpnt[badseg].offset, + (unsigned long long)SCSI_SG_PA(&sgpnt[badseg]), + sgpnt[badseg].length); /* * Not safe to continue. @@ -691,7 +691,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen); if (SCpnt->use_sg) { - struct scatterlist *sg; + struct scatterlist *sgpnt; struct chain *cptr; #ifdef DEBUG unsigned char *ptr; @@ -699,21 +699,23 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) int i; ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */ SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA); + sgpnt = (struct scatterlist *) SCpnt->request_buffer; cptr = (struct chain *) SCpnt->host_scribble; if (cptr == NULL) { /* free the claimed mailbox slot */ HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL; return SCSI_MLQUEUE_HOST_BUSY; } - scsi_for_each_sg(SCpnt, sg, SCpnt->use_sg, i) { - if (sg->length == 0 || SCpnt->use_sg > 16 || - (((int) sg->offset) & 1) || (sg->length & 1)) { + for (i = 0; i < SCpnt->use_sg; i++) { + if (sgpnt[i].length == 0 || SCpnt->use_sg > 16 || + (((int) sgpnt[i].offset) & 1) || (sgpnt[i].length & 1)) { unsigned char *ptr; printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i); - scsi_for_each_sg(SCpnt, sg, SCpnt->use_sg, i) { + for (i = 0; i < SCpnt->use_sg; i++) { printk(KERN_CRIT "%d: %p %d\n", i, - (page_address(sg->page) + - sg->offset), sg->length); + (page_address(sgpnt[i].page) + + sgpnt[i].offset), + sgpnt[i].length); }; printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr); ptr = (unsigned char *) &cptr[i]; @@ -721,10 +723,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) printk("%02x ", ptr[i]); panic("Foooooooood fight!"); }; - any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg)); - if (SCSI_SG_PA(sg) + sg->length - 1 > ISA_DMA_THRESHOLD) - BAD_SG_DMA(SCpnt, sg, SCpnt->use_sg, i); - any2scsi(cptr[i].datalen, sg->length); + any2scsi(cptr[i].dataptr, SCSI_SG_PA(&sgpnt[i])); + if (SCSI_SG_PA(&sgpnt[i]) + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD) + BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i); + any2scsi(cptr[i].datalen, sgpnt[i].length); }; any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain)); any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(cptr)); diff --git a/trunk/drivers/scsi/aha1740.c b/trunk/drivers/scsi/aha1740.c index f6722fd46008..e4a4f3a965d9 100644 --- a/trunk/drivers/scsi/aha1740.c +++ b/trunk/drivers/scsi/aha1740.c @@ -563,7 +563,6 @@ static struct scsi_host_template aha1740_template = { .sg_tablesize = AHA1740_SCATTER, .cmd_per_lun = AHA1740_CMDLUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .eh_abort_handler = aha1740_eh_abort_handler, }; diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_osm.c b/trunk/drivers/scsi/aic7xxx/aic79xx_osm.c index 42c0f14a262c..a055a96e3ad3 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -766,7 +766,6 @@ struct scsi_host_template aic79xx_driver_template = { .max_sectors = 8192, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .slave_alloc = ahd_linux_slave_alloc, .slave_configure = ahd_linux_slave_configure, .target_alloc = ahd_linux_target_alloc, diff --git a/trunk/drivers/scsi/aic7xxx/aic7xxx_osm.c b/trunk/drivers/scsi/aic7xxx/aic7xxx_osm.c index 7770befbf50c..2e9c38f2e8a6 100644 --- a/trunk/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/trunk/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -747,7 +747,6 @@ struct scsi_host_template aic7xxx_driver_template = { .max_sectors = 8192, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .slave_alloc = ahc_linux_slave_alloc, .slave_configure = ahc_linux_slave_configure, .target_alloc = ahc_linux_target_alloc, diff --git a/trunk/drivers/scsi/aic7xxx_old.c b/trunk/drivers/scsi/aic7xxx_old.c index 4025608d6964..1a71b0236c97 100644 --- a/trunk/drivers/scsi/aic7xxx_old.c +++ b/trunk/drivers/scsi/aic7xxx_old.c @@ -11142,7 +11142,6 @@ static struct scsi_host_template driver_template = { .max_sectors = 2048, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; #include "scsi_module.c" diff --git a/trunk/drivers/scsi/aic94xx/aic94xx_task.c b/trunk/drivers/scsi/aic94xx/aic94xx_task.c index ee0a98bffcd4..f2b23e01401a 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_task.c +++ b/trunk/drivers/scsi/aic94xx/aic94xx_task.c @@ -94,7 +94,7 @@ static inline int asd_map_scatterlist(struct sas_task *task, res = -ENOMEM; goto err_unmap; } - for_each_sg(task->scatter, sc, num_sg, i) { + for (sc = task->scatter, i = 0; i < num_sg; i++, sc++) { struct sg_el *sg = &((struct sg_el *)ascb->sg_arr->vaddr)[i]; sg->bus_addr = cpu_to_le64((u64)sg_dma_address(sc)); @@ -103,7 +103,7 @@ static inline int asd_map_scatterlist(struct sas_task *task, sg->flags |= ASD_SG_EL_LIST_EOL; } - for_each_sg(task->scatter, sc, 2, i) { + for (sc = task->scatter, i = 0; i < 2; i++, sc++) { sg_arr[i].bus_addr = cpu_to_le64((u64)sg_dma_address(sc)); sg_arr[i].size = cpu_to_le32((u32)sg_dma_len(sc)); @@ -115,7 +115,7 @@ static inline int asd_map_scatterlist(struct sas_task *task, sg_arr[2].bus_addr=cpu_to_le64((u64)ascb->sg_arr->dma_handle); } else { int i; - for_each_sg(task->scatter, sc, num_sg, i) { + for (sc = task->scatter, i = 0; i < num_sg; i++, sc++) { sg_arr[i].bus_addr = cpu_to_le64((u64)sg_dma_address(sc)); sg_arr[i].size = cpu_to_le32((u32)sg_dma_len(sc)); diff --git a/trunk/drivers/scsi/arcmsr/arcmsr_hba.c b/trunk/drivers/scsi/arcmsr/arcmsr_hba.c index f81777586b8f..cfcf40159eab 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/trunk/drivers/scsi/arcmsr/arcmsr_hba.c @@ -122,7 +122,6 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .max_sectors = ARCMSR_MAX_XFER_SECTORS, .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = arcmsr_host_attrs, }; #ifdef CONFIG_SCSI_ARCMSR_AER diff --git a/trunk/drivers/scsi/dc395x.c b/trunk/drivers/scsi/dc395x.c index fd42d4789202..1591824cf4b3 100644 --- a/trunk/drivers/scsi/dc395x.c +++ b/trunk/drivers/scsi/dc395x.c @@ -4765,7 +4765,6 @@ static struct scsi_host_template dc395x_driver_template = { .eh_bus_reset_handler = dc395x_eh_bus_reset, .unchecked_isa_dma = 0, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; diff --git a/trunk/drivers/scsi/dpt_i2o.c b/trunk/drivers/scsi/dpt_i2o.c index 8258506ba7d7..bea9d659af15 100644 --- a/trunk/drivers/scsi/dpt_i2o.c +++ b/trunk/drivers/scsi/dpt_i2o.c @@ -3295,7 +3295,6 @@ static struct scsi_host_template adpt_template = { .this_id = 7, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static s32 adpt_scsi_register(adpt_hba* pHba) diff --git a/trunk/drivers/scsi/eata.c b/trunk/drivers/scsi/eata.c index 7ead5210de96..ec2233114bc9 100644 --- a/trunk/drivers/scsi/eata.c +++ b/trunk/drivers/scsi/eata.c @@ -523,8 +523,7 @@ static struct scsi_host_template driver_template = { .slave_configure = eata2x_slave_configure, .this_id = 7, .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, + .use_clustering = ENABLE_CLUSTERING }; #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) diff --git a/trunk/drivers/scsi/hosts.c b/trunk/drivers/scsi/hosts.c index 112ab6abe62b..adc9559cb6f4 100644 --- a/trunk/drivers/scsi/hosts.c +++ b/trunk/drivers/scsi/hosts.c @@ -343,7 +343,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; shost->active_mode = sht->supported_mode; - shost->use_sg_chaining = sht->use_sg_chaining; if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; diff --git a/trunk/drivers/scsi/hptiop.c b/trunk/drivers/scsi/hptiop.c index 8515054cdf70..8b384fa7f048 100644 --- a/trunk/drivers/scsi/hptiop.c +++ b/trunk/drivers/scsi/hptiop.c @@ -655,7 +655,6 @@ static struct scsi_host_template driver_template = { .unchecked_isa_dma = 0, .emulated = 0, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .proc_name = driver_name, .shost_attrs = hptiop_attrs, .this_id = -1, diff --git a/trunk/drivers/scsi/ibmmca.c b/trunk/drivers/scsi/ibmmca.c index 714e6273a70d..1a924e9b0271 100644 --- a/trunk/drivers/scsi/ibmmca.c +++ b/trunk/drivers/scsi/ibmmca.c @@ -1501,7 +1501,6 @@ static struct scsi_host_template ibmmca_driver_template = { .sg_tablesize = 16, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int ibmmca_probe(struct device *dev) diff --git a/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c index 22d91ee173c5..cda0cc3d182f 100644 --- a/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1548,7 +1548,6 @@ static struct scsi_host_template driver_template = { .this_id = -1, .sg_tablesize = SG_ALL, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = ibmvscsi_attrs, }; diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index d297f64cd432..d81bb076a15a 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -70,7 +70,6 @@ typedef struct idescsi_pc_s { u8 *buffer; /* Data buffer */ u8 *current_position; /* Pointer into the above buffer */ struct scatterlist *sg; /* Scatter gather table */ - struct scatterlist *last_sg; /* Last sg element */ int b_count; /* Bytes transferred from current entry */ struct scsi_cmnd *scsi_cmd; /* SCSI command */ void (*done)(struct scsi_cmnd *); /* Scsi completion routine */ @@ -174,6 +173,12 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne char *buf; while (bcount) { + if (pc->sg - scsi_sglist(pc->scsi_cmd) > + scsi_sg_count(pc->scsi_cmd)) { + printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); + idescsi_discard_data (drive, bcount); + return; + } count = min(pc->sg->length - pc->b_count, bcount); if (PageHighMem(pc->sg->page)) { unsigned long flags; @@ -192,17 +197,10 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne } bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { - if (pc->sg == pc->last_sg) - break; - pc->sg = sg_next(pc->sg); + pc->sg++; pc->b_count = 0; } } - - if (bcount) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); - idescsi_discard_data (drive, bcount); - } } static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount) @@ -211,6 +209,12 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign char *buf; while (bcount) { + if (pc->sg - scsi_sglist(pc->scsi_cmd) > + scsi_sg_count(pc->scsi_cmd)) { + printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); + idescsi_output_zeros (drive, bcount); + return; + } count = min(pc->sg->length - pc->b_count, bcount); if (PageHighMem(pc->sg->page)) { unsigned long flags; @@ -229,17 +233,10 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign } bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { - if (pc->sg == pc->last_sg) - break; - pc->sg = sg_next(pc->sg); + pc->sg++; pc->b_count = 0; } } - - if (bcount) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); - idescsi_output_zeros (drive, bcount); - } } static void hexdump(u8 *x, int len) @@ -807,7 +804,6 @@ static int idescsi_queue (struct scsi_cmnd *cmd, memcpy (pc->c, cmd->cmnd, cmd->cmd_len); pc->buffer = NULL; pc->sg = scsi_sglist(cmd); - pc->last_sg = sg_last(pc->sg, cmd->use_sg); pc->b_count = 0; pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); pc->scsi_cmd = cmd; diff --git a/trunk/drivers/scsi/initio.c b/trunk/drivers/scsi/initio.c index 22d40fd5845b..d9dfb69ae031 100644 --- a/trunk/drivers/scsi/initio.c +++ b/trunk/drivers/scsi/initio.c @@ -2831,7 +2831,6 @@ static struct scsi_host_template initio_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int initio_probe_one(struct pci_dev *pdev, diff --git a/trunk/drivers/scsi/ips.c b/trunk/drivers/scsi/ips.c index edaac2714c5a..2ed099e2c20d 100644 --- a/trunk/drivers/scsi/ips.c +++ b/trunk/drivers/scsi/ips.c @@ -3252,7 +3252,7 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb) */ if ((scb->breakup) || (scb->sg_break)) { struct scatterlist *sg; - int i, sg_dma_index, ips_sg_index = 0; + int sg_dma_index, ips_sg_index = 0; /* we had a data breakup */ scb->data_len = 0; @@ -3261,22 +3261,20 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb) /* Spin forward to last dma chunk */ sg_dma_index = scb->breakup; - for (i = 0; i < scb->breakup; i++) - sg = sg_next(sg); /* Take care of possible partial on last chunk */ ips_fill_scb_sg_single(ha, - sg_dma_address(sg), + sg_dma_address(&sg[sg_dma_index]), scb, ips_sg_index++, - sg_dma_len(sg)); + sg_dma_len(&sg[sg_dma_index])); for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd); - sg_dma_index++, sg = sg_next(sg)) { + sg_dma_index++) { if (ips_fill_scb_sg_single (ha, - sg_dma_address(sg), + sg_dma_address(&sg[sg_dma_index]), scb, ips_sg_index++, - sg_dma_len(sg)) < 0) + sg_dma_len(&sg[sg_dma_index])) < 0) break; } diff --git a/trunk/drivers/scsi/lpfc/lpfc_scsi.c b/trunk/drivers/scsi/lpfc/lpfc_scsi.c index c0755565fae9..cd674938ccd5 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_scsi.c +++ b/trunk/drivers/scsi/lpfc/lpfc_scsi.c @@ -1438,7 +1438,6 @@ struct scsi_host_template lpfc_template = { .scan_finished = lpfc_scan_finished, .this_id = -1, .sg_tablesize = LPFC_SG_SEG_CNT, - .use_sg_chaining = ENABLE_SG_CHAINING, .cmd_per_lun = LPFC_CMD_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = lpfc_hba_attrs, @@ -1461,7 +1460,6 @@ struct scsi_host_template lpfc_vport_template = { .sg_tablesize = LPFC_SG_SEG_CNT, .cmd_per_lun = LPFC_CMD_PER_LUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = lpfc_vport_attrs, .max_sectors = 0xFFFF, }; diff --git a/trunk/drivers/scsi/mac53c94.c b/trunk/drivers/scsi/mac53c94.c index a035001f4438..b12ad7c7c673 100644 --- a/trunk/drivers/scsi/mac53c94.c +++ b/trunk/drivers/scsi/mac53c94.c @@ -402,7 +402,6 @@ static struct scsi_host_template mac53c94_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *match) diff --git a/trunk/drivers/scsi/mac_scsi.c b/trunk/drivers/scsi/mac_scsi.c index abe2bda6ac37..cdbcaa5ad6cf 100644 --- a/trunk/drivers/scsi/mac_scsi.c +++ b/trunk/drivers/scsi/mac_scsi.c @@ -53,11 +53,6 @@ #include "scsi.h" #include #include "mac_scsi.h" - -/* These control the behaviour of the generic 5380 core */ -#define AUTOSENSE -#define PSEUDO_DMA - #include "NCR5380.h" #if 0 @@ -576,6 +571,10 @@ static int macscsi_pwrite (struct Scsi_Host *instance, } +/* These control the behaviour of the generic 5380 core */ +#define AUTOSENSE +#define PSEUDO_DMA + #include "NCR5380.c" static struct scsi_host_template driver_template = { diff --git a/trunk/drivers/scsi/megaraid.c b/trunk/drivers/scsi/megaraid.c index 10d1aff9938a..e7e11f282c8f 100644 --- a/trunk/drivers/scsi/megaraid.c +++ b/trunk/drivers/scsi/megaraid.c @@ -4492,7 +4492,6 @@ static struct scsi_host_template megaraid_template = { .sg_tablesize = MAX_SGLIST, .cmd_per_lun = DEF_CMD_PER_LUN, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .eh_abort_handler = megaraid_abort, .eh_device_reset_handler = megaraid_reset, .eh_bus_reset_handler = megaraid_reset, diff --git a/trunk/drivers/scsi/megaraid/megaraid_mbox.c b/trunk/drivers/scsi/megaraid/megaraid_mbox.c index e4e4c6a39ed6..c6a53dccc16a 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mbox.c +++ b/trunk/drivers/scsi/megaraid/megaraid_mbox.c @@ -361,7 +361,6 @@ static struct scsi_host_template megaraid_template_g = { .eh_host_reset_handler = megaraid_reset_handler, .change_queue_depth = megaraid_change_queue_depth, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .sdev_attrs = megaraid_sdev_attrs, .shost_attrs = megaraid_shost_attrs, }; diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas.c b/trunk/drivers/scsi/megaraid/megaraid_sas.c index e3c5c5282203..ebb948c016bb 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas.c +++ b/trunk/drivers/scsi/megaraid/megaraid_sas.c @@ -1110,7 +1110,6 @@ static struct scsi_host_template megasas_template = { .eh_timed_out = megasas_reset_timer, .bios_param = megasas_bios_param, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; /** diff --git a/trunk/drivers/scsi/mesh.c b/trunk/drivers/scsi/mesh.c index 7470ff39ab22..651d09b08f2a 100644 --- a/trunk/drivers/scsi/mesh.c +++ b/trunk/drivers/scsi/mesh.c @@ -1843,7 +1843,6 @@ static struct scsi_host_template mesh_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) diff --git a/trunk/drivers/scsi/nsp32.c b/trunk/drivers/scsi/nsp32.c index 28161dc95e0d..7fed35372150 100644 --- a/trunk/drivers/scsi/nsp32.c +++ b/trunk/drivers/scsi/nsp32.c @@ -281,7 +281,6 @@ static struct scsi_host_template nsp32_template = { .cmd_per_lun = 1, .this_id = NSP32_HOST_SCSIID, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .eh_abort_handler = nsp32_eh_abort, .eh_bus_reset_handler = nsp32_eh_bus_reset, .eh_host_reset_handler = nsp32_eh_host_reset, diff --git a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c index 190e2a7d7067..961839ecfe86 100644 --- a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c @@ -694,7 +694,6 @@ static struct scsi_host_template sym53c500_driver_template = { .sg_tablesize = 32, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .shost_attrs = SYM53C500_shost_attrs }; diff --git a/trunk/drivers/scsi/qla1280.c b/trunk/drivers/scsi/qla1280.c index 76089cf55f4e..fba8aa8a81b5 100644 --- a/trunk/drivers/scsi/qla1280.c +++ b/trunk/drivers/scsi/qla1280.c @@ -2775,7 +2775,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; cmd_a64_entry_t *pkt; - struct scatterlist *sg = NULL, *s; + struct scatterlist *sg = NULL; __le32 *dword_ptr; dma_addr_t dma_handle; int status = 0; @@ -2889,16 +2889,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) * Load data segments. */ if (seg_cnt) { /* If data transfer. */ - int remseg = seg_cnt; /* Setup packet address segment pointer. */ dword_ptr = (u32 *)&pkt->dseg_0_address; if (cmd->use_sg) { /* If scatter gather */ /* Load command entry data segments. */ - for_each_sg(sg, s, seg_cnt, cnt) { - if (cnt == 2) - break; - dma_handle = sg_dma_address(s); + for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) sn_pci_set_vchan(ha->pdev, @@ -2909,12 +2906,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) cpu_to_le32(pci_dma_lo32(dma_handle)); *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); - *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + sg++; dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", cpu_to_le32(pci_dma_hi32(dma_handle)), cpu_to_le32(pci_dma_lo32(dma_handle)), - cpu_to_le32(sg_dma_len(sg_next(s)))); - remseg--; + cpu_to_le32(sg_dma_len(sg))); } dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " "command packet data - b %i, t %i, l %i \n", @@ -2929,9 +2926,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " "remains\n", seg_cnt); - while (remseg > 0) { - /* Update sg start */ - sg = s; + while (seg_cnt > 0) { /* Adjust ring index. */ ha->req_ring_index++; if (ha->req_ring_index == REQUEST_ENTRY_CNT) { @@ -2957,10 +2952,9 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; /* Load continuation entry data segments. */ - for_each_sg(sg, s, remseg, cnt) { - if (cnt == 5) - break; - dma_handle = sg_dma_address(s); + for (cnt = 0; cnt < 5 && seg_cnt; + cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) sn_pci_set_vchan(ha->pdev, @@ -2972,13 +2966,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); *dword_ptr++ = - cpu_to_le32(sg_dma_len(s)); + cpu_to_le32(sg_dma_len(sg)); dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", cpu_to_le32(pci_dma_hi32(dma_handle)), cpu_to_le32(pci_dma_lo32(dma_handle)), - cpu_to_le32(sg_dma_len(s))); + cpu_to_le32(sg_dma_len(sg))); + sg++; } - remseg -= cnt; dprintk(5, "qla1280_64bit_start_scsi: " "continuation packet data - b %i, t " "%i, l %i \n", SCSI_BUS_32(cmd), @@ -3068,7 +3062,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; struct cmd_entry *pkt; - struct scatterlist *sg = NULL, *s; + struct scatterlist *sg = NULL; __le32 *dword_ptr; int status = 0; int cnt; @@ -3194,7 +3188,6 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) * Load data segments. */ if (seg_cnt) { - int remseg = seg_cnt; /* Setup packet address segment pointer. */ dword_ptr = &pkt->dseg_0_address; @@ -3203,25 +3196,22 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) qla1280_dump_buffer(1, (char *)sg, 4 * 16); /* Load command entry data segments. */ - for_each_sg(sg, s, seg_cnt, cnt) { - if (cnt == 4) - break; + for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) { *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); - *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", - (pci_dma_lo32(sg_dma_address(s))), - (sg_dma_len(s))); - remseg--; + (pci_dma_lo32(sg_dma_address(sg))), + (sg_dma_len(sg))); + sg++; } /* * Build continuation packets. */ dprintk(3, "S/G Building Continuation" "...seg_cnt=0x%x remains\n", seg_cnt); - while (remseg > 0) { - /* Continue from end point */ - sg = s; + while (seg_cnt > 0) { /* Adjust ring index. */ ha->req_ring_index++; if (ha->req_ring_index == REQUEST_ENTRY_CNT) { @@ -3249,20 +3239,19 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) &((struct cont_entry *) pkt)->dseg_0_address; /* Load continuation entry data segments. */ - for_each_sg(sg, s, remseg, cnt) { - if (cnt == 7) - break; + for (cnt = 0; cnt < 7 && seg_cnt; + cnt++, seg_cnt--) { *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); *dword_ptr++ = - cpu_to_le32(sg_dma_len(s)); + cpu_to_le32(sg_dma_len(sg)); dprintk(1, "S/G Segment Cont. phys_addr=0x%x, " "len=0x%x\n", - cpu_to_le32(pci_dma_lo32(sg_dma_address(s))), - cpu_to_le32(sg_dma_len(s))); + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg))); + sg++; } - remseg -= cnt; dprintk(5, "qla1280_32bit_start_scsi: " "continuation packet data - " "scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd), @@ -4259,7 +4248,6 @@ static struct scsi_host_template qla1280_driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index 0351d380c2d7..a6bb8d0ecf13 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -132,7 +132,6 @@ struct scsi_host_template qla2x00_driver_template = { .this_id = -1, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .sg_tablesize = SG_ALL, /* @@ -164,7 +163,6 @@ struct scsi_host_template qla24xx_driver_template = { .this_id = -1, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, diff --git a/trunk/drivers/scsi/qla4xxx/ql4_os.c b/trunk/drivers/scsi/qla4xxx/ql4_os.c index 03b68d4f3bd0..b1d565c12c5b 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_os.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_os.c @@ -94,7 +94,6 @@ static struct scsi_host_template qla4xxx_driver_template = { .this_id = -1, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, diff --git a/trunk/drivers/scsi/qlogicfas.c b/trunk/drivers/scsi/qlogicfas.c index 1769f965eedf..1e874f1fb5c6 100644 --- a/trunk/drivers/scsi/qlogicfas.c +++ b/trunk/drivers/scsi/qlogicfas.c @@ -197,7 +197,6 @@ static struct scsi_host_template qlogicfas_driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static __init int qlogicfas_init(void) diff --git a/trunk/drivers/scsi/qlogicpti.c b/trunk/drivers/scsi/qlogicpti.c index 7a2e7986b038..e93f80316a19 100644 --- a/trunk/drivers/scsi/qlogicpti.c +++ b/trunk/drivers/scsi/qlogicpti.c @@ -868,7 +868,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr) { struct dataseg *ds; - struct scatterlist *sg, *s; + struct scatterlist *sg; int i, n; if (Cmnd->use_sg) { @@ -884,12 +884,11 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, n = sg_count; if (n > 4) n = 4; - for_each_sg(sg, s, n, i) { - ds[i].d_base = sg_dma_address(s); - ds[i].d_count = sg_dma_len(s); + for (i = 0; i < n; i++, sg++) { + ds[i].d_base = sg_dma_address(sg); + ds[i].d_count = sg_dma_len(sg); } sg_count -= 4; - sg = s; while (sg_count > 0) { struct Continuation_Entry *cont; @@ -908,9 +907,9 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, n = sg_count; if (n > 7) n = 7; - for_each_sg(sg, s, n, i) { - ds[i].d_base = sg_dma_address(s); - ds[i].d_count = sg_dma_len(s); + for (i = 0; i < n; i++, sg++) { + ds[i].d_base = sg_dma_address(sg); + ds[i].d_count = sg_dma_len(sg); } sg_count -= n; } diff --git a/trunk/drivers/scsi/scsi_debug.c b/trunk/drivers/scsi/scsi_debug.c index 72ee4c9cfb1a..4947dfe625a6 100644 --- a/trunk/drivers/scsi/scsi_debug.c +++ b/trunk/drivers/scsi/scsi_debug.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include "scsi.h" @@ -601,7 +600,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, int k, req_len, act_len, len, active; void * kaddr; void * kaddr_off; - struct scatterlist * sg; + struct scatterlist * sgpnt; if (0 == scp->request_bufflen) return 0; @@ -620,16 +619,16 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, scp->resid = req_len - act_len; return 0; } + sgpnt = (struct scatterlist *)scp->request_buffer; active = 1; - req_len = act_len = 0; - scsi_for_each_sg(scp, sg, scp->use_sg, k) { + for (k = 0, req_len = 0, act_len = 0; k < scp->use_sg; ++k, ++sgpnt) { if (active) { kaddr = (unsigned char *) - kmap_atomic(sg->page, KM_USER0); + kmap_atomic(sgpnt->page, KM_USER0); if (NULL == kaddr) return (DID_ERROR << 16); - kaddr_off = (unsigned char *)kaddr + sg->offset; - len = sg->length; + kaddr_off = (unsigned char *)kaddr + sgpnt->offset; + len = sgpnt->length; if ((req_len + len) > arr_len) { active = 0; len = arr_len - req_len; @@ -638,7 +637,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, kunmap_atomic(kaddr, KM_USER0); act_len += len; } - req_len += sg->length; + req_len += sgpnt->length; } if (scp->resid) scp->resid -= act_len; @@ -654,7 +653,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, int k, req_len, len, fin; void * kaddr; void * kaddr_off; - struct scatterlist * sg; + struct scatterlist * sgpnt; if (0 == scp->request_bufflen) return 0; @@ -669,14 +668,13 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, memcpy(arr, scp->request_buffer, len); return len; } - sg = scsi_sglist(scp); - req_len = fin = 0; - for (k = 0; k < scp->use_sg; ++k, sg = sg_next(sg)) { - kaddr = (unsigned char *)kmap_atomic(sg->page, KM_USER0); + sgpnt = (struct scatterlist *)scp->request_buffer; + for (k = 0, req_len = 0, fin = 0; k < scp->use_sg; ++k, ++sgpnt) { + kaddr = (unsigned char *)kmap_atomic(sgpnt->page, KM_USER0); if (NULL == kaddr) return -1; - kaddr_off = (unsigned char *)kaddr + sg->offset; - len = sg->length; + kaddr_off = (unsigned char *)kaddr + sgpnt->offset; + len = sgpnt->length; if ((req_len + len) > max_arr_len) { len = max_arr_len - req_len; fin = 1; @@ -685,7 +683,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, kunmap_atomic(kaddr, KM_USER0); if (fin) return req_len + len; - req_len += sg->length; + req_len += sgpnt->length; } return req_len; } diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index aac8a02cbe80..207f1aa08869 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -34,34 +33,35 @@ #define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) #define SG_MEMPOOL_SIZE 2 -/* - * The maximum number of SG segments that we will put inside a scatterlist - * (unless chaining is used). Should ideally fit inside a single page, to - * avoid a higher order allocation. - */ -#define SCSI_MAX_SG_SEGMENTS 128 - struct scsi_host_sg_pool { size_t size; - char *name; + char *name; struct kmem_cache *slab; mempool_t *pool; }; -#define SP(x) { x, "sgpool-" #x } +#if (SCSI_MAX_PHYS_SEGMENTS < 32) +#error SCSI_MAX_PHYS_SEGMENTS is too small +#endif + +#define SP(x) { x, "sgpool-" #x } static struct scsi_host_sg_pool scsi_sg_pools[] = { SP(8), SP(16), -#if (SCSI_MAX_SG_SEGMENTS > 16) SP(32), -#if (SCSI_MAX_SG_SEGMENTS > 32) +#if (SCSI_MAX_PHYS_SEGMENTS > 32) SP(64), -#if (SCSI_MAX_SG_SEGMENTS > 64) +#if (SCSI_MAX_PHYS_SEGMENTS > 64) SP(128), +#if (SCSI_MAX_PHYS_SEGMENTS > 128) + SP(256), +#if (SCSI_MAX_PHYS_SEGMENTS > 256) +#error SCSI_MAX_PHYS_SEGMENTS is too large #endif #endif #endif -}; +#endif +}; #undef SP static void scsi_run_queue(struct request_queue *q); @@ -289,16 +289,14 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, struct request_queue *q = rq->q; int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned int data_len = bufflen, len, bytes, off; - struct scatterlist *sg; struct page *page; struct bio *bio = NULL; int i, err, nr_vecs = 0; - for_each_sg(sgl, sg, nsegs, i) { - page = sg->page; - off = sg->offset; - len = sg->length; - data_len += len; + for (i = 0; i < nsegs; i++) { + page = sgl[i].page; + off = sgl[i].offset; + len = sgl[i].length; while (len > 0 && data_len > 0) { /* @@ -697,170 +695,56 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, return NULL; } -/* - * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit - * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. - */ -#define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 - -static inline unsigned int scsi_sgtable_index(unsigned short nents) +struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) { - unsigned int index; + struct scsi_host_sg_pool *sgp; + struct scatterlist *sgl; - switch (nents) { + BUG_ON(!cmd->use_sg); + + switch (cmd->use_sg) { case 1 ... 8: - index = 0; + cmd->sglist_len = 0; break; case 9 ... 16: - index = 1; + cmd->sglist_len = 1; break; -#if (SCSI_MAX_SG_SEGMENTS > 16) case 17 ... 32: - index = 2; + cmd->sglist_len = 2; break; -#if (SCSI_MAX_SG_SEGMENTS > 32) +#if (SCSI_MAX_PHYS_SEGMENTS > 32) case 33 ... 64: - index = 3; + cmd->sglist_len = 3; break; -#if (SCSI_MAX_SG_SEGMENTS > 64) +#if (SCSI_MAX_PHYS_SEGMENTS > 64) case 65 ... 128: - index = 4; + cmd->sglist_len = 4; + break; +#if (SCSI_MAX_PHYS_SEGMENTS > 128) + case 129 ... 256: + cmd->sglist_len = 5; break; #endif #endif #endif default: - printk(KERN_ERR "scsi: bad segment count=%d\n", nents); - BUG(); + return NULL; } - return index; -} - -struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) -{ - struct scsi_host_sg_pool *sgp; - struct scatterlist *sgl, *prev, *ret; - unsigned int index; - int this, left; - - BUG_ON(!cmd->use_sg); - - left = cmd->use_sg; - ret = prev = NULL; - do { - this = left; - if (this > SCSI_MAX_SG_SEGMENTS) { - this = SCSI_MAX_SG_SEGMENTS - 1; - index = SG_MEMPOOL_NR - 1; - } else - index = scsi_sgtable_index(this); - - left -= this; - - sgp = scsi_sg_pools + index; - - sgl = mempool_alloc(sgp->pool, gfp_mask); - if (unlikely(!sgl)) - goto enomem; - - memset(sgl, 0, sizeof(*sgl) * sgp->size); - - /* - * first loop through, set initial index and return value - */ - if (!ret) - ret = sgl; - - /* - * chain previous sglist, if any. we know the previous - * sglist must be the biggest one, or we would not have - * ended up doing another loop. - */ - if (prev) - sg_chain(prev, SCSI_MAX_SG_SEGMENTS, sgl); - - /* - * don't allow subsequent mempool allocs to sleep, it would - * violate the mempool principle. - */ - gfp_mask &= ~__GFP_WAIT; - gfp_mask |= __GFP_HIGH; - prev = sgl; - } while (left); - - /* - * ->use_sg may get modified after dma mapping has potentially - * shrunk the number of segments, so keep a copy of it for free. - */ - cmd->__use_sg = cmd->use_sg; - return ret; -enomem: - if (ret) { - /* - * Free entries chained off ret. Since we were trying to - * allocate another sglist, we know that all entries are of - * the max size. - */ - sgp = scsi_sg_pools + SG_MEMPOOL_NR - 1; - prev = ret; - ret = &ret[SCSI_MAX_SG_SEGMENTS - 1]; - - while ((sgl = sg_chain_ptr(ret)) != NULL) { - ret = &sgl[SCSI_MAX_SG_SEGMENTS - 1]; - mempool_free(sgl, sgp->pool); - } - - mempool_free(prev, sgp->pool); - } - return NULL; + sgp = scsi_sg_pools + cmd->sglist_len; + sgl = mempool_alloc(sgp->pool, gfp_mask); + return sgl; } EXPORT_SYMBOL(scsi_alloc_sgtable); -void scsi_free_sgtable(struct scsi_cmnd *cmd) +void scsi_free_sgtable(struct scatterlist *sgl, int index) { - struct scatterlist *sgl = cmd->request_buffer; struct scsi_host_sg_pool *sgp; - /* - * if this is the biggest size sglist, check if we have - * chained parts we need to free - */ - if (cmd->__use_sg > SCSI_MAX_SG_SEGMENTS) { - unsigned short this, left; - struct scatterlist *next; - unsigned int index; - - left = cmd->__use_sg - (SCSI_MAX_SG_SEGMENTS - 1); - next = sg_chain_ptr(&sgl[SCSI_MAX_SG_SEGMENTS - 1]); - while (left && next) { - sgl = next; - this = left; - if (this > SCSI_MAX_SG_SEGMENTS) { - this = SCSI_MAX_SG_SEGMENTS - 1; - index = SG_MEMPOOL_NR - 1; - } else - index = scsi_sgtable_index(this); - - left -= this; - - sgp = scsi_sg_pools + index; - - if (left) - next = sg_chain_ptr(&sgl[sgp->size - 1]); - - mempool_free(sgl, sgp->pool); - } - - /* - * Restore original, will be freed below - */ - sgl = cmd->request_buffer; - sgp = scsi_sg_pools + SG_MEMPOOL_NR - 1; - } else - sgp = scsi_sg_pools + scsi_sgtable_index(cmd->__use_sg); + BUG_ON(index >= SG_MEMPOOL_NR); + sgp = scsi_sg_pools + index; mempool_free(sgl, sgp->pool); } @@ -886,7 +770,7 @@ EXPORT_SYMBOL(scsi_free_sgtable); static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->use_sg) - scsi_free_sgtable(cmd); + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); /* * Zero these out. They now point to freed memory, and it is @@ -1100,6 +984,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) static int scsi_init_io(struct scsi_cmnd *cmd) { struct request *req = cmd->request; + struct scatterlist *sgpnt; int count; /* @@ -1112,13 +997,14 @@ static int scsi_init_io(struct scsi_cmnd *cmd) /* * If sg table allocation fails, requeue request later. */ - cmd->request_buffer = scsi_alloc_sgtable(cmd, GFP_ATOMIC); - if (unlikely(!cmd->request_buffer)) { + sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); + if (unlikely(!sgpnt)) { scsi_unprep_request(req); return BLKPREP_DEFER; } req->buffer = NULL; + cmd->request_buffer = (char *) sgpnt; if (blk_pc_request(req)) cmd->request_bufflen = req->data_len; else @@ -1643,25 +1529,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, if (!q) return NULL; - /* - * this limit is imposed by hardware restrictions - */ blk_queue_max_hw_segments(q, shost->sg_tablesize); - - /* - * In the future, sg chaining support will be mandatory and this - * ifdef can then go away. Right now we don't have all archs - * converted, so better keep it safe. - */ -#ifdef ARCH_HAS_SG_CHAIN - if (shost->use_sg_chaining) - blk_queue_max_phys_segments(q, SCSI_MAX_SG_CHAIN_SEGMENTS); - else - blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS); -#else - blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS); -#endif - + blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); @@ -2324,19 +2193,18 @@ EXPORT_SYMBOL_GPL(scsi_target_unblock); * * Returns virtual address of the start of the mapped page */ -void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count, +void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t *offset, size_t *len) { int i; size_t sg_len = 0, len_complete = 0; - struct scatterlist *sg; struct page *page; WARN_ON(!irqs_disabled()); - for_each_sg(sgl, sg, sg_count, i) { + for (i = 0; i < sg_count; i++) { len_complete = sg_len; /* Complete sg-entries */ - sg_len += sg->length; + sg_len += sg[i].length; if (sg_len > *offset) break; } @@ -2350,10 +2218,10 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count, } /* Offset starting from the beginning of first page in this sg-entry */ - *offset = *offset - len_complete + sg->offset; + *offset = *offset - len_complete + sg[i].offset; /* Assumption: contiguous pages can be accessed as "page + i" */ - page = nth_page(sg->page, (*offset >> PAGE_SHIFT)); + page = nth_page(sg[i].page, (*offset >> PAGE_SHIFT)); *offset &= ~PAGE_MASK; /* Bytes in this sg-entry from *offset to the end of the page */ diff --git a/trunk/drivers/scsi/scsi_tgt_lib.c b/trunk/drivers/scsi/scsi_tgt_lib.c index a91761c3645f..66c692ffa305 100644 --- a/trunk/drivers/scsi/scsi_tgt_lib.c +++ b/trunk/drivers/scsi/scsi_tgt_lib.c @@ -332,7 +332,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); if (cmd->request_buffer) - scsi_free_sgtable(cmd); + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); queue_work(scsi_tgtd, &tcmd->work); } @@ -373,7 +373,7 @@ static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) } eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg); - scsi_free_sgtable(cmd); + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); return -EINVAL; } diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 69f542c4923c..0a3a528212c2 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -826,6 +826,27 @@ static int sd_sync_cache(struct scsi_disk *sdkp) return 0; } +static int sd_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) +{ + int ret = 0; + struct scsi_device *sdp = q->queuedata; + struct scsi_disk *sdkp; + + if (sdp->sdev_state != SDEV_RUNNING) + return -ENXIO; + + sdkp = scsi_disk_get_from_dev(&sdp->sdev_gendev); + + if (!sdkp) + return -ENODEV; + + if (sdkp->WCE) + ret = sd_sync_cache(sdkp); + scsi_disk_put(sdkp); + return ret; +} + static void sd_prepare_flush(struct request_queue *q, struct request *rq) { memset(rq->cmd, 0, sizeof(rq->cmd)); @@ -1676,6 +1697,7 @@ static int sd_probe(struct device *dev) sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); + blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_DRIVERFS; diff --git a/trunk/drivers/scsi/sg.c b/trunk/drivers/scsi/sg.c index 7238b2dfc497..f6f5fc7d0cee 100644 --- a/trunk/drivers/scsi/sg.c +++ b/trunk/drivers/scsi/sg.c @@ -1165,7 +1165,7 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) sg = rsv_schp->buffer; sa = vma->vm_start; for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + ++k, ++sg) { len = vma->vm_end - sa; len = (len < sg->length) ? len : sg->length; if (offset < len) { @@ -1209,7 +1209,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) sa = vma->vm_start; sg = rsv_schp->buffer; for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + ++k, ++sg) { len = vma->vm_end - sa; len = (len < sg->length) ? len : sg->length; sa += len; @@ -1840,7 +1840,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) } for (k = 0, sg = schp->buffer, rem_sz = blk_size; (rem_sz > 0) && (k < mx_sc_elems); - ++k, rem_sz -= ret_sz, sg = sg_next(sg)) { + ++k, rem_sz -= ret_sz, ++sg) { num = (rem_sz > scatter_elem_sz_prev) ? scatter_elem_sz_prev : rem_sz; @@ -1913,7 +1913,7 @@ sg_write_xfer(Sg_request * srp) if (res) return res; - for (; p; sg = sg_next(sg), ksglen = sg->length, + for (; p; ++sg, ksglen = sg->length, p = page_address(sg->page)) { if (usglen <= 0) break; @@ -1992,7 +1992,7 @@ sg_remove_scat(Sg_scatter_hold * schp) int k; for (k = 0; (k < schp->k_use_sg) && sg->page; - ++k, sg = sg_next(sg)) { + ++k, ++sg) { SCSI_LOG_TIMEOUT(5, printk( "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", k, sg->page, sg->length)); @@ -2045,7 +2045,7 @@ sg_read_xfer(Sg_request * srp) if (res) return res; - for (; p; sg = sg_next(sg), ksglen = sg->length, + for (; p; ++sg, ksglen = sg->length, p = page_address(sg->page)) { if (usglen <= 0) break; @@ -2092,7 +2092,7 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) if ((!outp) || (num_read_xfer <= 0)) return 0; - for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, sg = sg_next(sg)) { + for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) { num = sg->length; if (num > num_read_xfer) { if (__copy_to_user(outp, page_address(sg->page), @@ -2142,7 +2142,7 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); rem = size; - for (k = 0; k < rsv_schp->k_use_sg; ++k, sg = sg_next(sg)) { + for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) { num = sg->length; if (rem <= num) { sfp->save_scat_len = num; diff --git a/trunk/drivers/scsi/stex.c b/trunk/drivers/scsi/stex.c index e3fab3a6aed7..72f6d8015358 100644 --- a/trunk/drivers/scsi/stex.c +++ b/trunk/drivers/scsi/stex.c @@ -1123,7 +1123,6 @@ static struct scsi_host_template driver_template = { .this_id = -1, .sg_tablesize = ST_MAX_SG, .cmd_per_lun = ST_CMD_PER_LUN, - .use_sg_chaining = ENABLE_SG_CHAINING, }; static int stex_set_dma_mask(struct pci_dev * pdev) diff --git a/trunk/drivers/scsi/sym53c416.c b/trunk/drivers/scsi/sym53c416.c index 8befab7e9839..92bfaeafe30d 100644 --- a/trunk/drivers/scsi/sym53c416.c +++ b/trunk/drivers/scsi/sym53c416.c @@ -854,6 +854,5 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 1, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; #include "scsi_module.c" diff --git a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c index db03c4c8ec1e..3db22325ea2c 100644 --- a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1808,7 +1808,6 @@ static struct scsi_host_template sym2_template = { .eh_host_reset_handler = sym53c8xx_eh_host_reset_handler, .this_id = 7, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, .max_sectors = 0xFFFF, #ifdef SYM_LINUX_PROC_INFO_SUPPORT .proc_info = sym53c8xx_proc_info, diff --git a/trunk/drivers/scsi/u14-34f.c b/trunk/drivers/scsi/u14-34f.c index 7edd6ceb13b2..fc9f51818e8f 100644 --- a/trunk/drivers/scsi/u14-34f.c +++ b/trunk/drivers/scsi/u14-34f.c @@ -450,8 +450,7 @@ static struct scsi_host_template driver_template = { .slave_configure = u14_34f_slave_configure, .this_id = 7, .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, + .use_clustering = ENABLE_CLUSTERING }; #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) diff --git a/trunk/drivers/scsi/ultrastor.c b/trunk/drivers/scsi/ultrastor.c index ea72bbeb8f9d..c08235d5afc9 100644 --- a/trunk/drivers/scsi/ultrastor.c +++ b/trunk/drivers/scsi/ultrastor.c @@ -1197,6 +1197,5 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = ULTRASTOR_MAX_CMDS_PER_LUN, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; #include "scsi_module.c" diff --git a/trunk/drivers/scsi/wd7000.c b/trunk/drivers/scsi/wd7000.c index 255c611e78b8..d6fd4259c56b 100644 --- a/trunk/drivers/scsi/wd7000.c +++ b/trunk/drivers/scsi/wd7000.c @@ -1671,7 +1671,6 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 1, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, - .use_sg_chaining = ENABLE_SG_CHAINING, }; #include "scsi_module.c" diff --git a/trunk/drivers/serial/8250_pci.c b/trunk/drivers/serial/8250_pci.c index 0e357562ce9e..1ea1ed82c352 100644 --- a/trunk/drivers/serial/8250_pci.c +++ b/trunk/drivers/serial/8250_pci.c @@ -1036,7 +1036,6 @@ enum pci_board_num_t { pbn_b0_2_115200, pbn_b0_4_115200, pbn_b0_5_115200, - pbn_b0_8_115200, pbn_b0_1_921600, pbn_b0_2_921600, @@ -1173,12 +1172,6 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, - [pbn_b0_8_115200] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 115200, - .uart_offset = 8, - }, [pbn_b0_1_921600] = { .flags = FL_BASE0, @@ -2573,119 +2566,6 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8, 0, 0, pbn_b2_8_921600 }, - - /* - * Mainpine series cards: Fairly standard layout but fools - * parts of the autodetect in some cases and uses otherwise - * unmatched communications subclasses in the PCI Express case - */ - - { /* RockForceDUO */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0200, - 0, 0, pbn_b0_2_115200 }, - { /* RockForceQUATRO */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0300, - 0, 0, pbn_b0_4_115200 }, - { /* RockForceDUO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0400, - 0, 0, pbn_b0_2_115200 }, - { /* RockForceQUATRO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0500, - 0, 0, pbn_b0_4_115200 }, - { /* RockForce+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0600, - 0, 0, pbn_b0_2_115200 }, - { /* RockForce+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0700, - 0, 0, pbn_b0_4_115200 }, - { /* RockForceOCTO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0800, - 0, 0, pbn_b0_8_115200 }, - { /* RockForceDUO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0C00, - 0, 0, pbn_b0_2_115200 }, - { /* RockForceQUARTRO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x0D00, - 0, 0, pbn_b0_4_115200 }, - { /* RockForceOCTO+ */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x1D00, - 0, 0, pbn_b0_8_115200 }, - { /* RockForceD1 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2000, - 0, 0, pbn_b0_1_115200 }, - { /* RockForceF1 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2100, - 0, 0, pbn_b0_1_115200 }, - { /* RockForceD2 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2200, - 0, 0, pbn_b0_2_115200 }, - { /* RockForceF2 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2300, - 0, 0, pbn_b0_2_115200 }, - { /* RockForceD4 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2400, - 0, 0, pbn_b0_4_115200 }, - { /* RockForceF4 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2500, - 0, 0, pbn_b0_4_115200 }, - { /* RockForceD8 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2600, - 0, 0, pbn_b0_8_115200 }, - { /* RockForceF8 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x2700, - 0, 0, pbn_b0_8_115200 }, - { /* IQ Express D1 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3000, - 0, 0, pbn_b0_1_115200 }, - { /* IQ Express F1 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3100, - 0, 0, pbn_b0_1_115200 }, - { /* IQ Express D2 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3200, - 0, 0, pbn_b0_2_115200 }, - { /* IQ Express F2 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3300, - 0, 0, pbn_b0_2_115200 }, - { /* IQ Express D4 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3400, - 0, 0, pbn_b0_4_115200 }, - { /* IQ Express F4 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3500, - 0, 0, pbn_b0_4_115200 }, - { /* IQ Express D8 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3C00, - 0, 0, pbn_b0_8_115200 }, - { /* IQ Express F8 */ - PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, - PCI_VENDOR_ID_MAINPINE, 0x3D00, - 0, 0, pbn_b0_8_115200 }, - - /* * PA Semi PA6T-1682M on-chip UART */ diff --git a/trunk/drivers/serial/8250_pnp.c b/trunk/drivers/serial/8250_pnp.c index 926f58a674a1..301c8c0be9d7 100644 --- a/trunk/drivers/serial/8250_pnp.c +++ b/trunk/drivers/serial/8250_pnp.c @@ -327,8 +327,6 @@ static const struct pnp_device_id pnp_dev_table[] = { { "WACF004", 0 }, { "WACF005", 0 }, { "WACF006", 0 }, - { "WACF007", 0 }, - { "WACF008", 0 }, /* Compaq touchscreen */ { "FPI2002", 0 }, /* Fujitsu Stylistic touchscreens */ diff --git a/trunk/drivers/serial/crisv10.c b/trunk/drivers/serial/crisv10.c index 7e8724d3571f..312bef6bd583 100644 --- a/trunk/drivers/serial/crisv10.c +++ b/trunk/drivers/serial/crisv10.c @@ -514,8 +514,6 @@ struct tty_driver *serial_driver; * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 * BUF_SIZE can't be > 128 */ -#define CRIS_BUF_SIZE 512 - /* Currently 16 descriptors x 128 bytes = 2048 bytes */ #define SERIAL_DESCR_BUF_SIZE 256 @@ -2499,18 +2497,55 @@ static void flush_to_flip_buffer(struct e100_serial *info) return; } - while ((buffer = info->first_recv_buffer) != NULL) { + length = tty->flip.count; + /* Don't flip more than the ldisc has room for. + * The return value from ldisc.receive_room(tty) - might not be up to + * date, the previous flip of up to TTY_FLIPBUF_SIZE might be on the + * processed and not accounted for yet. + * Since we use DMA, 1 SERIAL_DESCR_BUF_SIZE could be on the way. + * Lets buffer data here and let flow control take care of it. + * Since we normally flip large chunks, the ldisc don't react + * with throttle until too late if we flip to much. + */ + max_flip_size = tty->ldisc.receive_room(tty); + if (max_flip_size < 0) + max_flip_size = 0; + if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */ + length + info->recv_cnt + /* We have this queued */ + 2*SERIAL_DESCR_BUF_SIZE + /* This could be on the way */ + TTY_THRESHOLD_THROTTLE)) { /* Some slack */ + /* check TTY_THROTTLED first so it indicates our state */ + if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { + DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles room %lu\n", max_flip_size)); + rs_throttle(tty); + } +#if 0 + else if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */ + length + info->recv_cnt + /* We have this queued */ + SERIAL_DESCR_BUF_SIZE + /* This could be on the way */ + TTY_THRESHOLD_THROTTLE)) { /* Some slack */ + DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles again! %lu\n", max_flip_size)); + rs_throttle(tty); + } +#endif + } + + if (max_flip_size > TTY_FLIPBUF_SIZE) + max_flip_size = TTY_FLIPBUF_SIZE; + + while ((buffer = info->first_recv_buffer) && length < max_flip_size) { unsigned int count = buffer->length; - count = tty_buffer_request_room(tty, count); - if (count == 0) /* Throttle ?? */ - break; + if (length + count > max_flip_size) + count = max_flip_size - length; - if (count > 1) - tty_insert_flip_strings(tty, buffer->buffer, count - 1); - tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error); + memcpy(tty->flip.char_buf_ptr + length, buffer->buffer, count); + memset(tty->flip.flag_buf_ptr + length, TTY_NORMAL, count); + tty->flip.flag_buf_ptr[length] = buffer->error; + length += count; info->recv_cnt -= count; + DFLIP(DEBUG_LOG(info->line,"flip: %i\n", length)); if (count == buffer->length) { info->first_recv_buffer = buffer->next; @@ -2525,6 +2560,14 @@ static void flush_to_flip_buffer(struct e100_serial *info) if (!info->first_recv_buffer) info->last_recv_buffer = NULL; + tty->flip.count = length; + DFLIP(if (tty->ldisc.chars_in_buffer(tty) > 3500) { + DEBUG_LOG(info->line, "ldisc %lu\n", + tty->ldisc.chars_in_buffer(tty)); + DEBUG_LOG(info->line, "flip.count %lu\n", + tty->flip.count); + } + ); restore_flags(flags); DFLIP( @@ -2679,17 +2722,17 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) printk("!NO TTY!\n"); return info; } - if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE - TTY_THRESHOLD_THROTTLE) { /* check TTY_THROTTLED first so it indicates our state */ if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count)); rs_throttle(tty); } } - if (tty->flip.count >= CRIS_BUF_SIZE) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count); tty->flip.work.func((void *) tty); - if (tty->flip.count >= CRIS_BUF_SIZE) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count); return info; /* if TTY_DONT_FLIP is set */ } diff --git a/trunk/drivers/serial/m32r_sio.c b/trunk/drivers/serial/m32r_sio.c index 348ee2c19b58..6e09c8b395e8 100644 --- a/trunk/drivers/serial/m32r_sio.c +++ b/trunk/drivers/serial/m32r_sio.c @@ -539,7 +539,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up) static int serial_link_irq_chain(struct uart_sio_port *up) { struct irq_info *i = irq_lists + up->port.irq; - int ret, irq_flags = 0; + int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0; spin_lock_irq(&i->lock); diff --git a/trunk/drivers/serial/m32r_sio.h b/trunk/drivers/serial/m32r_sio.h index e9b7e11793b1..849f1b2c2531 100644 --- a/trunk/drivers/serial/m32r_sio.h +++ b/trunk/drivers/serial/m32r_sio.h @@ -46,3 +46,9 @@ struct old_serial_port { #define PROBE_ANY (~0) #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + +#ifdef CONFIG_SERIAL_SIO_SHARE_IRQ +#define M32R_SIO_SHARE_IRQS 1 +#else +#define M32R_SIO_SHARE_IRQS 0 +#endif diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index 68aa4da01865..a3bd3a3f41f3 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -1938,24 +1938,9 @@ static void uart_change_pm(struct uart_state *state, int pm_state) } } -struct uart_match { - struct uart_port *port; - struct uart_driver *driver; -}; - -static int serial_match_port(struct device *dev, void *data) -{ - struct uart_match *match = data; - dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line; - - return dev->devt == devt; /* Actually, only one tty per port */ -} - int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; - struct device *tty_dev; - struct uart_match match = {port, drv}; mutex_lock(&state->mutex); @@ -1966,15 +1951,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) } #endif - tty_dev = device_find_child(port->dev, &match, serial_match_port); - if (device_may_wakeup(tty_dev)) { - enable_irq_wake(port->irq); - put_device(tty_dev); - mutex_unlock(&state->mutex); - return 0; - } - port->suspended = 1; - if (state->info && state->info->flags & UIF_INITIALIZED) { const struct uart_ops *ops = port->ops; @@ -2023,13 +1999,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } #endif - if (!port->suspended) { - disable_irq_wake(port->irq); - mutex_unlock(&state->mutex); - return 0; - } - port->suspended = 0; - uart_change_pm(state, 0); /* @@ -2309,7 +2278,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state; int ret = 0; - struct device *tty_dev; BUG_ON(in_interrupt()); @@ -2346,13 +2314,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. */ - tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev); - if (likely(!IS_ERR(tty_dev))) { - device_can_wakeup(tty_dev) = 1; - device_set_wakeup_enable(tty_dev, 0); - } else - printk(KERN_ERR "Cannot register tty device on line %d\n", - port->line); + tty_register_device(drv->tty_driver, port->line, port->dev); /* * Ensure UPF_DEAD is not set. diff --git a/trunk/drivers/serial/serial_cs.c b/trunk/drivers/serial/serial_cs.c index 5afcb2fa7cd3..7c8d78fbbbfb 100644 --- a/trunk/drivers/serial/serial_cs.c +++ b/trunk/drivers/serial/serial_cs.c @@ -911,7 +911,6 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ diff --git a/trunk/drivers/serial/serial_txx9.c b/trunk/drivers/serial/serial_txx9.c index 6846a6c38b6d..0930e2a85514 100644 --- a/trunk/drivers/serial/serial_txx9.c +++ b/trunk/drivers/serial/serial_txx9.c @@ -25,15 +25,19 @@ #include #include #include +#include #include #include #include +#include +#include #include #include +#include #include -static char *serial_version = "1.11"; +static char *serial_version = "1.10"; static char *serial_name = "TX39/49 Serial driver"; #define PASS_LIMIT 256 @@ -64,6 +68,8 @@ static char *serial_name = "TX39/49 Serial driver"; */ #define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + struct uart_txx9_port { struct uart_port port; /* No additional info for now */ @@ -750,6 +756,21 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags) serial_txx9_initialize(port); } +static int +serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + unsigned long new_port = ser->port; + if (HIGH_BITS_OFFSET) + new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET; + if (ser->type != port->type || + ser->irq != port->irq || + ser->io_type != port->iotype || + new_port != port->iobase || + (unsigned long)ser->iomem_base != port->mapbase) + return -EINVAL; + return 0; +} + static const char * serial_txx9_type(struct uart_port *port) { @@ -773,6 +794,7 @@ static struct uart_ops serial_txx9_pops = { .release_port = serial_txx9_release_port, .request_port = serial_txx9_request_port, .config_port = serial_txx9_config_port, + .verify_port = serial_txx9_verify_port, }; static struct uart_txx9_port serial_txx9_ports[UART_NR]; @@ -928,8 +950,7 @@ int __init early_serial_txx9_setup(struct uart_port *port) serial_txx9_ports[port->line].port = *port; serial_txx9_ports[port->line].port.ops = &serial_txx9_pops; - serial_txx9_ports[port->line].port.flags |= - UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; + serial_txx9_ports[port->line].port.flags |= UPF_BOOT_AUTOCONF; return 0; } @@ -974,8 +995,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) uart->port.irq = port->irq; uart->port.uartclk = port->uartclk; uart->port.iotype = port->iotype; - uart->port.flags = port->flags - | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; + uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; uart->port.mapbase = port->mapbase; if (port->dev) uart->port.dev = port->dev; diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index a77ede598d34..b91571122daa 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -124,17 +124,16 @@ config SPI_MPC52xx_PSC Controller in master SPI mode. config SPI_MPC83xx - tristate "Freescale MPC83xx/QUICC Engine SPI controller" - depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL + tristate "Freescale MPC83xx SPI controller" + depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL select SPI_BITBANG help - This enables using the Freescale MPC83xx and QUICC Engine SPI - controllers in master mode. + This enables using the Freescale MPC83xx SPI controller in master + mode. Note, this driver uniquely supports the SPI controller on the MPC83xx - family of PowerPC processors, plus processors with QUICC Engine - technology. This driver uses a simple set of shift registers for data - (opposed to the CPM based descriptor model). + family of PowerPC processors. The MPC83xx uses a simple set of shift + registers for data (opposed to the CPM based descriptor model). config SPI_OMAP_UWIRE tristate "OMAP1 MicroWire" diff --git a/trunk/drivers/spi/atmel_spi.c b/trunk/drivers/spi/atmel_spi.c index 0d342dcdd302..b0469749310a 100644 --- a/trunk/drivers/spi/atmel_spi.c +++ b/trunk/drivers/spi/atmel_spi.c @@ -211,7 +211,7 @@ static void atmel_spi_next_message(struct spi_master *master) msg = list_entry(as->queue.next, struct spi_message, queue); spi = msg->spi; - dev_dbg(master->dev.parent, "start message %p for %s\n", + dev_dbg(master->cdev.dev, "start message %p for %s\n", msg, spi->dev.bus_id); /* select chip if it's not still active */ @@ -266,10 +266,10 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master, struct spi_transfer *xfer) { if (xfer->tx_dma != INVALID_DMA_ADDRESS) - dma_unmap_single(master->dev.parent, xfer->tx_dma, + dma_unmap_single(master->cdev.dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); if (xfer->rx_dma != INVALID_DMA_ADDRESS) - dma_unmap_single(master->dev.parent, xfer->rx_dma, + dma_unmap_single(master->cdev.dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); } @@ -285,7 +285,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, list_del(&msg->queue); msg->status = status; - dev_dbg(master->dev.parent, + dev_dbg(master->cdev.dev, "xfer complete: %u bytes transferred\n", msg->actual_length); @@ -348,7 +348,7 @@ atmel_spi_interrupt(int irq, void *dev_id) if (xfer->delay_usecs) udelay(xfer->delay_usecs); - dev_warn(master->dev.parent, "fifo overrun (%u/%u remaining)\n", + dev_warn(master->cdev.dev, "fifo overrun (%u/%u remaining)\n", spi_readl(as, TCR), spi_readl(as, RCR)); /* @@ -363,7 +363,7 @@ atmel_spi_interrupt(int irq, void *dev_id) if (spi_readl(as, SR) & SPI_BIT(TXEMPTY)) break; if (!timeout) - dev_warn(master->dev.parent, + dev_warn(master->cdev.dev, "timeout waiting for TXEMPTY"); while (spi_readl(as, SR) & SPI_BIT(RDRF)) spi_readl(as, RDR); @@ -526,7 +526,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) struct atmel_spi *as; struct spi_transfer *xfer; unsigned long flags; - struct device *controller = spi->master->dev.parent; + struct device *controller = spi->master->cdev.dev; as = spi_master_get_devdata(spi->master); diff --git a/trunk/drivers/spi/mpc52xx_psc_spi.c b/trunk/drivers/spi/mpc52xx_psc_spi.c index e9aba932f217..d2a4b2bdb07b 100644 --- a/trunk/drivers/spi/mpc52xx_psc_spi.c +++ b/trunk/drivers/spi/mpc52xx_psc_spi.c @@ -503,7 +503,7 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, INIT_LIST_HEAD(&mps->queue); mps->workqueue = create_singlethread_workqueue( - master->dev.parent->bus_id); + master->cdev.dev->bus_id); if (mps->workqueue == NULL) { ret = -EBUSY; goto free_irq; diff --git a/trunk/drivers/spi/omap2_mcspi.c b/trunk/drivers/spi/omap2_mcspi.c index 3cdab131c4a9..6b357cdb9ea3 100644 --- a/trunk/drivers/spi/omap2_mcspi.c +++ b/trunk/drivers/spi/omap2_mcspi.c @@ -645,7 +645,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) clk_enable(mcspi->ick); clk_enable(mcspi->fck); - ret = omap2_mcspi_setup_transfer(spi, NULL); + ret = omap2_mcspi_setup_transfer(spi, NULL); clk_disable(mcspi->fck); clk_disable(mcspi->ick); @@ -693,6 +693,7 @@ static void omap2_mcspi_work(struct work_struct *work) struct spi_device *spi; struct spi_transfer *t = NULL; int cs_active = 0; + struct omap2_mcspi_device_config *conf; struct omap2_mcspi_cs *cs; int par_override = 0; int status = 0; @@ -705,6 +706,7 @@ static void omap2_mcspi_work(struct work_struct *work) spin_unlock_irq(&mcspi->lock); spi = m->spi; + conf = spi->controller_data; cs = spi->controller_state; omap2_mcspi_set_enable(spi, 1); diff --git a/trunk/drivers/spi/omap_uwire.c b/trunk/drivers/spi/omap_uwire.c index 8245b5153f30..d275c615a73e 100644 --- a/trunk/drivers/spi/omap_uwire.c +++ b/trunk/drivers/spi/omap_uwire.c @@ -481,7 +481,7 @@ static void uwire_off(struct uwire_spi *uwire) spi_master_put(uwire->bitbang.master); } -static int __init uwire_probe(struct platform_device *pdev) +static int uwire_probe(struct platform_device *pdev) { struct spi_master *master; struct uwire_spi *uwire; @@ -525,7 +525,7 @@ static int __init uwire_probe(struct platform_device *pdev) return status; } -static int __exit uwire_remove(struct platform_device *pdev) +static int uwire_remove(struct platform_device *pdev) { struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev); int status; @@ -543,7 +543,8 @@ static struct platform_driver uwire_driver = { .bus = &platform_bus_type, .owner = THIS_MODULE, }, - .remove = __exit_p(uwire_remove), + .probe = uwire_probe, + .remove = uwire_remove, // suspend ... unuse ck // resume ... use ck }; @@ -565,7 +566,7 @@ static int __init omap_uwire_init(void) omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9); } - return platform_driver_probe(&uwire_driver, uwire_probe); + return platform_driver_register(&uwire_driver); } static void __exit omap_uwire_exit(void) diff --git a/trunk/drivers/spi/pxa2xx_spi.c b/trunk/drivers/spi/pxa2xx_spi.c index 5f3d808cbc29..e51311b2da0b 100644 --- a/trunk/drivers/spi/pxa2xx_spi.c +++ b/trunk/drivers/spi/pxa2xx_spi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -1229,7 +1230,7 @@ static void cleanup(struct spi_device *spi) kfree(chip); } -static int __init init_queue(struct driver_data *drv_data) +static int init_queue(struct driver_data *drv_data) { INIT_LIST_HEAD(&drv_data->queue); spin_lock_init(&drv_data->lock); @@ -1242,7 +1243,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1317,7 +1318,7 @@ static int destroy_queue(struct driver_data *drv_data) return 0; } -static int __init pxa2xx_spi_probe(struct platform_device *pdev) +static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct pxa2xx_spi_master *platform_info; @@ -1621,7 +1622,8 @@ static struct platform_driver driver = { .bus = &platform_bus_type, .owner = THIS_MODULE, }, - .remove = pxa2xx_spi_remove, + .probe = pxa2xx_spi_probe, + .remove = __devexit_p(pxa2xx_spi_remove), .shutdown = pxa2xx_spi_shutdown, .suspend = pxa2xx_spi_suspend, .resume = pxa2xx_spi_resume, @@ -1629,7 +1631,9 @@ static struct platform_driver driver = { static int __init pxa2xx_spi_init(void) { - return platform_driver_probe(&driver, pxa2xx_spi_probe); + platform_driver_register(&driver); + + return 0; } module_init(pxa2xx_spi_init); diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index 89769ce16f88..bcb8dd5fb0b4 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -204,7 +204,7 @@ struct spi_device *spi_new_device(struct spi_master *master, struct spi_board_info *chip) { struct spi_device *proxy; - struct device *dev = master->dev.parent; + struct device *dev = master->cdev.dev; int status; /* NOTE: caller did any chip->bus_num checks necessary. @@ -239,7 +239,7 @@ struct spi_device *spi_new_device(struct spi_master *master, proxy->modalias = chip->modalias; snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, - "%s.%u", master->dev.bus_id, + "%s.%u", master->cdev.class_id, chip->chip_select); proxy->dev.parent = dev; proxy->dev.bus = &spi_bus_type; @@ -338,18 +338,18 @@ static void scan_boardinfo(struct spi_master *master) /*-------------------------------------------------------------------------*/ -static void spi_master_release(struct device *dev) +static void spi_master_release(struct class_device *cdev) { struct spi_master *master; - master = container_of(dev, struct spi_master, dev); + master = container_of(cdev, struct spi_master, cdev); kfree(master); } static struct class spi_master_class = { .name = "spi_master", .owner = THIS_MODULE, - .dev_release = spi_master_release, + .release = spi_master_release, }; @@ -357,7 +357,7 @@ static struct class spi_master_class = { * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus * @size: how much zeroed driver-private data to allocate; the pointer to this - * memory is in the driver_data field of the returned device, + * memory is in the class_data field of the returned class_device, * accessible with spi_master_get_devdata(). * Context: can sleep * @@ -383,9 +383,9 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) if (!master) return NULL; - device_initialize(&master->dev); - master->dev.class = &spi_master_class; - master->dev.parent = get_device(dev); + class_device_initialize(&master->cdev); + master->cdev.class = &spi_master_class; + master->cdev.dev = get_device(dev); spi_master_set_devdata(master, &master[1]); return master; @@ -415,7 +415,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); int spi_register_master(struct spi_master *master) { static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); - struct device *dev = master->dev.parent; + struct device *dev = master->cdev.dev; int status = -ENODEV; int dynamic = 0; @@ -440,12 +440,12 @@ int spi_register_master(struct spi_master *master) /* register the device, then userspace will see it. * registration fails if the bus ID is in use. */ - snprintf(master->dev.bus_id, sizeof master->dev.bus_id, + snprintf(master->cdev.class_id, sizeof master->cdev.class_id, "spi%u", master->bus_num); - status = device_add(&master->dev); + status = class_device_add(&master->cdev); if (status < 0) goto done; - dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id, + dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, dynamic ? " (dynamic)" : ""); /* populate children from any spi device tables */ @@ -478,8 +478,8 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(master->dev.parent, NULL, __unregister); - device_unregister(&master->dev); + dummy = device_for_each_child(master->cdev.dev, NULL, __unregister); + class_device_unregister(&master->cdev); } EXPORT_SYMBOL_GPL(spi_unregister_master); @@ -495,13 +495,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master); */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - struct device *dev; + struct class_device *cdev; struct spi_master *master = NULL; struct spi_master *m; down(&spi_master_class.sem); - list_for_each_entry(dev, &spi_master_class.children, node) { - m = container_of(dev, struct spi_master, dev); + list_for_each_entry(cdev, &spi_master_class.children, node) { + m = container_of(cdev, struct spi_master, cdev); if (m->bus_num == bus_num) { master = spi_master_get(m); break; diff --git a/trunk/drivers/spi/spi_bfin5xx.c b/trunk/drivers/spi/spi_bfin5xx.c index 6cb71d74738f..f540ed77a102 100644 --- a/trunk/drivers/spi/spi_bfin5xx.c +++ b/trunk/drivers/spi/spi_bfin5xx.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -1106,7 +1107,7 @@ static inline int init_queue(struct driver_data *drv_data) /* init messages workqueue */ INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = - create_singlethread_workqueue(drv_data->master->dev.parent->bus_id); + create_singlethread_workqueue(drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) return -EBUSY; diff --git a/trunk/drivers/spi/spi_bitbang.c b/trunk/drivers/spi/spi_bitbang.c index 81639c6be1c7..0c85c984ccb4 100644 --- a/trunk/drivers/spi/spi_bitbang.c +++ b/trunk/drivers/spi/spi_bitbang.c @@ -472,7 +472,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) /* this task is the only thing to touch the SPI bits */ bitbang->busy = 0; bitbang->workqueue = create_singlethread_workqueue( - bitbang->master->dev.parent->bus_id); + bitbang->master->cdev.dev->bus_id); if (bitbang->workqueue == NULL) { status = -EBUSY; goto err1; diff --git a/trunk/drivers/spi/spi_imx.c b/trunk/drivers/spi/spi_imx.c index 3b4650ae6f1a..bd9177f51de9 100644 --- a/trunk/drivers/spi/spi_imx.c +++ b/trunk/drivers/spi/spi_imx.c @@ -1361,7 +1361,7 @@ static void cleanup(struct spi_device *spi) kfree(spi_get_ctldata(spi)); } -static int __init init_queue(struct driver_data *drv_data) +static int init_queue(struct driver_data *drv_data) { INIT_LIST_HEAD(&drv_data->queue); spin_lock_init(&drv_data->lock); @@ -1374,7 +1374,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->work, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1444,7 +1444,7 @@ static int destroy_queue(struct driver_data *drv_data) return 0; } -static int __init spi_imx_probe(struct platform_device *pdev) +static int spi_imx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct spi_imx_master *platform_info; @@ -1622,7 +1622,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) return status; } -static int __exit spi_imx_remove(struct platform_device *pdev) +static int __devexit spi_imx_remove(struct platform_device *pdev) { struct driver_data *drv_data = platform_get_drvdata(pdev); int irq; @@ -1739,7 +1739,8 @@ static struct platform_driver driver = { .bus = &platform_bus_type, .owner = THIS_MODULE, }, - .remove = __exit_p(spi_imx_remove), + .probe = spi_imx_probe, + .remove = __devexit_p(spi_imx_remove), .shutdown = spi_imx_shutdown, .suspend = spi_imx_suspend, .resume = spi_imx_resume, @@ -1747,7 +1748,7 @@ static struct platform_driver driver = { static int __init spi_imx_init(void) { - return platform_driver_probe(&driver, spi_imx_probe); + return platform_driver_register(&driver); } module_init(spi_imx_init); diff --git a/trunk/drivers/spi/spi_lm70llp.c b/trunk/drivers/spi/spi_lm70llp.c index 39d8d8ad65c0..4ea68ac16115 100644 --- a/trunk/drivers/spi/spi_lm70llp.c +++ b/trunk/drivers/spi/spi_lm70llp.c @@ -82,7 +82,7 @@ struct spi_lm70llp { struct pardevice *pd; struct spi_device *spidev_lm70; struct spi_board_info info; - //struct device *dev; + struct class_device *cdev; }; /* REVISIT : ugly global ; provides "exclusive open" facility */ diff --git a/trunk/drivers/spi/spi_mpc83xx.c b/trunk/drivers/spi/spi_mpc83xx.c index 4580b9cf625d..32cda77b31cd 100644 --- a/trunk/drivers/spi/spi_mpc83xx.c +++ b/trunk/drivers/spi/spi_mpc83xx.c @@ -511,7 +511,7 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) return ret; } -static int __exit mpc83xx_spi_remove(struct platform_device *dev) +static int __devexit mpc83xx_spi_remove(struct platform_device *dev) { struct mpc83xx_spi *mpc83xx_spi; struct spi_master *master; @@ -529,7 +529,8 @@ static int __exit mpc83xx_spi_remove(struct platform_device *dev) MODULE_ALIAS("mpc83xx_spi"); /* for platform bus hotplug */ static struct platform_driver mpc83xx_spi_driver = { - .remove = __exit_p(mpc83xx_spi_remove), + .probe = mpc83xx_spi_probe, + .remove = __devexit_p(mpc83xx_spi_remove), .driver = { .name = "mpc83xx_spi", }, @@ -537,7 +538,7 @@ static struct platform_driver mpc83xx_spi_driver = { static int __init mpc83xx_spi_init(void) { - return platform_driver_probe(&mpc83xx_spi_driver, mpc83xx_spi_probe); + return platform_driver_register(&mpc83xx_spi_driver); } static void __exit mpc83xx_spi_exit(void) diff --git a/trunk/drivers/spi/spi_s3c24xx.c b/trunk/drivers/spi/spi_s3c24xx.c index 89d6685a5ca4..e9b683f7d7b3 100644 --- a/trunk/drivers/spi/spi_s3c24xx.c +++ b/trunk/drivers/spi/spi_s3c24xx.c @@ -233,7 +233,7 @@ static irqreturn_t s3c24xx_spi_irq(int irq, void *dev) return IRQ_HANDLED; } -static int __init s3c24xx_spi_probe(struct platform_device *pdev) +static int s3c24xx_spi_probe(struct platform_device *pdev) { struct s3c24xx_spi *hw; struct spi_master *master; @@ -382,7 +382,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) return err; } -static int __exit s3c24xx_spi_remove(struct platform_device *dev) +static int s3c24xx_spi_remove(struct platform_device *dev) { struct s3c24xx_spi *hw = platform_get_drvdata(dev); @@ -429,7 +429,8 @@ static int s3c24xx_spi_resume(struct platform_device *pdev) MODULE_ALIAS("s3c2410_spi"); /* for platform bus hotplug */ static struct platform_driver s3c24xx_spidrv = { - .remove = __exit_p(s3c24xx_spi_remove), + .probe = s3c24xx_spi_probe, + .remove = s3c24xx_spi_remove, .suspend = s3c24xx_spi_suspend, .resume = s3c24xx_spi_resume, .driver = { @@ -440,7 +441,7 @@ static struct platform_driver s3c24xx_spidrv = { static int __init s3c24xx_spi_init(void) { - return platform_driver_probe(&s3c24xx_spidrv, s3c24xx_spi_probe); + return platform_driver_register(&s3c24xx_spidrv); } static void __exit s3c24xx_spi_exit(void) diff --git a/trunk/drivers/spi/spi_txx9.c b/trunk/drivers/spi/spi_txx9.c index cc5094f37dd3..b7f4bb239eaf 100644 --- a/trunk/drivers/spi/spi_txx9.c +++ b/trunk/drivers/spi/spi_txx9.c @@ -400,7 +400,7 @@ static int __init txx9spi_probe(struct platform_device *dev) goto exit; } - c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id); + c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id); if (!c->workqueue) goto exit; c->last_chipselect = -1; diff --git a/trunk/drivers/telephony/Kconfig b/trunk/drivers/telephony/Kconfig index b5f78b6ed2bd..5f98f673f1b6 100644 --- a/trunk/drivers/telephony/Kconfig +++ b/trunk/drivers/telephony/Kconfig @@ -19,7 +19,7 @@ if PHONE config PHONE_IXJ tristate "QuickNet Internet LineJack/PhoneJack support" - depends on ISA || PCI + depends ISA || PCI ---help--- Say M if you have a telephony card manufactured by Quicknet Technologies, Inc. These include the Internet PhoneJACK and diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 60a8f55a0cc7..d20cb545a6e4 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -1407,11 +1407,7 @@ int usb_new_device(struct usb_device *udev) /** - * usb_deauthorize_device - deauthorize a device (usbcore-internal) - * @usb_dev: USB device - * - * Move the USB device to a very basic state where interfaces are disabled - * and the device is in fact unconfigured and unusable. + * Similar to usb_disconnect() * * We share a lock (that we have) with device_del(), so we need to * defer its call. diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb_con.c b/trunk/drivers/usb/misc/sisusbvga/sisusb_con.c index b624320df903..43722e5a49d1 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -1042,8 +1042,7 @@ sisusbcon_set_origin(struct vc_data *c) /* Interface routine */ static int -sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows, - unsigned int user) +sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows) { struct sisusb_usb_data *sisusb; int fh; diff --git a/trunk/drivers/usb/storage/alauda.c b/trunk/drivers/usb/storage/alauda.c index 8d3711a7ff06..4d3cbb12b713 100644 --- a/trunk/drivers/usb/storage/alauda.c +++ b/trunk/drivers/usb/storage/alauda.c @@ -798,13 +798,12 @@ static int alauda_read_data(struct us_data *us, unsigned long address, { unsigned char *buffer; u16 lba, max_lba; - unsigned int page, len, offset; + unsigned int page, len, index, offset; unsigned int blockshift = MEDIA_INFO(us).blockshift; unsigned int pageshift = MEDIA_INFO(us).pageshift; unsigned int blocksize = MEDIA_INFO(us).blocksize; unsigned int pagesize = MEDIA_INFO(us).pagesize; unsigned int uzonesize = MEDIA_INFO(us).uzonesize; - struct scatterlist *sg; int result; /* @@ -828,8 +827,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address, max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift); result = USB_STOR_TRANSPORT_GOOD; - offset = 0; - sg = NULL; + index = offset = 0; while (sectors > 0) { unsigned int zone = lba / uzonesize; /* integer division */ @@ -875,7 +873,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address, /* Store the data in the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, TO_XFER_BUF); + &index, &offset, TO_XFER_BUF); page = 0; lba++; @@ -893,12 +891,11 @@ static int alauda_write_data(struct us_data *us, unsigned long address, unsigned int sectors) { unsigned char *buffer, *blockbuffer; - unsigned int page, len, offset; + unsigned int page, len, index, offset; unsigned int blockshift = MEDIA_INFO(us).blockshift; unsigned int pageshift = MEDIA_INFO(us).pageshift; unsigned int blocksize = MEDIA_INFO(us).blocksize; unsigned int pagesize = MEDIA_INFO(us).pagesize; - struct scatterlist *sg; u16 lba, max_lba; int result; @@ -932,8 +929,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift); result = USB_STOR_TRANSPORT_GOOD; - offset = 0; - sg = NULL; + index = offset = 0; while (sectors > 0) { /* Write as many sectors as possible in this block */ @@ -950,7 +946,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, /* Get the data from the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, FROM_XFER_BUF); + &index, &offset, FROM_XFER_BUF); result = alauda_write_lba(us, lba, page, pages, buffer, blockbuffer); diff --git a/trunk/drivers/usb/storage/datafab.c b/trunk/drivers/usb/storage/datafab.c index 579e9f52053a..c87ad1bae1d6 100644 --- a/trunk/drivers/usb/storage/datafab.c +++ b/trunk/drivers/usb/storage/datafab.c @@ -98,8 +98,7 @@ static int datafab_read_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Datafab @@ -156,7 +155,7 @@ static int datafab_read_data(struct us_data *us, // Store the data in the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, TO_XFER_BUF); + &sg_idx, &sg_offset, TO_XFER_BUF); sector += thistime; totallen -= len; @@ -182,8 +181,7 @@ static int datafab_write_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Datafab @@ -219,7 +217,7 @@ static int datafab_write_data(struct us_data *us, // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, FROM_XFER_BUF); + &sg_idx, &sg_offset, FROM_XFER_BUF); command[0] = 0; command[1] = thistime; diff --git a/trunk/drivers/usb/storage/jumpshot.c b/trunk/drivers/usb/storage/jumpshot.c index 61097cbb1585..003fcf545888 100644 --- a/trunk/drivers/usb/storage/jumpshot.c +++ b/trunk/drivers/usb/storage/jumpshot.c @@ -119,8 +119,7 @@ static int jumpshot_read_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Jumpshot @@ -171,7 +170,7 @@ static int jumpshot_read_data(struct us_data *us, // Store the data in the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, TO_XFER_BUF); + &sg_idx, &sg_offset, TO_XFER_BUF); sector += thistime; totallen -= len; @@ -196,8 +195,7 @@ static int jumpshot_write_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result, waitcount; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Jumpshot @@ -227,7 +225,7 @@ static int jumpshot_write_data(struct us_data *us, // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, FROM_XFER_BUF); + &sg_idx, &sg_offset, FROM_XFER_BUF); command[0] = 0; command[1] = thistime; diff --git a/trunk/drivers/usb/storage/protocol.c b/trunk/drivers/usb/storage/protocol.c index cc8f7c52c729..9ad30428d2dd 100644 --- a/trunk/drivers/usb/storage/protocol.c +++ b/trunk/drivers/usb/storage/protocol.c @@ -157,7 +157,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, * pick up from where this one left off. */ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, unsigned int *offset, enum xfer_buf_dir dir) { unsigned int cnt; @@ -184,17 +184,16 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, * located in high memory -- then kmap() will map it to a temporary * position in the kernel's virtual address space. */ } else { - struct scatterlist *sg = *sgptr; - - if (!sg) - sg = (struct scatterlist *) srb->request_buffer; + struct scatterlist *sg = + (struct scatterlist *) srb->request_buffer + + *index; /* This loop handles a single s-g list entry, which may * include multiple pages. Find the initial page structure * and the starting offset within the page, and update * the *offset and *index values for the next loop. */ cnt = 0; - while (cnt < buflen) { + while (cnt < buflen && *index < srb->use_sg) { struct page *page = sg->page + ((sg->offset + *offset) >> PAGE_SHIFT); unsigned int poff = @@ -210,7 +209,8 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, /* Transfer continues to next s-g entry */ *offset = 0; - sg = sg_next(sg); + ++*index; + ++sg; } /* Transfer the data for all the pages in this @@ -234,7 +234,6 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, sglen -= plen; } } - *sgptr = sg; } /* Return the amount actually transferred */ @@ -246,10 +245,9 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, void usb_stor_set_xfer_buf(unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb) { - unsigned int offset = 0; - struct scatterlist *sg = NULL; + unsigned int index = 0, offset = 0; - usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset, + usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, TO_XFER_BUF); if (buflen < srb->request_bufflen) srb->resid = srb->request_bufflen - buflen; diff --git a/trunk/drivers/usb/storage/protocol.h b/trunk/drivers/usb/storage/protocol.h index 8737a36891ca..845bed4b8031 100644 --- a/trunk/drivers/usb/storage/protocol.h +++ b/trunk/drivers/usb/storage/protocol.h @@ -52,7 +52,7 @@ extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*, enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, unsigned int *offset, enum xfer_buf_dir dir); extern void usb_stor_set_xfer_buf(unsigned char *buffer, diff --git a/trunk/drivers/usb/storage/sddr09.c b/trunk/drivers/usb/storage/sddr09.c index b12202c5da2d..b2ed2a3e6fca 100644 --- a/trunk/drivers/usb/storage/sddr09.c +++ b/trunk/drivers/usb/storage/sddr09.c @@ -705,8 +705,7 @@ sddr09_read_data(struct us_data *us, unsigned char *buffer; unsigned int lba, maxlba, pba; unsigned int page, pages; - unsigned int len, offset; - struct scatterlist *sg; + unsigned int len, index, offset; int result; // Figure out the initial LBA and page @@ -731,8 +730,7 @@ sddr09_read_data(struct us_data *us, // contiguous LBA's. Another exercise left to the student. result = 0; - offset = 0; - sg = NULL; + index = offset = 0; while (sectors > 0) { @@ -779,7 +777,7 @@ sddr09_read_data(struct us_data *us, // Store the data in the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, TO_XFER_BUF); + &index, &offset, TO_XFER_BUF); page = 0; lba++; @@ -933,8 +931,7 @@ sddr09_write_data(struct us_data *us, unsigned int pagelen, blocklen; unsigned char *blockbuffer; unsigned char *buffer; - unsigned int len, offset; - struct scatterlist *sg; + unsigned int len, index, offset; int result; // Figure out the initial LBA and page @@ -971,8 +968,7 @@ sddr09_write_data(struct us_data *us, } result = 0; - offset = 0; - sg = NULL; + index = offset = 0; while (sectors > 0) { @@ -991,7 +987,7 @@ sddr09_write_data(struct us_data *us, // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, FROM_XFER_BUF); + &index, &offset, FROM_XFER_BUF); result = sddr09_write_lba(us, lba, page, pages, buffer, blockbuffer); diff --git a/trunk/drivers/usb/storage/sddr55.c b/trunk/drivers/usb/storage/sddr55.c index d43a3415e12f..0b1b5b59ca7b 100644 --- a/trunk/drivers/usb/storage/sddr55.c +++ b/trunk/drivers/usb/storage/sddr55.c @@ -167,8 +167,7 @@ static int sddr55_read_data(struct us_data *us, unsigned long address; unsigned short pages; - unsigned int len, offset; - struct scatterlist *sg; + unsigned int len, index, offset; // Since we only read in one block at a time, we have to create // a bounce buffer and move the data a piece at a time between the @@ -179,8 +178,7 @@ static int sddr55_read_data(struct us_data *us, buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; /* out of memory */ - offset = 0; - sg = NULL; + index = offset = 0; while (sectors>0) { @@ -257,7 +255,7 @@ static int sddr55_read_data(struct us_data *us, // Store the data in the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, TO_XFER_BUF); + &index, &offset, TO_XFER_BUF); page = 0; lba++; @@ -289,8 +287,7 @@ static int sddr55_write_data(struct us_data *us, unsigned short pages; int i; - unsigned int len, offset; - struct scatterlist *sg; + unsigned int len, index, offset; /* check if we are allowed to write */ if (info->read_only || info->force_read_only) { @@ -307,8 +304,7 @@ static int sddr55_write_data(struct us_data *us, buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; - offset = 0; - sg = NULL; + index = offset = 0; while (sectors > 0) { @@ -326,7 +322,7 @@ static int sddr55_write_data(struct us_data *us, // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &offset, FROM_XFER_BUF); + &index, &offset, FROM_XFER_BUF); US_DEBUGP("Write %02X pages, to PBA %04X" " (LBA %04X) page %02X\n", diff --git a/trunk/drivers/usb/storage/shuttle_usbat.c b/trunk/drivers/usb/storage/shuttle_usbat.c index cb22a9ad1694..17ca4d73577b 100644 --- a/trunk/drivers/usb/storage/shuttle_usbat.c +++ b/trunk/drivers/usb/storage/shuttle_usbat.c @@ -993,8 +993,7 @@ static int usbat_flash_read_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; result = usbat_flash_check_media(us, info); if (result != USB_STOR_TRANSPORT_GOOD) @@ -1048,7 +1047,7 @@ static int usbat_flash_read_data(struct us_data *us, /* Store the data in the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, TO_XFER_BUF); + &sg_idx, &sg_offset, TO_XFER_BUF); sector += thistime; totallen -= len; @@ -1084,8 +1083,7 @@ static int usbat_flash_write_data(struct us_data *us, unsigned char thistime; unsigned int totallen, alloclen; int len, result; - unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; + unsigned int sg_idx = 0, sg_offset = 0; result = usbat_flash_check_media(us, info); if (result != USB_STOR_TRANSPORT_GOOD) @@ -1124,7 +1122,7 @@ static int usbat_flash_write_data(struct us_data *us, /* Get the data from the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, - &sg, &sg_offset, FROM_XFER_BUF); + &sg_idx, &sg_offset, FROM_XFER_BUF); /* ATA command 0x30 (WRITE SECTORS) */ usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30); @@ -1164,8 +1162,8 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, unsigned char *buffer; unsigned int len; unsigned int sector; + unsigned int sg_segment = 0; unsigned int sg_offset = 0; - struct scatterlist *sg = NULL; US_DEBUGP("handle_read10: transfersize %d\n", srb->transfersize); @@ -1222,6 +1220,9 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, sector |= short_pack(data[7+5], data[7+4]); transferred = 0; + sg_segment = 0; /* for keeping track of where we are in */ + sg_offset = 0; /* the scatter/gather list */ + while (transferred != srb->request_bufflen) { if (len > srb->request_bufflen - transferred) @@ -1254,7 +1255,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, /* Store the data in the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, srb, - &sg, &sg_offset, TO_XFER_BUF); + &sg_segment, &sg_offset, TO_XFER_BUF); /* Update the amount transferred and the sector number */ diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index efe474e2cc3b..5216c11d4dec 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -5,9 +5,8 @@ menu "Graphics support" depends on HAS_IOMEM -source "drivers/char/agp/Kconfig" - -source "drivers/char/drm/Kconfig" +source "drivers/video/backlight/Kconfig" +source "drivers/video/display/Kconfig" config VGASTATE tristate @@ -20,7 +19,7 @@ config VIDEO_OUTPUT_CONTROL This framework adds support for low-level control of the video output switch. -menuconfig FB +config FB tristate "Support for frame buffer devices" ---help--- The frame buffer device provides an abstraction for the graphics @@ -104,15 +103,6 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. -config FB_CFB_REV_PIXELS_IN_BYTE - bool - depends on FB - default n - ---help--- - Allow generic frame-buffer functions to work on displays with 1, 2 - and 4 bits per pixel depths which has opposite order of pixels in - byte order to bytes in long order. - config FB_SYS_FILLRECT tristate depends on FB @@ -545,15 +535,6 @@ config FB_VGA16 To compile this driver as a module, choose M here: the module will be called vga16fb. -config FB_BF54X_LQ043 - tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)" - depends on FB && (BF54x) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD - config FB_STI tristate "HP STI frame buffer device support" depends on FB && PARISC @@ -611,24 +592,6 @@ config FB_TGA Say Y if you have one of those. -config FB_UVESA - tristate "Userspace VESA VGA graphics support" - depends on FB && CONNECTOR - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - help - This is the frame buffer driver for generic VBE 2.0 compliant - graphic cards. It can also take advantage of VBE 3.0 features, - such as refresh rate adjustment. - - This driver generally provides more features than vesafb but - requires a userspace helper application called 'v86d'. See - for more information. - - If unsure, say N. - config FB_VESA bool "VESA VGA graphics support" depends on (FB = y) && X86 @@ -1662,7 +1625,7 @@ config FB_PMAG_BA config FB_PMAGB_B tristate "PMAGB-B TURBOchannel framebuffer support" - depends on FB && TC + depends on TC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1830,7 +1793,7 @@ config FB_PNX4008_DUM_RGB config FB_IBM_GXT4500 tristate "Framebuffer support for IBM GXT4500P adaptor" - depends on FB && PPC + depends on PPC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1870,6 +1833,10 @@ config FB_XILINX framebuffer. ML300 carries a 640*480 LCD display on the board, ML403 uses a standard DB15 VGA connector. +if ARCH_OMAP + source "drivers/video/omap/Kconfig" +endif + config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB @@ -1893,13 +1860,6 @@ config FB_VIRTUAL If unsure, say N. -if ARCH_OMAP - source "drivers/video/omap/Kconfig" -endif - -source "drivers/video/backlight/Kconfig" -source "drivers/video/display/Kconfig" - if VT source "drivers/video/console/Kconfig" endif @@ -1909,3 +1869,4 @@ if FB || SGI_NEWPORT_CONSOLE endif endmenu + diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 59d6c45a910d..06eec7b182b7 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -115,12 +115,10 @@ obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_FB_OMAP) += omap/ # Platform or fallback drivers go here -obj-$(CONFIG_FB_UVESA) += uvesafb.o obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_IMAC) += imacfb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o -obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/trunk/drivers/video/amifb.c b/trunk/drivers/video/amifb.c index f2e243c353f9..1a849b870bcc 100644 --- a/trunk/drivers/video/amifb.c +++ b/trunk/drivers/video/amifb.c @@ -52,7 +52,7 @@ #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/video/arcfb.c b/trunk/drivers/video/arcfb.c index c3431691c9f2..db15baca3f7b 100644 --- a/trunk/drivers/video/arcfb.c +++ b/trunk/drivers/video/arcfb.c @@ -48,7 +48,7 @@ #include #include -#include +#include #define floor8(a) (a&(~0x07)) #define floorXres(a,xres) (a&(~(xres - 1))) diff --git a/trunk/drivers/video/atafb.c b/trunk/drivers/video/atafb.c index 5d4fbaa53a6c..0038a0541c7e 100644 --- a/trunk/drivers/video/atafb.c +++ b/trunk/drivers/video/atafb.c @@ -58,7 +58,7 @@ #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/video/aty/ati_ids.h b/trunk/drivers/video/aty/ati_ids.h index 3e9d28bcd9f8..dca2eb8f2dde 100644 --- a/trunk/drivers/video/aty/ati_ids.h +++ b/trunk/drivers/video/aty/ati_ids.h @@ -188,7 +188,6 @@ #define PCI_CHIP_MACH64VT 0x5654 #define PCI_CHIP_MACH64VU 0x5655 #define PCI_CHIP_MACH64VV 0x5656 -#define PCI_CHIP_RC410_5A62 0x5A62 #define PCI_CHIP_RS300_5834 0x5834 #define PCI_CHIP_RS300_5835 0x5835 #define PCI_CHIP_RS300_5836 0x5836 diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index cbd3308b6690..cfcbe37d2d70 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/video/aty/atyfb.h b/trunk/drivers/video/aty/atyfb.h index 7691e73823d3..dc62f8e282b4 100644 --- a/trunk/drivers/video/aty/atyfb.h +++ b/trunk/drivers/video/aty/atyfb.h @@ -126,7 +126,6 @@ union aty_pll { */ struct atyfb_par { - u32 pseudo_palette[16]; struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index abe0c435a664..bc6f0096aa04 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -68,7 +68,7 @@ #include #include -#include +#include #include